OpenMesh
|
00001 /*===========================================================================*\ 00002 * * 00003 * OpenMesh * 00004 * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * 00005 * www.openmesh.org * 00006 * * 00007 *---------------------------------------------------------------------------* 00008 * This file is part of OpenMesh. * 00009 * * 00010 * OpenMesh is free software: you can redistribute it and/or modify * 00011 * it under the terms of the GNU Lesser General Public License as * 00012 * published by the Free Software Foundation, either version 3 of * 00013 * the License, or (at your option) any later version with the * 00014 * following exceptions: * 00015 * * 00016 * If other files instantiate templates or use macros * 00017 * or inline functions from this file, or you compile this file and * 00018 * link it with other files to produce an executable, this file does * 00019 * not by itself cause the resulting executable to be covered by the * 00020 * GNU Lesser General Public License. This exception does not however * 00021 * invalidate any other reasons why the executable file might be * 00022 * covered by the GNU Lesser General Public License. * 00023 * * 00024 * OpenMesh is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU Lesser General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU LesserGeneral Public * 00030 * License along with OpenMesh. If not, * 00031 * see <http://www.gnu.org/licenses/>. * 00032 * * 00033 \*===========================================================================*/ 00034 00035 /*===========================================================================*\ 00036 * * 00037 * $Revision: 362 $ * 00038 * $Date: 2011-01-26 10:21:12 +0100 (Mi, 26 Jan 2011) $ * 00039 * * 00040 \*===========================================================================*/ 00041 00042 #ifndef OPENMESH_PROPERTYCONTAINER 00043 #define OPENMESH_PROPERTYCONTAINER 00044 00045 // Use static casts when not debugging 00046 #ifdef NDEBUG 00047 #define OM_FORCE_STATIC_CAST 00048 #endif 00049 00050 #include <OpenMesh/Core/Utils/Property.hh> 00051 00052 //----------------------------------------------------------------------------- 00053 namespace OpenMesh 00054 { 00055 //== FORWARDDECLARATIONS ====================================================== 00056 class BaseKernel; 00057 00058 //== CLASS DEFINITION ========================================================= 00060 class PropertyContainer 00061 { 00062 public: 00063 00064 //-------------------------------------------------- constructor / destructor 00065 00066 PropertyContainer() {} 00067 virtual ~PropertyContainer() { std::for_each(properties_.begin(), properties_.end(), Delete()); } 00068 00069 00070 //------------------------------------------------------------- info / access 00071 00072 typedef std::vector<BaseProperty*> Properties; 00073 const Properties& properties() const { return properties_; } 00074 size_t size() const { return properties_.size(); } 00075 00076 00077 00078 //--------------------------------------------------------- copy / assignment 00079 00080 PropertyContainer(const PropertyContainer& _rhs) { operator=(_rhs); } 00081 00082 PropertyContainer& operator=(const PropertyContainer& _rhs) 00083 { 00084 // The assignment below relies on all previous BaseProperty* elements having been deleted 00085 std::for_each(properties_.begin(), properties_.end(), Delete()); 00086 properties_ = _rhs.properties_; 00087 Properties::iterator p_it=properties_.begin(), p_end=properties_.end(); 00088 for (; p_it!=p_end; ++p_it) 00089 if (*p_it) 00090 *p_it = (*p_it)->clone(); 00091 return *this; 00092 } 00093 00094 00095 00096 //--------------------------------------------------------- manage properties 00097 00098 template <class T> 00099 BasePropHandleT<T> add(const T&, const std::string& _name="<unknown>") 00100 { 00101 Properties::iterator p_it=properties_.begin(), p_end=properties_.end(); 00102 int idx=0; 00103 for ( ; p_it!=p_end && *p_it!=NULL; ++p_it, ++idx ) {}; 00104 if (p_it==p_end) properties_.push_back(NULL); 00105 properties_[idx] = new PropertyT<T>(_name); 00106 return BasePropHandleT<T>(idx); 00107 } 00108 00109 00110 template <class T> 00111 BasePropHandleT<T> handle(const T&, const std::string& _name) const 00112 { 00113 Properties::const_iterator p_it = properties_.begin(); 00114 for (int idx=0; p_it != properties_.end(); ++p_it, ++idx) 00115 { 00116 if (*p_it != NULL && 00117 (*p_it)->name() == _name //skip deleted properties 00118 // Skip type check 00119 #ifndef OM_FORCE_STATIC_CAST 00120 && dynamic_cast<PropertyT<T>*>(properties_[idx]) != NULL //check type 00121 #endif 00122 ) 00123 { 00124 return BasePropHandleT<T>(idx); 00125 } 00126 } 00127 return BasePropHandleT<T>(); 00128 } 00129 00130 BaseProperty* property( const std::string& _name ) const 00131 { 00132 Properties::const_iterator p_it = properties_.begin(); 00133 for (int idx=0; p_it != properties_.end(); ++p_it, ++idx) 00134 { 00135 if (*p_it != NULL && (*p_it)->name() == _name) //skip deleted properties 00136 { 00137 return *p_it; 00138 } 00139 } 00140 return NULL; 00141 } 00142 00143 template <class T> PropertyT<T>& property(BasePropHandleT<T> _h) 00144 { 00145 assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size()); 00146 assert(properties_[_h.idx()] != NULL); 00147 #ifdef OM_FORCE_STATIC_CAST 00148 return *static_cast <PropertyT<T>*> (properties_[_h.idx()]); 00149 #else 00150 PropertyT<T>* p = dynamic_cast<PropertyT<T>*>(properties_[_h.idx()]); 00151 assert(p != NULL); 00152 return *p; 00153 #endif 00154 } 00155 00156 00157 template <class T> const PropertyT<T>& property(BasePropHandleT<T> _h) const 00158 { 00159 assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size()); 00160 assert(properties_[_h.idx()] != NULL); 00161 #ifdef OM_FORCE_STATIC_CAST 00162 return *static_cast<PropertyT<T>*>(properties_[_h.idx()]); 00163 #else 00164 PropertyT<T>* p = dynamic_cast<PropertyT<T>*>(properties_[_h.idx()]); 00165 assert(p != NULL); 00166 return *p; 00167 #endif 00168 } 00169 00170 00171 template <class T> void remove(BasePropHandleT<T> _h) 00172 { 00173 assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size()); 00174 delete properties_[_h.idx()]; 00175 properties_[_h.idx()] = NULL; 00176 } 00177 00178 00179 void clear() 00180 { 00181 // Clear properties vector: 00182 // Replaced the old version with new one 00183 // which performs a swap to clear values and 00184 // deallocate memory. 00185 00186 // Old version (changed 22.07.09) { 00187 // std::for_each(properties_.begin(), properties_.end(), Delete()); 00188 // } 00189 00190 std::for_each(properties_.begin(), properties_.end(), ClearAll()); 00191 } 00192 00193 00194 //---------------------------------------------------- synchronize properties 00195 00196 void reserve(size_t _n) const { 00197 std::for_each(properties_.begin(), properties_.end(), Reserve(_n)); 00198 } 00199 00200 void resize(size_t _n) const { 00201 std::for_each(properties_.begin(), properties_.end(), Resize(_n)); 00202 } 00203 00204 void swap(size_t _i0, size_t _i1) const { 00205 std::for_each(properties_.begin(), properties_.end(), Swap(_i0, _i1)); 00206 } 00207 00208 00209 00210 protected: // generic add/get 00211 00212 size_t _add( BaseProperty* _bp ) 00213 { 00214 Properties::iterator p_it=properties_.begin(), p_end=properties_.end(); 00215 size_t idx=0; 00216 for (; p_it!=p_end && *p_it!=NULL; ++p_it, ++idx) {}; 00217 if (p_it==p_end) properties_.push_back(NULL); 00218 properties_[idx] = _bp; 00219 return idx; 00220 } 00221 00222 BaseProperty& _property( size_t _idx ) 00223 { 00224 assert( _idx < properties_.size()); 00225 assert( properties_[_idx] != NULL); 00226 BaseProperty *p = properties_[_idx]; 00227 assert( p != NULL ); 00228 return *p; 00229 } 00230 00231 const BaseProperty& _property( size_t _idx ) const 00232 { 00233 assert( _idx < properties_.size()); 00234 assert( properties_[_idx] != NULL); 00235 BaseProperty *p = properties_[_idx]; 00236 assert( p != NULL ); 00237 return *p; 00238 } 00239 00240 00241 typedef Properties::iterator iterator; 00242 typedef Properties::const_iterator const_iterator; 00243 iterator begin() { return properties_.begin(); } 00244 iterator end() { return properties_.end(); } 00245 const_iterator begin() const { return properties_.begin(); } 00246 const_iterator end() const { return properties_.end(); } 00247 00248 friend class BaseKernel; 00249 00250 private: 00251 00252 //-------------------------------------------------- synchronization functors 00253 00254 #ifndef DOXY_IGNORE_THIS 00255 struct Reserve 00256 { 00257 Reserve(size_t _n) : n_(_n) {} 00258 void operator()(BaseProperty* _p) const { if (_p) _p->reserve(n_); } 00259 size_t n_; 00260 }; 00261 00262 struct Resize 00263 { 00264 Resize(size_t _n) : n_(_n) {} 00265 void operator()(BaseProperty* _p) const { if (_p) _p->resize(n_); } 00266 size_t n_; 00267 }; 00268 00269 struct ClearAll 00270 { 00271 ClearAll() {} 00272 void operator()(BaseProperty* _p) const { if (_p) _p->clear(); } 00273 }; 00274 00275 struct Swap 00276 { 00277 Swap(size_t _i0, size_t _i1) : i0_(_i0), i1_(_i1) {} 00278 void operator()(BaseProperty* _p) const { if (_p) _p->swap(i0_, i1_); } 00279 size_t i0_, i1_; 00280 }; 00281 00282 struct Delete 00283 { 00284 Delete() {} 00285 void operator()(BaseProperty* _p) const { if (_p) delete _p; _p=NULL; } 00286 }; 00287 #endif 00288 00289 Properties properties_; 00290 }; 00291 00292 }//namespace OpenMesh 00293 00294 #endif//OPENMESH_PROPERTYCONTAINER 00295