1 /* ========================================================================= *
2  *                                                                           *
3  *                               OpenMesh                                    *
4  *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
5  *           Department of Computer Graphics and Multimedia                  *
6  *                          All rights reserved.                             *
7  *                            www.openmesh.org                               *
8  *                                                                           *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenMesh.                                            *
11  *---------------------------------------------------------------------------*
12  *                                                                           *
13  * Redistribution and use in source and binary forms, with or without        *
14  * modification, are permitted provided that the following conditions        *
15  * are met:                                                                  *
16  *                                                                           *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  *    this list of conditions and the following disclaimer.                  *
19  *                                                                           *
20  * 2. Redistributions in binary form must reproduce the above copyright      *
21  *    notice, this list of conditions and the following disclaimer in the    *
22  *    documentation and/or other materials provided with the distribution.   *
23  *                                                                           *
24  * 3. Neither the name of the copyright holder nor the names of its          *
25  *    contributors may be used to endorse or promote products derived from   *
26  *    this software without specific prior written permission.               *
27  *                                                                           *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
39  *                                                                           *
40  * ========================================================================= */
41 
42 
43 
44 #ifndef OPENMESH_PROPERTY_HH
45 #define OPENMESH_PROPERTY_HH
46 
47 
48 //== INCLUDES =================================================================
49 
50 
51 #include <OpenMesh/Core/System/config.h>
52 #include <OpenMesh/Core/Mesh/Handles.hh>
53 #include <OpenMesh/Core/Utils/BaseProperty.hh>
54 #include <vector>
55 #include <string>
56 #include <algorithm>
57 
58 
59 //== NAMESPACES ===============================================================
60 
61 namespace OpenMesh {
62 
63 //== CLASS DEFINITION =========================================================
64 
65 /** \class PropertyT Property.hh <OpenMesh/Core/Utils/PropertyT.hh>
66  *
67  *  \brief Default property class for any type T.
68  *
69  *  The default property class for any type T.
70  *
71  *  The property supports persistency if T is a "fundamental" type:
72  *  - integer fundamental types except bool:
73  *    char, short, int, long, long long (__int64 for MS VC++) and
74  *    their unsigned companions.
75  *  - float fundamentals except <tt>long double</tt>:
76  *    float, double
77  *  - %OpenMesh vector types
78  *
79  *  Persistency of non-fundamental types is supported if and only if a
80  *  specialization of struct IO::binary<> exists for the wanted type.
81  */
82 
83 // TODO: it might be possible to define Property using kind of a runtime info
84 // structure holding the size of T. Then reserve, swap, resize, etc can be written
85 // in pure malloc() style w/o virtual overhead. Template member function proved per
86 // element access to the properties, asserting dynamic_casts in debug
87 
88 template <class T>
89 class PropertyT : public BaseProperty
90 {
91 public:
92 
93   typedef T                                       Value;
94   typedef std::vector<T>                          vector_type;
95   typedef T                                       value_type;
96   typedef typename vector_type::reference         reference;
97   typedef typename vector_type::const_reference   const_reference;
98 
99 public:
100 
101   /// Default constructor
PropertyT(const std::string & _name="<unknown>",const std::string & _internal_type_name="<unknown>")102   explicit PropertyT(
103             const std::string& _name = "<unknown>",
104             const std::string& _internal_type_name = "<unknown>")
105   : BaseProperty(_name, _internal_type_name)
106   {}
107 
108   /// Copy constructor
PropertyT(const PropertyT & _rhs)109   PropertyT(const PropertyT & _rhs)
110       : BaseProperty( _rhs ), data_( _rhs.data_ ) {}
111 
112 public: // inherited from BaseProperty
113 
reserve(size_t _n)114   virtual void reserve(size_t _n) override { data_.reserve(_n);    }
resize(size_t _n)115   virtual void resize(size_t _n) override  { data_.resize(_n);     }
clear()116   virtual void clear() override  { data_.clear(); vector_type().swap(data_);    }
push_back()117   virtual void push_back() override        { data_.push_back(T()); }
swap(size_t _i0,size_t _i1)118   virtual void swap(size_t _i0, size_t _i1) override
119   { std::swap(data_[_i0], data_[_i1]); }
copy(size_t _i0,size_t _i1)120   virtual void copy(size_t _i0, size_t _i1) override
121   { data_[_i1] = data_[_i0]; }
122 
123 public:
124 
set_persistent(bool _yn)125   virtual void set_persistent( bool _yn ) override
126   { check_and_set_persistent<T>( _yn ); }
127 
n_elements() const128   virtual size_t       n_elements()   const override { return data_.size(); }
element_size() const129   virtual size_t       element_size() const override { return IO::size_of<T>(); }
130 
131 #ifndef DOXY_IGNORE_THIS
132   struct plus {
operator ()OpenMesh::PropertyT::plus133     size_t operator () ( size_t _b, const T& _v )
134     { return _b + IO::size_of<T>(_v); }
135   };
136 #endif
137 
size_of(void) const138   virtual size_t size_of(void) const override
139   {
140     if (element_size() != IO::UnknownSize)
141       return this->BaseProperty::size_of(n_elements());
142     return std::accumulate(data_.begin(), data_.end(), size_t(0), plus());
143   }
144 
size_of(size_t _n_elem) const145   virtual size_t size_of(size_t _n_elem) const override
146   { return this->BaseProperty::size_of(_n_elem); }
147 
store(std::ostream & _ostr,bool _swap) const148   virtual size_t store( std::ostream& _ostr, bool _swap ) const override
149   {
150     if ( IO::is_streamable<vector_type>() )
151       return IO::store(_ostr, data_, _swap );
152     size_t bytes = 0;
153     for (size_t i=0; i<n_elements(); ++i)
154       bytes += IO::store( _ostr, data_[i], _swap );
155     return bytes;
156   }
157 
restore(std::istream & _istr,bool _swap)158   virtual size_t restore( std::istream& _istr, bool _swap ) override
159   {
160     if ( IO::is_streamable<vector_type>() )
161       return IO::restore(_istr, data_, _swap );
162     size_t bytes = 0;
163     for (size_t i=0; i<n_elements(); ++i)
164       bytes += IO::restore( _istr, data_[i], _swap );
165     return bytes;
166   }
167 
168 public: // data access interface
169 
170   /// Get pointer to array (does not work for T==bool)
data() const171   const T* data() const {
172 
173     if( data_.empty() )
174       return 0;
175 
176     return &data_[0];
177   }
178 
179   /// Get reference to property vector (be careful, improper usage, e.g. resizing, may crash OpenMesh!!!)
data_vector()180   vector_type& data_vector() {
181     return data_;
182   }
183 
184   /// Const access to property vector
data_vector() const185   const vector_type& data_vector() const {
186     return data_;
187   }
188 
189   /// Access the i'th element. No range check is performed!
operator [](int _idx)190   reference operator[](int _idx)
191   {
192     assert( size_t(_idx) < data_.size() );
193     return data_[_idx];
194   }
195 
196   /// Const access to the i'th element. No range check is performed!
operator [](int _idx) const197   const_reference operator[](int _idx) const
198   {
199     assert( size_t(_idx) < data_.size());
200     return data_[_idx];
201   }
202 
203   /// Make a copy of self.
clone() const204   PropertyT<T>* clone() const override
205   {
206     PropertyT<T>* p = new PropertyT<T>( *this );
207     return p;
208   }
209 
210 
211 private:
212 
213   vector_type data_;
214 };
215 
216 //-----------------------------------------------------------------------------
217 
218 
219 /** Property specialization for bool type.
220 
221   The data will be stored as a bitset.
222  */
223 template <>
224 class PropertyT<bool> : public BaseProperty
225 {
226 public:
227 
228   typedef std::vector<bool>                       vector_type;
229   typedef bool                                    value_type;
230   typedef vector_type::reference                  reference;
231   typedef vector_type::const_reference            const_reference;
232 
233 public:
234 
PropertyT(const std::string & _name="<unknown>",const std::string & _internal_type_name="")235   explicit PropertyT(const std::string& _name = "<unknown>", const std::string& _internal_type_name="" )
236     : BaseProperty(_name, _internal_type_name)
237   { }
238 
239 public: // inherited from BaseProperty
240 
reserve(size_t _n)241   virtual void reserve(size_t _n) override { data_.reserve(_n);    }
resize(size_t _n)242   virtual void resize(size_t _n) override  { data_.resize(_n);     }
clear()243   virtual void clear() override  { data_.clear(); vector_type().swap(data_);    }
push_back()244   virtual void push_back() override        { data_.push_back(bool()); }
swap(size_t _i0,size_t _i1)245   virtual void swap(size_t _i0, size_t _i1) override
246   { bool t(data_[_i0]); data_[_i0]=data_[_i1]; data_[_i1]=t; }
copy(size_t _i0,size_t _i1)247   virtual void copy(size_t _i0, size_t _i1) override
248   { data_[_i1] = data_[_i0]; }
249 
250 public:
251 
set_persistent(bool _yn)252   virtual void set_persistent( bool _yn ) override
253   {
254     check_and_set_persistent<bool>( _yn );
255   }
256 
n_elements() const257   virtual size_t       n_elements()   const override { return data_.size();  }
element_size() const258   virtual size_t       element_size() const override { return UnknownSize;    }
size_of() const259   virtual size_t       size_of() const override      { return size_of( n_elements() ); }
size_of(size_t _n_elem) const260   virtual size_t       size_of(size_t _n_elem) const override
261   {
262     return _n_elem / 8 + ((_n_elem % 8)!=0);
263   }
264 
store(std::ostream & _ostr,bool) const265   size_t store( std::ostream& _ostr, bool /* _swap */ ) const override
266   {
267     size_t bytes = 0;
268 
269     size_t N = data_.size() / 8;
270     size_t R = data_.size() % 8;
271 
272     size_t        idx;  // element index
273     size_t        bidx;
274     unsigned char bits; // bitset
275 
276     for (bidx=idx=0; idx < N; ++idx, bidx+=8)
277     {
278       bits = static_cast<unsigned char>(data_[bidx])
279         | (static_cast<unsigned char>(data_[bidx+1]) << 1)
280         | (static_cast<unsigned char>(data_[bidx+2]) << 2)
281         | (static_cast<unsigned char>(data_[bidx+3]) << 3)
282         | (static_cast<unsigned char>(data_[bidx+4]) << 4)
283         | (static_cast<unsigned char>(data_[bidx+5]) << 5)
284         | (static_cast<unsigned char>(data_[bidx+6]) << 6)
285         | (static_cast<unsigned char>(data_[bidx+7]) << 7);
286       _ostr << bits;
287     }
288     bytes = N;
289 
290     if (R)
291     {
292       bits = 0;
293       for (idx=0; idx < R; ++idx)
294         bits |= static_cast<unsigned char>(data_[bidx+idx]) << idx;
295       _ostr << bits;
296       ++bytes;
297     }
298 
299     assert( bytes == size_of() );
300 
301     return bytes;
302   }
303 
restore(std::istream & _istr,bool)304   size_t restore( std::istream& _istr, bool /* _swap */ ) override
305   {
306     size_t bytes = 0;
307 
308     size_t N = data_.size() / 8;
309     size_t R = data_.size() % 8;
310 
311     size_t        idx;  // element index
312     size_t        bidx; //
313     unsigned char bits; // bitset
314 
315     for (bidx=idx=0; idx < N; ++idx, bidx+=8)
316     {
317       _istr >> bits;
318       data_[bidx+0] = (bits & 0x01) != 0;
319       data_[bidx+1] = (bits & 0x02) != 0;
320       data_[bidx+2] = (bits & 0x04) != 0;
321       data_[bidx+3] = (bits & 0x08) != 0;
322       data_[bidx+4] = (bits & 0x10) != 0;
323       data_[bidx+5] = (bits & 0x20) != 0;
324       data_[bidx+6] = (bits & 0x40) != 0;
325       data_[bidx+7] = (bits & 0x80) != 0;
326     }
327     bytes = N;
328 
329     if (R)
330     {
331       _istr >> bits;
332       for (idx=0; idx < R; ++idx)
333         data_[bidx+idx] = (bits & (1<<idx)) != 0;
334       ++bytes;
335     }
336 
337     return bytes;
338   }
339 
340 
341 public:
342 
343   /// Get reference to property vector (be careful, improper usage, e.g. resizing, may crash OpenMesh!!!)
data_vector()344   vector_type& data_vector() {
345     return data_;
346   }
347 
348   /// Const access to property vector
data_vector() const349   const vector_type& data_vector() const {
350     return data_;
351   }
352 
353   /// Access the i'th element. No range check is performed!
operator [](int _idx)354   reference operator[](int _idx)
355   {
356     assert( size_t(_idx) < data_.size() );
357     return data_[_idx];
358   }
359 
360   /// Const access to the i'th element. No range check is performed!
operator [](int _idx) const361   const_reference operator[](int _idx) const
362   {
363     assert( size_t(_idx) < data_.size());
364     return data_[_idx];
365   }
366 
367   /// Make a copy of self.
clone() const368   PropertyT<bool>* clone() const override
369   {
370     PropertyT<bool>* p = new PropertyT<bool>( *this );
371     return p;
372   }
373 
374 
375 private:
376 
377   vector_type data_;
378 };
379 
380 
381 //-----------------------------------------------------------------------------
382 
383 
384 /** Property specialization for std::string type.
385 */
386 template <>
387 class PropertyT<std::string> : public BaseProperty
388 {
389 public:
390 
391   typedef std::string                             Value;
392   typedef std::vector<std::string>                vector_type;
393   typedef std::string                             value_type;
394   typedef vector_type::reference                  reference;
395   typedef vector_type::const_reference            const_reference;
396 
397 public:
398 
PropertyT(const std::string & _name="<unknown>",const std::string & _internal_type_name="")399   explicit PropertyT(const std::string& _name = "<unknown>", const std::string& _internal_type_name="" )
400     : BaseProperty(_name, _internal_type_name)
401   { }
402 
403 public: // inherited from BaseProperty
404 
reserve(size_t _n)405   virtual void reserve(size_t _n) override { data_.reserve(_n);    }
resize(size_t _n)406   virtual void resize(size_t _n) override  { data_.resize(_n);     }
clear()407   virtual void clear() override  { data_.clear(); vector_type().swap(data_);    }
push_back()408   virtual void push_back() override        { data_.push_back(std::string()); }
swap(size_t _i0,size_t _i1)409   virtual void swap(size_t _i0, size_t _i1) override {
410     std::swap(data_[_i0], data_[_i1]);
411   }
copy(size_t _i0,size_t _i1)412   virtual void copy(size_t _i0, size_t _i1) override
413   { data_[_i1] = data_[_i0]; }
414 
415 public:
416 
set_persistent(bool _yn)417   virtual void set_persistent( bool _yn ) override
418   { check_and_set_persistent<std::string>( _yn ); }
419 
n_elements() const420   virtual size_t       n_elements()   const override { return data_.size();  }
element_size() const421   virtual size_t       element_size() const override { return UnknownSize;    }
size_of() const422   virtual size_t       size_of() const override
423   { return IO::size_of( data_ ); }
424 
size_of(size_t) const425   virtual size_t       size_of(size_t /* _n_elem */) const override
426   { return UnknownSize; }
427 
428   /// Store self as one binary block. Max. length of a string is 65535 bytes.
store(std::ostream & _ostr,bool _swap) const429   size_t store( std::ostream& _ostr, bool _swap ) const override
430   { return IO::store( _ostr, data_, _swap ); }
431 
restore(std::istream & _istr,bool _swap)432   size_t restore( std::istream& _istr, bool _swap ) override
433   { return IO::restore( _istr, data_, _swap ); }
434 
435 public:
436 
data() const437   const value_type* data() const {
438       if( data_.empty() )
439 	  return nullptr;
440 
441       return (value_type*) &data_[0];
442   }
443 
444   /// Access the i'th element. No range check is performed!
operator [](int _idx)445   reference operator[](int _idx) {
446     assert( size_t(_idx) < data_.size());
447     return ((value_type*) &data_[0])[_idx];
448   }
449 
450   /// Const access the i'th element. No range check is performed!
operator [](int _idx) const451   const_reference operator[](int _idx) const {
452     assert( size_t(_idx) < data_.size());
453     return ((value_type*) &data_[0])[_idx];
454   }
455 
clone() const456   PropertyT<value_type>* clone() const override {
457     PropertyT<value_type>* p = new PropertyT<value_type>( *this );
458     return p;
459   }
460 private:
461 
462   vector_type data_;
463 
464 };
465 
466 /// Base property handle.
467 template <class T>
468 struct BasePropHandleT : public BaseHandle
469 {
470   typedef T                                       Value;
471   typedef std::vector<T>                          vector_type;
472   typedef T                                       value_type;
473   typedef typename vector_type::reference         reference;
474   typedef typename vector_type::const_reference   const_reference;
475 
BasePropHandleTOpenMesh::BasePropHandleT476   explicit BasePropHandleT(int _idx=-1) : BaseHandle(_idx) {}
477 };
478 
479 
480 /** \ingroup mesh_property_handle_group
481  *  Handle representing a vertex property
482  */
483 template <class T>
484 struct VPropHandleT : public BasePropHandleT<T>
485 {
486   typedef T                       Value;
487   typedef T                       value_type;
488   typedef VertexHandle            Handle;
489 
VPropHandleTOpenMesh::VPropHandleT490   explicit VPropHandleT(int _idx=-1) : BasePropHandleT<T>(_idx) {}
VPropHandleTOpenMesh::VPropHandleT491   explicit VPropHandleT(const BasePropHandleT<T>& _b) : BasePropHandleT<T>(_b) {}
492 };
493 
494 
495 /** \ingroup mesh_property_handle_group
496  *  Handle representing a halfedge property
497  */
498 template <class T>
499 struct HPropHandleT : public BasePropHandleT<T>
500 {
501   typedef T                       Value;
502   typedef T                       value_type;
503   typedef HalfedgeHandle          Handle;
504 
HPropHandleTOpenMesh::HPropHandleT505   explicit HPropHandleT(int _idx=-1) : BasePropHandleT<T>(_idx) {}
HPropHandleTOpenMesh::HPropHandleT506   explicit HPropHandleT(const BasePropHandleT<T>& _b) : BasePropHandleT<T>(_b) {}
507 };
508 
509 
510 /** \ingroup mesh_property_handle_group
511  *  Handle representing an edge property
512  */
513 template <class T>
514 struct EPropHandleT : public BasePropHandleT<T>
515 {
516   typedef T                       Value;
517   typedef T                       value_type;
518   typedef EdgeHandle              Handle;
519 
EPropHandleTOpenMesh::EPropHandleT520   explicit EPropHandleT(int _idx=-1) : BasePropHandleT<T>(_idx) {}
EPropHandleTOpenMesh::EPropHandleT521   explicit EPropHandleT(const BasePropHandleT<T>& _b) : BasePropHandleT<T>(_b) {}
522 };
523 
524 
525 /** \ingroup mesh_property_handle_group
526  *  Handle representing a face property
527  */
528 template <class T>
529 struct FPropHandleT : public BasePropHandleT<T>
530 {
531   typedef T                       Value;
532   typedef T                       value_type;
533   typedef FaceHandle              Handle;
534 
FPropHandleTOpenMesh::FPropHandleT535   explicit FPropHandleT(int _idx=-1) : BasePropHandleT<T>(_idx) {}
FPropHandleTOpenMesh::FPropHandleT536   explicit FPropHandleT(const BasePropHandleT<T>& _b) : BasePropHandleT<T>(_b) {}
537 };
538 
539 
540 /** \ingroup mesh_property_handle_group
541  *  Handle representing a mesh property
542  */
543 template <class T>
544 struct MPropHandleT : public BasePropHandleT<T>
545 {
546   typedef T                       Value;
547   typedef T                       value_type;
548   typedef MeshHandle              Handle;
549 
MPropHandleTOpenMesh::MPropHandleT550   explicit MPropHandleT(int _idx=-1) : BasePropHandleT<T>(_idx) {}
MPropHandleTOpenMesh::MPropHandleT551   explicit MPropHandleT(const BasePropHandleT<T>& _b) : BasePropHandleT<T>(_b) {}
552 };
553 
554 template <typename HandleT>
555 struct PropHandle;
556 
557 template <>
558 struct PropHandle<VertexHandle> {
559   template <typename T>
560   using type = VPropHandleT<T>;
561 };
562 
563 template <>
564 struct PropHandle<HalfedgeHandle> {
565   template <typename T>
566   using type = HPropHandleT<T>;
567 };
568 
569 template <>
570 struct PropHandle<EdgeHandle> {
571   template <typename T>
572   using type = EPropHandleT<T>;
573 };
574 
575 template <>
576 struct PropHandle<FaceHandle> {
577   template <typename T>
578   using type = FPropHandleT<T>;
579 };
580 
581 } // namespace OpenMesh
582 //=============================================================================
583 #endif // OPENMESH_PROPERTY_HH defined
584 //=============================================================================
585