OpenMesh
OpenMesh/Core/Utils/PropertyContainer.hh
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines