Graphite Version 3
An experimental 3D geometry processing program
Loading...
Searching...
No Matches
attributes.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40
41#ifndef GEOGRAM_BASIC_ATTRIBUTES
42#define GEOGRAM_BASIC_ATTRIBUTES
43
50#include <geogram/basic/logger.h>
51
52#include <map>
53#include <typeinfo>
54#include <set>
55#include <type_traits>
56
62namespace GEO {
63
64 class AttributeStore;
65
70 class GEOGRAM_API AttributeStoreObserver {
71 public:
72
77 base_addr_(nullptr), size_(0), dimension_(0),
78 disconnected_(false) {
79 }
80
88 void notify(
89 Memory::pointer base_addr, index_t size, index_t dim
90 ) {
91 base_addr_ = base_addr;
92 size_ = size;
93 dimension_ = dim;
94 }
95
100 index_t size() const {
101 return size_;
102 }
103
109 return dimension_;
110 }
111
119 return size_ * dimension_;
120 }
121
127 return base_addr_;
128 }
129
135
141
149 void disconnect() {
150 base_addr_ = nullptr;
151 size_ = 0;
152 dimension_ = 0;
153 disconnected_ = true;
154 }
155
162 bool disconnected() const {
163 return disconnected_;
164 }
165
166 protected:
167 Memory::pointer base_addr_;
168 index_t size_;
169 index_t dimension_;
170 bool disconnected_;
171 };
172
173
174 /*********************************************************************/
175
176
181 class GEOGRAM_API AttributeStoreCreator : public Counted {
182 public:
183
188
195
203 virtual bool elements_are_trivially_copyable() const = 0;
204
205 private:
206 std::string element_type_name_;
207 std::string element_typeid_name_;
208 };
209
215
221 class GEOGRAM_API AttributeStore {
222 public:
232 AttributeStore(size_t elemsize, index_t dim=1);
233
238
239
250 const std::string& type_name
251 ) const = 0;
252
258 virtual std::string element_typeid_name() const = 0;
259
267 virtual std::string user_element_typeid_name() const = 0;
268
273 index_t size() const {
274 return cached_size_;
275 }
276
283 return cached_capacity_;
284 }
285
290 virtual void resize(index_t new_size) = 0;
291
297 virtual void reserve(index_t new_capacity) = 0;
298
304 virtual void clear(bool keep_memory = false) = 0;
305
311 bool has_observers() const {
312 return !observers_.empty();
313 }
314
321 return dimension_;
322 }
323
333 virtual void redim(index_t dim) = 0;
334
335
351 virtual void apply_permutation(
352 const vector<index_t>& permutation
353 );
354
355
371 virtual void compress(const vector<index_t>& old2new);
372
377 virtual void zero();
378
384 virtual AttributeStore* clone() const = 0;
385
386
392 void copy_item(index_t to, index_t from) {
393 geo_debug_assert(from < cached_size_);
394 geo_debug_assert(to < cached_size_);
395 size_t item_size = element_size_ * dimension_;
396 if(lifecycle_.is_null()) {
397 Memory::copy(
398 cached_base_addr_+to*item_size,
399 cached_base_addr_+from*item_size,
400 item_size
401 );
402 } else {
403 lifecycle_->assign(
404 cached_base_addr_+to*item_size,
405 cached_base_addr_+from*item_size
406 );
407 }
408 }
409
415 geo_debug_assert(to < cached_size_);
416 size_t item_size = element_size_ * dimension_;
417 if(lifecycle_.is_null()) {
418 Memory::clear(
419 cached_base_addr_+to*item_size,
420 item_size
421 );
422 } else {
423 lifecycle_->reset(cached_base_addr_+to*item_size);
424 }
425 }
426
434 virtual void scale_item(index_t to, double s);
435
444 virtual void madd_item(index_t to, double s, index_t from);
445
451
456 void* data() {
457 return cached_base_addr_;
458 }
459
464 const void* data() const {
465 return cached_base_addr_;
466 }
467
472 size_t element_size() const {
473 return element_size_;
474 }
475
485 const std::string& element_type_name
486 ) {
487 return (
488 type_name_to_creator_.find(element_type_name) !=
489 type_name_to_creator_.end()
490 );
491 }
492
502 const std::string& element_typeid_name
503 ) {
504 return (
505 typeid_name_to_type_name_.find(element_typeid_name) !=
506 typeid_name_to_type_name_.end()
507 );
508 }
509
520 const std::string& element_type_name
521 ) {
522 geo_debug_assert(element_type_name_is_known(element_type_name));
523 return (
524 type_name_to_creator_[
525 element_type_name
526 ]->elements_are_trivially_copyable()
527 );
528 }
529
540 const std::string& element_typeid_name
541 ) {
542 geo_debug_assert(element_typeid_name_is_known(element_typeid_name));
543 std::string element_type_name =
544 typeid_name_to_type_name_[element_typeid_name];
545 return element_by_type_name_is_trivially_copyable(element_type_name);
546 }
547
555 const std::string& element_type_name,
556 index_t dimension
557 ) {
558 geo_assert(element_type_name_is_known(element_type_name));
559 return type_name_to_creator_[element_type_name]->
560 create_attribute_store(dimension);
561 }
562
571 const std::string& element_typeid_name
572 ) {
573 geo_assert(element_typeid_name_is_known(element_typeid_name));
574 return typeid_name_to_type_name_[element_typeid_name];
575 }
576
586 const std::string& element_type_name
587 ) {
588 geo_assert(element_type_name_is_known(element_type_name));
589 return type_name_to_typeid_name_[element_type_name];
590 }
591
603 AttributeStoreCreator* creator,
604 const std::string& element_type_name,
605 const std::string& element_typeid_name
606 );
607
616 return lifecycle_;
617 }
618
619 protected:
620
627 const vector<index_t>& permutation
628 );
629
638 virtual void notify(
639 Memory::pointer base_addr, index_t size, index_t dim
640 );
641
651
660
661
662 protected:
663 size_t element_size_;
664 index_t dimension_;
665 Memory::pointer cached_base_addr_;
666 index_t cached_size_;
667 index_t cached_capacity_;
668 LifeCycle_var lifecycle_;
669 std::set<AttributeStoreObserver*> observers_;
670 Process::spinlock lock_;
671
672 static std::map<std::string, AttributeStoreCreator_var>
673 type_name_to_creator_;
674
675 static std::map<std::string, std::string>
676 typeid_name_to_type_name_;
677
678 static std::map<std::string, std::string>
679 type_name_to_typeid_name_;
680
681 friend class AttributeStoreObserver;
682 };
683
684 /*********************************************************************/
685
692 template <class ST> class TypedAttributeStore : public AttributeStore {
693 public:
694
705 index_t dim=1, const std::type_info& user_type_info = typeid(ST)
706 ) :
707 AttributeStore(sizeof(ST),dim),
708 storage_type_(typeid(ST)),
709 user_type_(user_type_info) {
710 if(!std::is_trivially_copyable<ST>::value) {
711 lifecycle_ = new GenericLifeCycle<ST>();
712 }
713 }
714
715 void resize(index_t new_size) override {
716 store_.resize(new_size*dimension_);
717 notify(
718 store_.empty() ? nullptr : Memory::pointer(store_.data()),
719 new_size,
720 dimension_
721 );
722 }
723
724 void reserve(index_t new_capacity) override {
725 if(new_capacity > capacity()) {
726 store_.reserve(new_capacity*dimension_);
727 cached_capacity_ = new_capacity;
728 notify(
729 store_.empty() ? nullptr : Memory::pointer(store_.data()),
730 size(),
731 dimension_
732 );
733 }
734 }
735
736 void clear(bool keep_memory=false) override {
737 if(keep_memory) {
738 store_.resize(0);
739 } else {
740 store_.clear();
741 }
742 notify(nullptr, 0, dimension_);
743 }
744
745 void redim(index_t dim) override {
746 if(dim == dimension()) {
747 return;
748 }
749 vector<ST> new_store(size()*dim);
750 new_store.reserve(capacity()*dim);
751 index_t copy_dim = std::min(dim, dimension());
752 for(index_t i = 0; i < size(); ++i) {
753 for(index_t c = 0; c < copy_dim; ++c) {
754 new_store[dim * i + c] = store_[dimension_ * i + c];
755 }
756 }
757 store_.swap(new_store);
758 notify(
759 store_.empty() ? nullptr : Memory::pointer(store_.data()),
760 size(),
761 dim
762 );
763 }
764
765 bool elements_type_matches(const std::string& type_name) const override {
766 return (
767 type_name == storage_type_.name() ||
768 type_name == user_type_.name()
769 );
770 }
771
772 std::string element_typeid_name() const override {
773 return storage_type_.name();
774 }
775
776 std::string user_element_typeid_name() const override {
777 return user_type_.name();
778 }
779
780 AttributeStore* clone() const override {
782 new TypedAttributeStore<ST>(dimension(), user_type_);
783 result->resize(size());
784 result->store_ = store_;
785 result->lifecycle_ = lifecycle_;
786 return result;
787 }
788
789 vector<ST>& get_vector() {
790 return store_;
791 }
792
793 void scale_item(index_t to, double s) override {
794 geo_assert(to < size());
795 for(index_t i=0; i<dimension_; ++i) {
796 scale_value(store_[to*dimension_+i], s);
797 }
798 }
799
800 void madd_item(index_t to, double s, index_t from) override {
801 geo_assert(from < size());
802 geo_assert(to < size());
803 for(index_t i=0; i<dimension_; ++i) {
804 madd_value(
805 store_[to*dimension_+i], s, store_[from*dimension_+i]
806 );
807 }
808 }
809
810 protected:
811 void notify(
812 Memory::pointer base_addr, index_t size, index_t dim
813 ) override {
814 AttributeStore::notify(base_addr, size, dim);
815 geo_assert(size*dim <= store_.size());
816 }
817
818 template<class TT> static void scale_value(TT& to, double s) {
819 geo_argused(to);
820 geo_argused(s);
821 }
822
823 static void scale_value(uint8_t& to, double s) {
824 to = uint8_t(double(to)*s != 0.0);
825 }
826
827 static void scale_value(int32_t& to, double s) {
828 to = int32_t(double(to)*s);
829 }
830
831 static void scale_value(uint32_t& to, double s) {
832 to = uint32_t(double(to)*s);
833 }
834
835 static void scale_value(float& to, double s) {
836 to = float(double(to)*s);
837 }
838
839 static void scale_value(double& to, double s) {
840 to *= s;
841 }
842
843 template<class TT> static void madd_value(TT& to, double s, TT& from) {
844 geo_argused(to);
845 geo_argused(s);
846 geo_argused(from);
847 }
848
849 static void madd_value(uint8_t& to, double s, uint8_t& from) {
850 to = uint8_t(double(to) + s*double(from) != 0.0);
851 }
852
853 static void madd_value(int32_t& to, double s, int32_t& from) {
854 to = int32_t(double(to) + s*double(from));
855 }
856
857 static void madd_value(uint32_t& to, double s, uint32_t& from) {
858 to = uint32_t(double(to) + s*double(from));
859 }
860
861 static void madd_value(float& to, double s, float& from) {
862 to = float(double(to) + s*double(from));
863 }
864
865 static void madd_value(double& to, double s, double& from) {
866 to += s*from;
867 }
868
869 private:
870 vector<ST> store_;
871 const std::type_info& storage_type_;
872 const std::type_info& user_type_;
873 };
874
875 /*********************************************************************/
876
882 template <class UT, class ST=UT>
884 public:
889 return new TypedAttributeStore<ST>(dim,typeid(UT));
890 }
891
895 bool elements_are_trivially_copyable() const override {
896 return(std::is_trivially_copyable<ST>::value);
897 }
898 };
899
900 /*********************************************************************/
901
909 template <class UT, class ST=UT> class geo_register_attribute_type {
910 public:
920 geo_register_attribute_type(const std::string& type_name) {
923 type_name, typeid(UT).name()
924 );
925 if(type_name == "bool") {
927 type_name,
930 );
931 } else {
933 type_name,
934 read_ascii_attribute<UT>,
935 write_ascii_attribute<UT>
936 );
937 }
938 }
939 };
940
941 /*********************************************************************/
942
947 class GEOGRAM_API AttributesManager {
948 public:
953
954
959
965 index_t nb() const {
966 return index_t(attributes_.size());
967 }
968
975
982 index_t size() const {
983 return size_;
984 }
985
992 return capacity_;
993 }
994
1001 void resize(index_t new_size);
1002
1009 void reserve(index_t new_capacity);
1010
1019 void clear(bool keep_attributes, bool keep_memory = false);
1020
1021
1025 void zero();
1026
1035 void bind_attribute_store(const std::string& name, AttributeStore* as);
1036
1043 AttributeStore* find_attribute_store(const std::string& name);
1044
1052 const std::string& name
1053 ) const;
1054
1055
1062 bool is_defined(const std::string& name) const {
1063 return (find_attribute_store(name) != nullptr);
1064 }
1065
1071 void delete_attribute_store(const std::string& name);
1072
1079
1096 const vector<index_t>& permutation
1097 );
1098
1114 void compress(const vector<index_t>& old2new);
1115
1120 void copy(const AttributesManager& rhs);
1121
1122
1129 void copy_item(index_t to, index_t from);
1130
1137
1138
1144
1152 void scale_item(index_t to, double s);
1153
1162 void madd_item(index_t to, double s, index_t from);
1163
1173 const std::string& name, const std::string& new_name
1174 );
1175
1185 const std::string& old_name, const std::string& new_name
1186 );
1187
1188 private:
1196 AttributesManager(const AttributesManager& rhs) = delete;
1197
1205 const AttributesManager& operator=(const AttributesManager& rhs) = delete;
1206
1207 private:
1208 index_t size_;
1209 index_t capacity_;
1210 std::map<std::string, AttributeStore*> attributes_;
1211 } ;
1212
1213
1214 /*********************************************************************/
1215
1216
1223 template <class UT, class ST = UT>
1225 public:
1226
1231 manager_(nullptr),
1232 store_(nullptr),
1233 existed_already_(false) {
1234 }
1235
1245 AttributeBase(AttributesManager& manager, const std::string& name) :
1246 manager_(nullptr),
1247 store_(nullptr),
1248 existed_already_(false) {
1249 bind(manager, name);
1250 }
1251
1257 bool is_bound() const {
1258 return (store_ != nullptr && !disconnected_);
1259 }
1260
1268 bool existed_already() const {
1269 return existed_already_;
1270 }
1271
1276 void unbind() {
1278 // If the AttributesManager was destroyed before, do not
1279 // do anything. This can occur in Lua scripting when using
1280 // Attribute wrapper objects.
1281 if(!disconnected_) {
1282 unregister_me(store_);
1283 }
1284 manager_ = nullptr;
1285 store_ = nullptr;
1286 existed_already_ = false;
1287 }
1288
1298 void bind(AttributesManager& manager, const std::string& name) {
1299 geo_assert(!is_bound());
1300 manager_ = &manager;
1301 store_ = manager_->find_attribute_store(name);
1302 if(store_ == nullptr) {
1303 store_ = new TypedAttributeStore<ST>(1,typeid(UT));
1304 manager_->bind_attribute_store(name,store_);
1305 existed_already_ = false;
1306 } else {
1307 geo_assert(can_bind_to(store_));
1308 existed_already_ = true;
1309 }
1310 register_me(store_);
1311 }
1312
1313
1323 AttributesManager& manager, const std::string& name
1324 ) {
1325 geo_assert(!is_bound());
1326 manager_ = &manager;
1327 store_ = manager_->find_attribute_store(name);
1328 if(store_ != nullptr) {
1329 geo_assert(can_bind_to(store_));
1330 register_me(store_);
1331 existed_already_ = true;
1332 return true;
1333 }
1334 existed_already_ = false;
1335 return false;
1336 }
1337
1347 AttributesManager& manager, const std::string& name
1348 ) {
1349 if( is_bound() ) {
1350 unbind();
1351 }
1352 store_ = manager.find_attribute_store(name);
1353 if(store_ != nullptr) {
1354 existed_already_ = true;
1355 if(!can_bind_to(store_)) {
1356 store_ = nullptr;
1357 return false;
1358 }
1359 manager_ = &manager;
1360 register_me(store_);
1361 return true;
1362 }
1363 existed_already_ = false;
1364 return false;
1365 }
1366
1375 const std::string& name,
1377 ) {
1378 geo_assert(!is_bound());
1379 manager_ = &manager;
1380 geo_assert(manager_->find_attribute_store(name) == nullptr);
1381 store_ = new TypedAttributeStore<ST>(dimension,typeid(UT));
1382 manager_->bind_attribute_store(name,store_);
1383 register_me(store_);
1384 }
1385
1392 void destroy() {
1394 unregister_me(store_);
1395 manager_->delete_attribute_store(store_);
1396 store_ = nullptr;
1397 manager_ = nullptr;
1398 }
1399
1409 void redim(index_t new_dim) {
1411 store_->redim(new_dim);
1412 }
1413
1422 if(is_bound()) {
1423 unbind();
1424 }
1425 }
1426
1427
1435 static bool is_defined(
1436 AttributesManager& manager, const std::string& name,
1437 index_t dim = 0
1438 ) {
1440 return (
1441 store != nullptr &&
1442 can_bind_to(store) &&
1443 ((dim == 0) || (store->dimension() == dim))
1444 );
1445 }
1446
1451 index_t size() const {
1452 return size_;
1453 }
1454
1459 void zero() {
1461 store_->zero();
1462 }
1463
1474 return(
1475 dynamic_cast<TypedAttributeStore<ST>*>(store_) != nullptr
1476 );
1477 }
1478
1490 TypedAttributeStore<ST>* typed_store =
1491 dynamic_cast<TypedAttributeStore<ST>*>(store_);
1492 geo_assert(typed_store != nullptr);
1493 return typed_store->get_vector();
1494 }
1495
1502 const vector<ST>& get_vector() const {
1503 TypedAttributeStore<ST>* typed_store =
1504 dynamic_cast<TypedAttributeStore<ST>*>(store_);
1505 geo_assert(typed_store != nullptr);
1506 return typed_store->get_vector();
1507 }
1508
1514 return manager_;
1515 }
1516
1517 protected:
1518
1525 static bool can_bind_to(const AttributeStore* store) {
1526 return (
1527 store->elements_type_matches(typeid(UT).name()) ||
1528 store->elements_type_matches(typeid(ST).name())
1529 );
1530 }
1531
1532 protected:
1533 AttributesManager* manager_;
1534 AttributeStore* store_;
1535 bool existed_already_;
1536 } ;
1537
1538 /*********************************************************************/
1539
1546 template <class T> class Attribute : public AttributeBase<T> {
1547 public:
1549
1554 }
1555
1565 Attribute(AttributesManager& manager, const std::string& name) :
1566 superclass(manager, name) {
1567 }
1568
1577 return ((T*)(void*)superclass::base_addr_)[i];
1578 }
1579
1585 const T& operator[](index_t i) const {
1588 return ((const T*)(void*)superclass::base_addr_)[i];
1589 }
1590
1596 void fill(const T& val) {
1598 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1599 (*this)[i] = val;
1600 }
1601 }
1602
1609 void copy(const Attribute<T>& rhs) {
1610 geo_assert(rhs.size() == superclass::size());
1612 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1613 (*this)[i] = rhs[i];
1614 }
1615 }
1616
1621 T* data() {
1622 return (T*)AttributeStoreObserver::base_addr_;
1623 }
1624
1629 const T* data() const {
1630 return (const T*)AttributeStoreObserver::base_addr_;
1631 }
1632
1633
1634 private:
1638 Attribute(const Attribute<T>& rhs) = delete;
1642 Attribute<T>& operator=(const Attribute<T>& rhs) = delete;
1643 };
1644
1645 /*********************************************************************/
1646
1655 template <> class Attribute<bool> :
1656 public AttributeBase<bool,Numeric::uint8> {
1657 public:
1659
1660 Attribute() : superclass() {
1661 }
1662
1663 Attribute(AttributesManager& manager, const std::string& name) :
1664 superclass(manager,name) {
1665 }
1666
1667 class BoolAttributeAccessor;
1668
1673 class ConstBoolAttributeAccessor {
1674 public:
1679 const Attribute<bool>& attribute,
1680 index_t index
1681 ) :
1682 attribute_(&attribute),
1683 index_(index) {
1684 }
1685
1690 operator bool() const {
1691 return (attribute_->element(index_) != 0);
1692 }
1693
1694 private:
1695 const Attribute<bool>* attribute_;
1696 index_t index_;
1697
1698 friend class BoolAttributeAccessor;
1699 };
1700
1705 class BoolAttributeAccessor {
1706 public:
1711 Attribute<bool>& attribute,
1712 index_t index
1713 ) :
1714 attribute_(&attribute),
1715 index_(index) {
1716 }
1717
1722 operator bool() const {
1723 return (attribute_->element(index_) != 0);
1724 }
1725
1731 BoolAttributeAccessor(const BoolAttributeAccessor& rhs) {
1732 attribute_ = rhs.attribute_;
1733 index_ = rhs.index_;
1734 }
1735
1740 BoolAttributeAccessor& operator=(bool x) {
1741 attribute_->element(index_) = Numeric::uint8(x);
1742 return *this;
1743 }
1744
1750 BoolAttributeAccessor& operator=(
1751 const BoolAttributeAccessor& rhs
1752 ) {
1753 if(&rhs != this) {
1754 attribute_->element(index_) =
1755 rhs.attribute_->element(rhs.index_);
1756 }
1757 return *this;
1758 }
1759
1765 BoolAttributeAccessor& operator=(
1766 const ConstBoolAttributeAccessor& rhs
1767 ) {
1768 attribute_->element(index_) =
1769 rhs.attribute_->element(rhs.index_);
1770 return *this;
1771 }
1772
1773 private:
1774 Attribute<bool>* attribute_;
1775 index_t index_;
1776 };
1777
1778
1779 BoolAttributeAccessor operator[](index_t i) {
1780 return BoolAttributeAccessor(*this,i);
1781 }
1782
1783 ConstBoolAttributeAccessor operator[](index_t i) const {
1784 return ConstBoolAttributeAccessor(*this,i);
1785 }
1786
1792 void fill(bool val) {
1793 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1794 element(i) = Numeric::uint8(val);
1795 }
1796 }
1797
1804 void copy(const Attribute<bool>& rhs) {
1805 geo_assert(rhs.size() == superclass::size());
1807 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1808 element(i) = rhs.element(i);
1809 }
1810 }
1811
1812 protected:
1813
1814 friend class BoolAttributeAccessor;
1815 friend class ConstBoolAttributeAccessor;
1816
1824 return ((Numeric::uint8*)superclass::base_addr_)[i];
1825 }
1826
1834 return ((const Numeric::uint8*)superclass::base_addr_)[i];
1835 }
1836
1837 private:
1841 Attribute(const Attribute<bool>& rhs) = delete;
1845 Attribute<bool>& operator=(const Attribute<bool>& rhs) = delete;
1846 } ;
1847
1848 /***********************************************************/
1849
1854 class GEOGRAM_API ScalarAttributeAdapterBase :
1855 public AttributeStoreObserver {
1856
1857 public:
1862 ET_NONE=0,
1863 ET_UINT8=1,
1864 ET_INT8=2,
1865 ET_UINT32=3,
1866 ET_INT32=4,
1867 ET_FLOAT32=5,
1868 ET_FLOAT64=6,
1869 ET_VEC2=7,
1870 ET_VEC3=8
1871 };
1872
1873
1878 class Accessor {
1879 public:
1880 Accessor(
1881 ScalarAttributeAdapterBase& attribute,
1882 index_t index
1883 ) : attribute_(attribute), index_(index) {
1884 }
1885
1886 operator double() const {
1887 return attribute_.get_element_as_double(index_);
1888 }
1889
1890 void operator=(double x) {
1891 attribute_.set_element_as_double(index_, x);
1892 }
1893
1894 private:
1895 ScalarAttributeAdapterBase& attribute_;
1896 index_t index_;
1897 };
1898
1904 public:
1906 const ScalarAttributeAdapterBase& attribute,
1907 index_t index
1908 ) : attribute_(attribute), index_(index) {
1909 }
1910
1911 operator double() const {
1912 return attribute_.get_element_as_double(index_);
1913 }
1914
1915 private:
1916 const ScalarAttributeAdapterBase& attribute_;
1917 index_t index_;
1918 };
1919
1924 manager_(nullptr),
1925 store_(nullptr),
1926 element_type_(ET_NONE),
1927 element_index_(index_t(-1)) {
1928 }
1929
1940 const AttributesManager& manager, const std::string& name
1941 ) :
1942 manager_(nullptr),
1943 store_(nullptr) {
1944 bind_if_is_defined(manager, name);
1945 }
1946
1952 bool is_bound() const {
1953 return (store_ != nullptr);
1954 }
1955
1960 void unbind() {
1961 geo_assert(is_bound());
1962 unregister_me(const_cast<AttributeStore*>(store_));
1963 manager_ = nullptr;
1964 store_ = nullptr;
1965 element_type_ = ET_NONE;
1966 element_index_ = index_t(-1);
1967 }
1968
1979 const AttributesManager& manager, const std::string& name
1980 );
1981
1990 if(is_bound()) {
1991 unbind();
1992 }
1993 }
1994
2004 static bool is_defined(
2005 const AttributesManager& manager, const std::string& name
2006 );
2007
2012 index_t size() const {
2013 return (store_ == nullptr) ? 0 : store_->size();
2014 }
2015
2024 return element_type_;
2025 }
2026
2034 return element_index_;
2035 }
2036
2042 return store_;
2043 }
2044
2045
2053 static bool can_be_bound_to(const AttributeStore* store) {
2054 return element_type(store) != ET_NONE;
2055 }
2056
2065
2066 protected:
2075 static std::string attribute_base_name(const std::string& name);
2076
2085 static index_t attribute_element_index(const std::string& name);
2086
2095
2104 double result = 0.0;
2105 switch(element_type()) {
2106 case ET_UINT8:
2107 result = double(get_element<Numeric::uint8>(i));
2108 break;
2109 case ET_INT8:
2110 result = double(get_element<Numeric::int8>(i));
2111 break;
2112 case ET_UINT32:
2113 result = double(get_element<Numeric::uint32>(i));
2114 break;
2115 case ET_INT32:
2116 result = double(get_element<Numeric::int32>(i));
2117 break;
2118 case ET_FLOAT32:
2119 result = double(get_element<Numeric::float32>(i));
2120 break;
2121 case ET_FLOAT64:
2122 result = double(get_element<Numeric::float64>(i));
2123 break;
2124 case ET_VEC2:
2125 result = double(get_element<Numeric::float64>(i,2));
2126 break;
2127 case ET_VEC3:
2128 result = double(get_element<Numeric::float64>(i,3));
2129 break;
2130 case ET_NONE:
2132 }
2133 return result;
2134 }
2135
2144 template <class T> T get_element(index_t i,index_t multiplier=1) const {
2145 geo_debug_assert(is_bound());
2146 geo_debug_assert(i < size());
2147 return static_cast<const T*>(store_->data())[
2148 (i * store_->dimension() * multiplier) +
2149 element_index_
2150 ];
2151 }
2152
2159 double set_element_as_double(index_t i, double value) {
2160 double result = 0.0;
2161 switch(element_type()) {
2162 case ET_UINT8:
2163 set_element<Numeric::uint8>(Numeric::uint8(value), i);
2164 break;
2165 case ET_INT8:
2166 set_element<Numeric::int8>(Numeric::int8(value),i);
2167 break;
2168 case ET_UINT32:
2169 set_element<Numeric::uint32>(Numeric::uint32(value),i);
2170 break;
2171 case ET_INT32:
2172 set_element<Numeric::int32>(Numeric::int32(value),i);
2173 break;
2174 case ET_FLOAT32:
2175 set_element<Numeric::float32>(Numeric::float32(value),i);
2176 break;
2177 case ET_FLOAT64:
2178 set_element<Numeric::float64>(Numeric::float64(value),i);
2179 break;
2180 case ET_VEC2:
2181 set_element<Numeric::float64>(Numeric::float64(value),i,2);
2182 break;
2183 case ET_VEC3:
2184 set_element<Numeric::float64>(Numeric::float64(value),i,3);
2185 break;
2186 case ET_NONE:
2188 }
2189 return result;
2190 }
2191
2201 template <class T> void set_element(
2202 T value, index_t i, index_t multiplier=1
2203 ) const {
2204 geo_debug_assert(is_bound());
2205 geo_debug_assert(i < size());
2206 const_cast<T*>(static_cast<const T*>(store_->data()))[
2207 (i * store_->dimension() * multiplier) +
2208 element_index_
2209 ] = value;
2210 }
2211
2212 protected:
2213 const AttributesManager* manager_;
2214 const AttributeStore* store_;
2215 ElementType element_type_;
2216 index_t element_index_;
2217 };
2218
2219 /***********************************************************/
2220
2226 public:
2228 }
2229
2231 const AttributesManager& manager, const std::string& name
2232 ) : ScalarAttributeAdapterBase(manager, name) {
2233 }
2234
2243 return get_element_as_double(i);
2244 }
2245 };
2246
2247 /***********************************************************/
2248
2254 public:
2256 }
2257
2259 const AttributesManager& manager, const std::string& name
2260 ) : ScalarAttributeAdapterBase(manager, name) {
2261 }
2262
2263 Accessor operator[](index_t i) {
2264 return Accessor(*this, i);
2265 }
2266
2267 ConstAccessor operator[](index_t i) const {
2268 return ConstAccessor(*this, i);
2269 }
2270
2271 protected:
2272 };
2273
2274
2275}
2276
2277#endif
#define geo_assert_not_reached
Sets a non reachable point in the program.
Definition assert.h:177
#define geo_assert(x)
Verifies that a condition is met.
Definition assert.h:149
#define geo_debug_assert(x)
Verifies that a condition is met.
Definition assert.h:196
Base class for Attributes, that manipulates an attribute stored in an AttributesManager.
bool can_get_vector()
Tests whether get_vector() can be called on this Attribute.
void zero()
Sets all the elements of this Attribute to zero.
void bind(AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager.
AttributeBase(AttributesManager &manager, const std::string &name)
Creates or retrieves a persistent attribute attached to a given AttributesManager.
vector< ST > & get_vector()
Gets a reference to the internal vector<T> used to store the attribute.
bool bind_if_is_compatible(AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager if it already exists in the AttributesManager and types ...
bool is_bound() const
Tests whether an Attribute is bound.
void redim(index_t new_dim)
Sets the dimension.
static bool can_bind_to(const AttributeStore *store)
Tests whether this Attribute can be bound to an AttributeStore.
AttributeBase()
Creates an uninitialized (unbound) Attribute.
AttributesManager * manager() const
Gets the AttributesManager this Attribute is bound to.
void destroy()
Destroys this attribute in the AttributesManager.
static bool is_defined(AttributesManager &manager, const std::string &name, index_t dim=0)
Tests whether an attribute with the specified name and with corresponding type exists in an Attribute...
~AttributeBase()
Attribute destructor.
index_t size() const
Gets the size.
bool existed_already() const
Tests whether the latest bound attribute existed already.
void unbind()
Unbinds this Attribute.
const vector< ST > & get_vector() const
Gets a const reference to the internal vector<T> used to store the attribute.
bool bind_if_is_defined(AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager if it already exists in the AttributesManager.
void create_vector_attribute(AttributesManager &manager, const std::string &name, index_t dimension)
Creates and binds a new vector attribute.
Internal class for creating an AttributeStore from the type name of its elements.
Definition attributes.h:181
~AttributeStoreCreator() override
AttributeStoreCreator destructor.
virtual bool elements_are_trivially_copyable() const =0
Tests whether elements of this attribute can be trivially copyable.
virtual AttributeStore * create_attribute_store(index_t dimension)=0
Creates a new attribute store.
Base class for attributes. They are notified whenever the AttributeStore is modified.
Definition attributes.h:70
AttributeStoreObserver()
Creates a new uninitialied AttributeStore.
Definition attributes.h:76
void register_me(AttributeStore *store)
Registers this observer to an AttributeStore.
index_t size() const
Gets the size.
Definition attributes.h:100
void notify(Memory::pointer base_addr, index_t size, index_t dim)
Callback function, called by the AttributeStore whenever it is modified.
Definition attributes.h:88
index_t nb_elements() const
Gets the total number of elements.
Definition attributes.h:118
bool disconnected() const
Tests whether this AttributeStoreObserver was disconnected.
Definition attributes.h:162
void disconnect()
Disconnects this AttributeStoreObserver from its AttributeStore.
Definition attributes.h:149
void unregister_me(AttributeStore *store)
Unregisters this observer from an AttributeStore.
index_t dimension() const
Gets the dimension.
Definition attributes.h:108
Memory::pointer base_addr() const
Gets a pointer to the storage.
Definition attributes.h:126
Notifies a set of AttributeStoreObservers each time the stored array changes size and/or base address...
Definition attributes.h:221
void * data()
Gets a pointer to the stored data.
Definition attributes.h:456
static AttributeStore * create_attribute_store_by_element_type_name(const std::string &element_type_name, index_t dimension)
Creates an attribute store of a given type.
Definition attributes.h:554
bool has_observers() const
Tests whether observers listen to this AttributeStore.
Definition attributes.h:311
void zero_item(index_t to)
Sets an item to zero.
Definition attributes.h:414
virtual ~AttributeStore()
AttributeStore destructor.
static std::string element_typeid_name_by_element_type_name(const std::string &element_type_name)
Gets an element mangled type name from its C++ name.
Definition attributes.h:585
static void register_attribute_creator(AttributeStoreCreator *creator, const std::string &element_type_name, const std::string &element_typeid_name)
Registers a new element type.
index_t size() const
Gets the size.
Definition attributes.h:273
const void * data() const
Gets a pointer to the stored data.
Definition attributes.h:464
virtual void clear(bool keep_memory=false)=0
Resizes this AttributeStore to 0.
virtual void notify(Memory::pointer base_addr, index_t size, index_t dim)
If size or base address differ from the cached values, notify all the observers, and update the cache...
AttributeStore(size_t elemsize, index_t dim=1)
AttributeStore constructor.
index_t capacity() const
Gets the capacity.
Definition attributes.h:282
virtual void madd_item(index_t to, double s, index_t from)
Adds a scaled item to another item \detais item[to] += s * item[from].
static bool element_by_typeid_name_is_trivially_copyable(const std::string &element_typeid_name)
Tests whether an element type is trivially copyable.
Definition attributes.h:539
static bool element_type_name_is_known(const std::string &element_type_name)
Tests whether a given element type is registered in the system.
Definition attributes.h:484
void apply_permutation_with_lifecycle(const vector< index_t > &permutation)
implementation of apply_permutation() used when there is a lifecycle, that is, when attribute type is...
virtual void compress(const vector< index_t > &old2new)
Compresses the stored attributes, by applying an index mapping that fills-in the gaps.
LifeCycle * lifecycle() const
Gets the LifeCycle.
Definition attributes.h:615
virtual std::string element_typeid_name() const =0
Gets the typeid name of the element type stored in this AttributeStore.
void copy_item(index_t to, index_t from)
Copies an item.
Definition attributes.h:392
virtual AttributeStore * clone() const =0
Creates a new AttributeStore that is a carbon copy of this AttributeStore.
static bool element_typeid_name_is_known(const std::string &element_typeid_name)
Tests whether a given element type is registered in the system.
Definition attributes.h:501
virtual std::string user_element_typeid_name() const =0
Gets the user typeid name of the element type stored in this AttributeStore.
void register_observer(AttributeStoreObserver *observer)
Registers an observer.
virtual void apply_permutation(const vector< index_t > &permutation)
Applies a permutation to the stored attributes.
virtual void resize(index_t new_size)=0
Resizes this AttributeStore.
virtual void scale_item(index_t to, double s)
Scales an item.
void unregister_observer(AttributeStoreObserver *observer)
Unregisters an observer.
virtual void redim(index_t dim)=0
Sets the dimension.
index_t dimension() const
Gets the dimension.
Definition attributes.h:320
static std::string element_type_name_by_element_typeid_name(const std::string &element_typeid_name)
Gets an element type name from its mangled name.
Definition attributes.h:570
virtual bool elements_type_matches(const std::string &type_name) const =0
Tests whether this AttributeStore stores elements of a given type.
void swap_items(index_t i, index_t j)
Swaps two items.
static bool element_by_type_name_is_trivially_copyable(const std::string &element_type_name)
Tests whether an element type is trivially copyable.
Definition attributes.h:519
size_t element_size() const
Gets the element size.
Definition attributes.h:472
virtual void reserve(index_t new_capacity)=0
Reserves memory.
virtual void zero()
Zeroes all the memory associated with this AttributeStore.
BoolAttributeAccessor(Attribute< bool > &attribute, index_t index)
BoolAttributeAccessor constructor.
BoolAttributeAccessor & operator=(const BoolAttributeAccessor &rhs)
Copies a bool from another attribute.
BoolAttributeAccessor & operator=(const ConstBoolAttributeAccessor &rhs)
Copies a bool from another attribute.
BoolAttributeAccessor & operator=(bool x)
Assigns a bool to a BoolAttributeAccessor.
BoolAttributeAccessor(const BoolAttributeAccessor &rhs)
Copy-constructor.
ConstBoolAttributeAccessor(const Attribute< bool > &attribute, index_t index)
ConstBoolAttributeAccessor constructor.
Numeric::uint8 & element(index_t i)
Gets a modifiable element by index.
void fill(bool val)
Sets all the elements in this attribute to a specified value.
const Numeric::uint8 & element(index_t i) const
Gets an element by index.
void copy(const Attribute< bool > &rhs)
Copies all the values from another attribute.
Manages an attribute attached to a set of object.
Attribute(AttributesManager &manager, const std::string &name)
Creates or retrieves a persistent attribute attached to a given AttributesManager.
const T & operator[](index_t i) const
Gets an element by index.
Attribute()
Creates an uninitialized (unbound) Attribute.
T * data()
Gets the pointer to the data.
void fill(const T &val)
Sets all the elements in this attribute to a specified value.
const T * data() const
Gets the pointer to the data.
T & operator[](index_t i)
Gets a modifiable element by index.
void copy(const Attribute< T > &rhs)
Copies all the values from another attribute.
Manages a set of attributes attached to an object.
Definition attributes.h:947
void delete_attribute_store(AttributeStore *as)
Deletes an AttributeStore.
void compress(const vector< index_t > &old2new)
Compresses the stored attributes, by applying an index mapping that fills-in the gaps.
void zero_item(index_t to)
Sets an item to zero.
void copy(const AttributesManager &rhs)
Copies all the attributes from another AttributesManager.
AttributesManager()
Constructs a new empty AttributesManager.
index_t nb() const
Gets the number of attributes.
Definition attributes.h:965
bool rename_attribute(const std::string &old_name, const std::string &new_name)
Renames an attribute.
void scale_item(index_t to, double s)
Scales an item.
const AttributeStore * find_attribute_store(const std::string &name) const
Finds an AttributeStore by name.
void apply_permutation(const vector< index_t > &permutation)
Applies a permutation to the stored attributes.
AttributeStore * find_attribute_store(const std::string &name)
Finds an AttributeStore by name.
void bind_attribute_store(const std::string &name, AttributeStore *as)
Binds an AttributeStore with the specified name. Ownership of this AttributeStore is transferred to t...
void list_attribute_names(vector< std::string > &names) const
Gets the names of all the attributes in this AttributeStore.
~AttributesManager()
AttributesManager destructor.
void copy_item(index_t to, index_t from)
Copies all the attributes of an item into another one.
void madd_item(index_t to, double s, index_t from)
Adds a scaled item to another item \detais item[to] += s * item[from].
bool is_defined(const std::string &name) const
Tests whether an attribute is defined.
void swap_items(index_t i, index_t j)
Swaps all the attributes of two items.
index_t size() const
Gets the size.
Definition attributes.h:982
void clear(bool keep_attributes, bool keep_memory=false)
Clears this AttributesManager.
index_t capacity() const
Gets the capacity.
Definition attributes.h:991
void delete_attribute_store(const std::string &name)
Deletes an AttributeStore by name.
bool copy_attribute(const std::string &name, const std::string &new_name)
Copies an attribute.
void zero()
Zeroes all the attributes.
void reserve(index_t new_capacity)
Pre-allocates memory for a number of items.
void resize(index_t new_size)
Resizes all the attributes managed by this AttributesManager.
Base class for reference-counted objects.
Definition counted.h:71
Concrete implementation of LifeCycle.
Definition life_cycle.h:252
static void register_ascii_attribute_serializer(const std::string &type_name, AsciiAttributeReadSerializer read, AsciiAttributeWriteSerializer write)
Declares a new attribute type that can be read from and written to ascii files.
Manages the life cycle of an object.
Definition life_cycle.h:66
Readonly access to an attribute as a double regardless its type.
double operator[](index_t i)
Gets a property value.
Readwrite access to an attribute as a double regardless its type.
Accessor class used by ScalarAttributeAdapter to implement indexing operator.
Accessor class used by ScalarAttributeAdapter to implement indexing operator (const version).
Access to an attribute as a double regardless its type.
index_t element_index() const
Gets the element index.
T get_element(index_t i, index_t multiplier=1) const
Gets an element.
ElementType
Internal representation of the attribute.
static std::string attribute_base_name(const std::string &name)
Gets the base attribute name from a compound name.
void bind_if_is_defined(const AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager if it already exists in the AttributesManager.
bool is_bound() const
Tests whether an Attribute is bound.
static index_t nb_scalar_elements_per_item(const AttributeStore *store)
Gets the number of scalar components per item in an AttributeStore.
double get_element_as_double(index_t i) const
Gets an attribute value.
~ScalarAttributeAdapterBase()
ReadonlyScalarAttributeAdapterBase destructor.
static ElementType element_type(const AttributeStore *store)
Gets the element type stored in an AttributeStore.
const AttributeStore * attribute_store() const
Gets the AttributeStore.
ScalarAttributeAdapterBase()
ScalarAttributeAdapterBase constructor.
static bool can_be_bound_to(const AttributeStore *store)
Tests whether a ScalarAttributeAdapterBase can be bound to a given attribute store.
void unbind()
Unbinds this Attribute.
static bool is_defined(const AttributesManager &manager, const std::string &name)
Tests whether an attribute with the specified name and with a type that can be converted to double ex...
ScalarAttributeAdapterBase(const AttributesManager &manager, const std::string &name)
ScalarAttributeAdapterBase constructor.
double set_element_as_double(index_t i, double value)
Sets an attribute value.
void set_element(T value, index_t i, index_t multiplier=1) const
Sets an element.
static index_t attribute_element_index(const std::string &name)
Gets the base attribute name from a compound name.
index_t size() const
Gets the size.
ElementType element_type() const
Gets the internal representation of the elements.
A smart pointer with reference-counted copy semantics.
Implementation of AttributeStoreCreator for a specific type.
Definition attributes.h:883
AttributeStore * create_attribute_store(index_t dim) override
Creates a new attribute store.
Definition attributes.h:888
bool elements_are_trivially_copyable() const override
Tests whether elements of this attribute can be trivially copyable.
Definition attributes.h:895
Stores an array of elements of a given type, and notifies a set of AttributeStoreObservers each time ...
Definition attributes.h:692
AttributeStore * clone() const override
Creates a new AttributeStore that is a carbon copy of this AttributeStore.
Definition attributes.h:780
void madd_item(index_t to, double s, index_t from) override
Adds a scaled item to another item \detais item[to] += s * item[from].
Definition attributes.h:800
void resize(index_t new_size) override
Resizes this AttributeStore.
Definition attributes.h:715
TypedAttributeStore(index_t dim=1, const std::type_info &user_type_info=typeid(ST))
Creates a new empty attribute store.
Definition attributes.h:704
void reserve(index_t new_capacity) override
Reserves memory.
Definition attributes.h:724
bool elements_type_matches(const std::string &type_name) const override
Tests whether this AttributeStore stores elements of a given type.
Definition attributes.h:765
void clear(bool keep_memory=false) override
Resizes this AttributeStore to 0.
Definition attributes.h:736
std::string user_element_typeid_name() const override
Gets the user typeid name of the element type stored in this AttributeStore.
Definition attributes.h:776
void notify(Memory::pointer base_addr, index_t size, index_t dim) override
If size or base address differ from the cached values, notify all the observers, and update the cache...
Definition attributes.h:811
std::string element_typeid_name() const override
Gets the typeid name of the element type stored in this AttributeStore.
Definition attributes.h:772
void redim(index_t dim) override
Sets the dimension.
Definition attributes.h:745
void scale_item(index_t to, double s) override
Scales an item.
Definition attributes.h:793
Helper class to register new attribute types.
Definition attributes.h:909
geo_register_attribute_type(const std::string &type_name)
geo_register_attribute_type constructor
Definition attributes.h:920
Vector with aligned memory allocation.
Definition memory.h:702
T * data()
Gets a pointer to the array of elements.
Definition memory.h:848
index_t size() const
Gets the number of elements.
Definition memory.h:748
Common include file, providing basic definitions. Should be included before anything else by all head...
Functions to read and write structured files.
Implementation of generic object lifecycle service.
Types and functions for memory manipulation.
byte * pointer
Pointer to unsigned byte(s)
Definition memory.h:104
float float32
Definition numeric.h:148
uint8_t uint8
Definition numeric.h:136
int8_t int8
Definition numeric.h:124
double float64
Definition numeric.h:151
int32_t int32
Definition numeric.h:130
uint32_t uint32
Definition numeric.h:142
std::atomic_flag spinlock
A lightweight synchronization structure.
Global Vorpaline namespace.
void geo_argused(const T &)
Suppresses compiler warnings about unused parameters.
Definition argused.h:60
geo_index_t index_t
The type for storing and manipulating indices.
Definition numeric.h:330
SmartPointer< AttributeStoreCreator > AttributeStoreCreator_var
An automatic reference-counted pointer to an AttributeStoreCreator.
Definition attributes.h:214
bool read_ascii_attribute< bool >(FILE *file, Memory::pointer base_addr, index_t nb_elements)
Reads an ASCII attribute from a file.
Definition geofile.h:208
bool write_ascii_attribute< bool >(FILE *file, Memory::const_pointer base_addr, index_t nb_elements)
Writes an ASCII attribute to a file.
Definition geofile.h:232
Types and functions for numbers manipulation.
Function and classes for process manipulation.