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