Geogram Version 1.9.6-rc
A programming library of geometric algorithms
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
51#include <map>
52#include <typeinfo>
53#include <set>
54#include <type_traits>
55
61namespace GEO {
62
63 class AttributeStore;
64
69 class GEOGRAM_API AttributeStoreObserver {
70 public:
71
76 base_addr_(nullptr), size_(0), dimension_(0),
77 disconnected_(false) {
78 }
79
87 void notify(
88 Memory::pointer base_addr, index_t size, index_t dim
89 ) {
90 base_addr_ = base_addr;
91 size_ = size;
92 dimension_ = dim;
93 }
94
99 index_t size() const {
100 return size_;
101 }
102
108 return dimension_;
109 }
110
118 return size_ * dimension_;
119 }
120
126 return base_addr_;
127 }
128
134
140
148 void disconnect() {
149 base_addr_ = nullptr;
150 size_ = 0;
151 dimension_ = 0;
152 disconnected_ = true;
153 }
154
161 bool disconnected() const {
162 return disconnected_;
163 }
164
165 protected:
166 Memory::pointer base_addr_;
167 index_t size_;
168 index_t dimension_;
169 bool disconnected_;
170 };
171
172
173 /*********************************************************************/
174
175
180 class GEOGRAM_API AttributeStoreCreator : public Counted {
181 public:
182
187
194
195
196 private:
197 std::string element_type_name_;
198 std::string element_typeid_name_;
199 };
200
206
212 class GEOGRAM_API AttributeStore {
213 public:
223 AttributeStore(size_t elemsize, index_t dim=1);
224
229
230
241 const std::string& type_name
242 ) const = 0;
243
249 virtual std::string element_typeid_name() const = 0;
250
255 index_t size() const {
256 return cached_size_;
257 }
258
265 return cached_capacity_;
266 }
267
272 virtual void resize(index_t new_size) = 0;
273
279 virtual void reserve(index_t new_capacity) = 0;
280
286 virtual void clear(bool keep_memory = false) = 0;
287
293 bool has_observers() const {
294 return !observers_.empty();
295 }
296
303 return dimension_;
304 }
305
315 virtual void redim(index_t dim) = 0;
316
317
335 virtual void apply_permutation(
336 const vector<index_t>& permutation
337 );
338
356 virtual void compress(const vector<index_t>& old2new);
357
365 virtual void zero();
366
372 virtual AttributeStore* clone() const = 0;
373
374
380 void copy_item(index_t to, index_t from) {
381 geo_debug_assert(from < cached_size_);
382 geo_debug_assert(to < cached_size_);
383 size_t item_size = element_size_ * dimension_;
384 Memory::copy(
385 cached_base_addr_+to*item_size,
386 cached_base_addr_+from*item_size,
387 item_size
388 );
389 }
390
396 geo_debug_assert(to < cached_size_);
397 size_t item_size = element_size_ * dimension_;
398 Memory::clear(
399 cached_base_addr_+to*item_size,
400 item_size
401 );
402 }
403
411 virtual void scale_item(index_t to, double s);
412
421 virtual void madd_item(index_t to, double s, index_t from);
422
428
433 void* data() {
434 return cached_base_addr_;
435 }
436
441 const void* data() const {
442 return cached_base_addr_;
443 }
444
449 size_t element_size() const {
450 return element_size_;
451 }
452
462 const std::string& element_type_name
463 ) {
464 return (
465 type_name_to_creator_.find(element_type_name) !=
466 type_name_to_creator_.end()
467 );
468 }
469
479 const std::string& element_typeid_name
480 ) {
481 return (
482 typeid_name_to_type_name_.find(element_typeid_name) !=
483 typeid_name_to_type_name_.end()
484 );
485 }
486
494 const std::string& element_type_name,
495 index_t dimension
496 ) {
497 geo_assert(element_type_name_is_known(element_type_name));
498 return type_name_to_creator_[element_type_name]->
499 create_attribute_store(dimension);
500 }
501
510 const std::string& element_typeid_name
511 ) {
512 geo_assert(element_typeid_name_is_known(element_typeid_name));
513 return typeid_name_to_type_name_[element_typeid_name];
514 }
515
525 const std::string& element_type_name
526 ) {
527 geo_assert(element_type_name_is_known(element_type_name));
528 return type_name_to_typeid_name_[element_type_name];
529 }
530
542 AttributeStoreCreator* creator,
543 const std::string& element_type_name,
544 const std::string& element_typeid_name
545 ) {
546 if(element_type_name_is_known(element_type_name)) {
547 Logger::warn("Attributes") << element_type_name
548 << " already registered"
549 << std::endl;
550 if(element_typeid_name_is_known(element_typeid_name)) {
551 bool already_registered_attribute_has_same_type = (
552 type_name_to_typeid_name_[element_type_name] ==
553 element_typeid_name
554 );
555 geo_assert(already_registered_attribute_has_same_type);
556 }
557 }
558 type_name_to_creator_[element_type_name] = creator;
559 typeid_name_to_type_name_[element_typeid_name] = element_type_name;
560 type_name_to_typeid_name_[element_type_name] = element_typeid_name;
561 }
562
563 protected:
572 virtual void notify(
573 Memory::pointer base_addr, index_t size, index_t dim
574 );
575
585
594
595
596 protected:
597 size_t element_size_;
598 index_t dimension_;
599 Memory::pointer cached_base_addr_;
600 index_t cached_size_;
601 index_t cached_capacity_;
602 std::set<AttributeStoreObserver*> observers_;
603 Process::spinlock lock_;
604
605 static std::map<std::string, AttributeStoreCreator_var>
606 type_name_to_creator_;
607
608 static std::map<std::string, std::string>
609 typeid_name_to_type_name_;
610
611 static std::map<std::string, std::string>
612 type_name_to_typeid_name_;
613
614 friend class AttributeStoreObserver;
615 };
616
617 /*********************************************************************/
618
624 template <class T> class TypedAttributeStore : public AttributeStore {
625 public:
626
634 AttributeStore(sizeof(T),dim) {
635 }
636
637 void resize(index_t new_size) override {
638 store_.resize(new_size*dimension_);
639 notify(
640 store_.empty() ? nullptr : Memory::pointer(store_.data()),
641 new_size,
642 dimension_
643 );
644 }
645
646 void reserve(index_t new_capacity) override {
647 if(new_capacity > capacity()) {
648 store_.reserve(new_capacity*dimension_);
649 cached_capacity_ = new_capacity;
650 notify(
651 store_.empty() ? nullptr : Memory::pointer(store_.data()),
652 size(),
653 dimension_
654 );
655 }
656 }
657
658 void clear(bool keep_memory=false) override {
659 if(keep_memory) {
660 store_.resize(0);
661 } else {
662 store_.clear();
663 }
664 notify(nullptr, 0, dimension_);
665 }
666
667
668 void redim(index_t dim) override {
669 if(dim == dimension()) {
670 return;
671 }
672 vector<T> new_store(size()*dim);
673 new_store.reserve(capacity()*dim);
674 index_t copy_dim = std::min(dim, dimension());
675 for(index_t i = 0; i < size(); ++i) {
676 for(index_t c = 0; c < copy_dim; ++c) {
677 new_store[dim * i + c] = store_[dimension_ * i + c];
678 }
679 }
680 store_.swap(new_store);
681 notify(
682 store_.empty() ? nullptr : Memory::pointer(store_.data()),
683 size(),
684 dim
685 );
686 }
687
688 bool elements_type_matches(const std::string& type_name) const override {
689 return type_name == typeid(T).name();
690 }
691
692 std::string element_typeid_name() const override {
693 return typeid(T).name();
694 }
695
696 AttributeStore* clone() const override {
697 TypedAttributeStore<T>* result =
699 result->resize(size());
700 result->store_ = store_;
701 return result;
702 }
703
704 vector<T>& get_vector() {
705 return store_;
706 }
707
708 void scale_item(index_t to, double s) override {
709 geo_assert(to < size());
710 for(index_t i=0; i<dimension_; ++i) {
711 scale_value(store_[to*dimension_+i], s);
712 }
713 }
714
715 void madd_item(index_t to, double s, index_t from) override {
716 geo_assert(from < size());
717 geo_assert(to < size());
718 for(index_t i=0; i<dimension_; ++i) {
719 madd_value(
720 store_[to*dimension_+i], s, store_[from*dimension_+i]
721 );
722 }
723 }
724
725 protected:
726 void notify(
727 Memory::pointer base_addr, index_t size, index_t dim
728 ) override {
729 AttributeStore::notify(base_addr, size, dim);
730 geo_assert(size*dim <= store_.size());
731 }
732
733 template<class TT> static void scale_value(TT& to, double s) {
734 geo_argused(to);
735 geo_argused(s);
736 }
737
738 static void scale_value(uint8_t& to, double s) {
739 to = uint8_t(double(to)*s != 0.0);
740 }
741
742 static void scale_value(int32_t& to, double s) {
743 to = int32_t(double(to)*s);
744 }
745
746 static void scale_value(uint32_t& to, double s) {
747 to = uint32_t(double(to)*s);
748 }
749
750 static void scale_value(float& to, double s) {
751 to = float(double(to)*s);
752 }
753
754 static void scale_value(double& to, double s) {
755 to *= s;
756 }
757
758 template<class TT> static void madd_value(TT& to, double s, TT& from) {
759 geo_argused(to);
760 geo_argused(s);
761 geo_argused(from);
762 }
763
764 static void madd_value(uint8_t& to, double s, uint8_t& from) {
765 to = uint8_t(double(to) + s*double(from) != 0.0);
766 }
767
768 static void madd_value(int32_t& to, double s, int32_t& from) {
769 to = int32_t(double(to) + s*double(from));
770 }
771
772 static void madd_value(uint32_t& to, double s, uint32_t& from) {
773 to = uint32_t(double(to) + s*double(from));
774 }
775
776 static void madd_value(float& to, double s, float& from) {
777 to = float(double(to) + s*double(from));
778 }
779
780 static void madd_value(double& to, double s, double& from) {
781 to += s*from;
782 }
783
784
785 private:
786 vector<T> store_;
787 };
788
789 /*********************************************************************/
790
795 template <class T>
797 public:
802 return new TypedAttributeStore<T>(dim);
803 }
804 };
805
806 /*********************************************************************/
807
812 template <class T> class geo_register_attribute_type {
813 public:
823 geo_register_attribute_type(const std::string& type_name) {
825 new TypedAttributeStoreCreator<T>, type_name, typeid(T).name()
826 );
827 if(type_name == "bool") {
829 type_name,
832 );
833 } else {
835 type_name,
836 read_ascii_attribute<T>,
837 write_ascii_attribute<T>
838 );
839 }
840 }
841 };
842
843 /*********************************************************************/
844
849 class GEOGRAM_API AttributesManager {
850 public:
855
856
861
867 index_t nb() const {
868 return index_t(attributes_.size());
869 }
870
877
884 index_t size() const {
885 return size_;
886 }
887
894 return capacity_;
895 }
896
903 void resize(index_t new_size);
904
911 void reserve(index_t new_capacity);
912
921 void clear(bool keep_attributes, bool keep_memory = false);
922
923
927 void zero();
928
937 void bind_attribute_store(const std::string& name, AttributeStore* as);
938
945 AttributeStore* find_attribute_store(const std::string& name);
946
954 const std::string& name
955 ) const;
956
957
964 bool is_defined(const std::string& name) const {
965 return (find_attribute_store(name) != nullptr);
966 }
967
973 void delete_attribute_store(const std::string& name);
974
981
998 const vector<index_t>& permutation
999 );
1000
1016 void compress(const vector<index_t>& old2new);
1017
1022 void copy(const AttributesManager& rhs);
1023
1024
1031 void copy_item(index_t to, index_t from);
1032
1039
1040
1046
1054 void scale_item(index_t to, double s);
1055
1064 void madd_item(index_t to, double s, index_t from);
1065
1075 const std::string& name, const std::string& new_name
1076 );
1077
1087 const std::string& old_name, const std::string& new_name
1088 );
1089
1090 private:
1098 AttributesManager(const AttributesManager& rhs) = delete;
1099
1107 const AttributesManager& operator=(const AttributesManager& rhs) = delete;
1108
1109 private:
1110 index_t size_;
1111 index_t capacity_;
1112 std::map<std::string, AttributeStore*> attributes_;
1113 } ;
1114
1115
1116 /*********************************************************************/
1117
1118
1123 template <class T> class AttributeBase : public AttributeStoreObserver {
1124 public:
1125
1130 manager_(nullptr),
1131 store_(nullptr) {
1132 }
1133
1143 AttributeBase(AttributesManager& manager, const std::string& name) :
1144 manager_(nullptr),
1145 store_(nullptr) {
1146 bind(manager, name);
1147 }
1148
1154 bool is_bound() const {
1155 return (store_ != nullptr && !disconnected_);
1156 }
1157
1162 void unbind() {
1164 // If the AttributesManager was destroyed before, do not
1165 // do anything. This can occur in Lua scripting when using
1166 // Attribute wrapper objects.
1167 if(!disconnected_) {
1168 unregister_me(store_);
1169 }
1170 manager_ = nullptr;
1171 store_ = nullptr;
1172 }
1173
1183 void bind(AttributesManager& manager, const std::string& name) {
1184 geo_assert(!is_bound());
1185 manager_ = &manager;
1186 store_ = manager_->find_attribute_store(name);
1187 if(store_ == nullptr) {
1188 store_ = new TypedAttributeStore<T>();
1189 manager_->bind_attribute_store(name,store_);
1190 } else {
1191 geo_assert(store_->elements_type_matches(typeid(T).name()));
1192 }
1193 register_me(store_);
1194 }
1195
1196
1206 AttributesManager& manager, const std::string& name
1207 ) {
1208 geo_assert(!is_bound());
1209 manager_ = &manager;
1210 store_ = manager_->find_attribute_store(name);
1211 if(store_ != nullptr) {
1212 geo_assert(store_->elements_type_matches(typeid(T).name()));
1213 register_me(store_);
1214 return true;
1215 }
1216 return false;
1217 }
1218
1228 AttributesManager& manager, const std::string& name
1229 ) {
1230 if( is_bound() ) {
1231 unbind();
1232 }
1233 store_ = manager.find_attribute_store(name);
1234 if(store_ != nullptr) {
1235 if( !store_->elements_type_matches(typeid(T).name()) ) {
1236 store_ = nullptr;
1237 return false;
1238 }
1239 manager_ = &manager;
1240 register_me(store_);
1241 return true;
1242 }
1243 return false;
1244 }
1245
1254 const std::string& name,
1256 ) {
1257 geo_assert(!is_bound());
1258 manager_ = &manager;
1259 geo_assert(manager_->find_attribute_store(name) == nullptr);
1260 store_ = new TypedAttributeStore<T>(dimension);
1261 manager_->bind_attribute_store(name,store_);
1262 register_me(store_);
1263 }
1264
1271 void destroy() {
1273 unregister_me(store_);
1274 manager_->delete_attribute_store(store_);
1275 store_ = nullptr;
1276 manager_ = nullptr;
1277 }
1278
1288 void redim(index_t new_dim) {
1290 store_->redim(new_dim);
1291 }
1292
1301 if(is_bound()) {
1302 unbind();
1303 }
1304 }
1305
1306
1314 static bool is_defined(
1315 AttributesManager& manager, const std::string& name,
1316 index_t dim = 0
1317 ) {
1319 return (
1320 store != nullptr &&
1321 store->elements_type_matches(typeid(T).name()) &&
1322 ((dim == 0) || (store->dimension() == dim))
1323 );
1324 }
1325
1330 index_t size() const {
1331 return size_;
1332 }
1333
1338 void zero() {
1340 store_->zero();
1341 }
1342
1353 return(
1354 dynamic_cast<TypedAttributeStore<T>*>(store_) != nullptr
1355 );
1356 }
1357
1369 TypedAttributeStore<T>* typed_store =
1370 dynamic_cast<TypedAttributeStore<T>*>(store_);
1371 geo_assert(typed_store != nullptr);
1372 return typed_store->get_vector();
1373 }
1374
1381 const vector<T>& get_vector() const {
1382 TypedAttributeStore<T>* typed_store =
1383 dynamic_cast<TypedAttributeStore<T>*>(store_);
1384 geo_assert(typed_store != nullptr);
1385 return typed_store->get_vector();
1386 }
1387
1393 return manager_;
1394 }
1395
1396 protected:
1397 AttributesManager* manager_;
1398 AttributeStore* store_;
1399 } ;
1400
1401 /*********************************************************************/
1402
1409 template <class T> class Attribute : public AttributeBase<T> {
1410 public:
1412
1418 static void static_test_type() {
1419 // Attributes are only implemented for classes that
1420 // can be copied with memcpy() and read/written to
1421 // files using fread()/fwrite()
1422#if __GNUG__ && __GNUC__ < 5 && !__clang__
1423 static_assert(
1424 __has_trivial_copy(T),
1425 "Attribute only implemented for types that can be copied with memcpy()"
1426 );
1427#else
1428 static_assert(
1429 std::is_trivially_copyable<T>::value,
1430 "Attribute only implemented for types that can be copied with memcpy()"
1431 );
1432#endif
1433 }
1434
1440 }
1441
1451 Attribute(AttributesManager& manager, const std::string& name) :
1452 superclass(manager, name) {
1454 }
1455
1464 return ((T*)(void*)superclass::base_addr_)[i];
1465 }
1466
1472 const T& operator[](index_t i) const {
1475 return ((const T*)(void*)superclass::base_addr_)[i];
1476 }
1477
1483 void fill(const T& val) {
1485 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1486 (*this)[i] = val;
1487 }
1488 }
1489
1496 void copy(const Attribute<T>& rhs) {
1497 geo_assert(rhs.size() == superclass::size());
1499 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1500 (*this)[i] = rhs[i];
1501 }
1502 }
1503
1508 T* data() {
1509 return (T*)AttributeStoreObserver::base_addr_;
1510 }
1511
1516 const T* data() const {
1517 return (const T*)AttributeStoreObserver::base_addr_;
1518 }
1519
1520
1521 private:
1525 Attribute(const Attribute<T>& rhs) = delete;
1529 Attribute<T>& operator=(const Attribute<T>& rhs) = delete;
1530 };
1531
1532 /*********************************************************************/
1533
1542 template <> class Attribute<bool> : public AttributeBase<Numeric::uint8> {
1543 public:
1545
1546 Attribute() : superclass() {
1547 }
1548
1549 Attribute(AttributesManager& manager, const std::string& name) :
1550 superclass(manager,name) {
1551 }
1552
1553 class BoolAttributeAccessor;
1554
1555
1560 class ConstBoolAttributeAccessor {
1561 public:
1566 const Attribute<bool>& attribute,
1567 index_t index
1568 ) :
1569 attribute_(&attribute),
1570 index_(index) {
1571 }
1572
1577 operator bool() const {
1578 return (attribute_->element(index_) != 0);
1579 }
1580
1581 private:
1582 const Attribute<bool>* attribute_;
1583 index_t index_;
1584
1585 friend class BoolAttributeAccessor;
1586 };
1587
1592 class BoolAttributeAccessor {
1593 public:
1598 Attribute<bool>& attribute,
1599 index_t index
1600 ) :
1601 attribute_(&attribute),
1602 index_(index) {
1603 }
1604
1609 operator bool() const {
1610 return (attribute_->element(index_) != 0);
1611 }
1612
1618 BoolAttributeAccessor(const BoolAttributeAccessor& rhs) {
1619 attribute_ = rhs.attribute_;
1620 index_ = rhs.index_;
1621 }
1622
1627 BoolAttributeAccessor& operator=(bool x) {
1628 attribute_->element(index_) = Numeric::uint8(x);
1629 return *this;
1630 }
1631
1637 BoolAttributeAccessor& operator=(
1638 const BoolAttributeAccessor& rhs
1639 ) {
1640 if(&rhs != this) {
1641 attribute_->element(index_) =
1642 rhs.attribute_->element(rhs.index_);
1643 }
1644 return *this;
1645 }
1646
1652 BoolAttributeAccessor& operator=(
1653 const ConstBoolAttributeAccessor& rhs
1654 ) {
1655 attribute_->element(index_) =
1656 rhs.attribute_->element(rhs.index_);
1657 return *this;
1658 }
1659
1660 private:
1661 Attribute<bool>* attribute_;
1662 index_t index_;
1663 };
1664
1665
1666 BoolAttributeAccessor operator[](index_t i) {
1667 return BoolAttributeAccessor(*this,i);
1668 }
1669
1670 ConstBoolAttributeAccessor operator[](index_t i) const {
1671 return ConstBoolAttributeAccessor(*this,i);
1672 }
1673
1679 void fill(bool val) {
1680 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1681 element(i) = Numeric::uint8(val);
1682 }
1683 }
1684
1691 void copy(const Attribute<bool>& rhs) {
1692 geo_assert(rhs.size() == superclass::size());
1694 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1695 element(i) = rhs.element(i);
1696 }
1697 }
1698
1699 protected:
1700
1701 friend class BoolAttributeAccessor;
1702 friend class ConstBoolAttributeAccessor;
1703
1711 return ((Numeric::uint8*)superclass::base_addr_)[i];
1712 }
1713
1721 return ((const Numeric::uint8*)superclass::base_addr_)[i];
1722 }
1723
1724 private:
1728 Attribute(const Attribute<bool>& rhs) = delete;
1732 Attribute<bool>& operator=(const Attribute<bool>& rhs) = delete;
1733 } ;
1734
1735 /***********************************************************/
1736
1741 class GEOGRAM_API ScalarAttributeAdapterBase :
1742 public AttributeStoreObserver {
1743
1744 public:
1749 ET_NONE=0,
1750 ET_UINT8=1,
1751 ET_INT8=2,
1752 ET_UINT32=3,
1753 ET_INT32=4,
1754 ET_FLOAT32=5,
1755 ET_FLOAT64=6,
1756 ET_VEC2=7,
1757 ET_VEC3=8
1758 };
1759
1760
1765 class Accessor {
1766 public:
1767 Accessor(
1768 ScalarAttributeAdapterBase& attribute,
1769 index_t index
1770 ) : attribute_(attribute), index_(index) {
1771 }
1772
1773 operator double() const {
1774 return attribute_.get_element_as_double(index_);
1775 }
1776
1777 void operator=(double x) {
1778 attribute_.set_element_as_double(index_, x);
1779 }
1780
1781 private:
1782 ScalarAttributeAdapterBase& attribute_;
1783 index_t index_;
1784 };
1785
1791 public:
1793 const ScalarAttributeAdapterBase& attribute,
1794 index_t index
1795 ) : attribute_(attribute), index_(index) {
1796 }
1797
1798 operator double() const {
1799 return attribute_.get_element_as_double(index_);
1800 }
1801
1802 private:
1803 const ScalarAttributeAdapterBase& attribute_;
1804 index_t index_;
1805 };
1806
1811 manager_(nullptr),
1812 store_(nullptr),
1813 element_type_(ET_NONE),
1814 element_index_(index_t(-1)) {
1815 }
1816
1827 const AttributesManager& manager, const std::string& name
1828 ) :
1829 manager_(nullptr),
1830 store_(nullptr) {
1831 bind_if_is_defined(manager, name);
1832 }
1833
1839 bool is_bound() const {
1840 return (store_ != nullptr);
1841 }
1842
1847 void unbind() {
1848 geo_assert(is_bound());
1849 unregister_me(const_cast<AttributeStore*>(store_));
1850 manager_ = nullptr;
1851 store_ = nullptr;
1852 element_type_ = ET_NONE;
1853 element_index_ = index_t(-1);
1854 }
1855
1866 const AttributesManager& manager, const std::string& name
1867 );
1868
1877 if(is_bound()) {
1878 unbind();
1879 }
1880 }
1881
1891 static bool is_defined(
1892 const AttributesManager& manager, const std::string& name
1893 );
1894
1899 index_t size() const {
1900 return (store_ == nullptr) ? 0 : store_->size();
1901 }
1902
1911 return element_type_;
1912 }
1913
1921 return element_index_;
1922 }
1923
1929 return store_;
1930 }
1931
1932
1940 static bool can_be_bound_to(const AttributeStore* store) {
1941 return element_type(store) != ET_NONE;
1942 }
1943
1952
1953 protected:
1962 static std::string attribute_base_name(const std::string& name);
1963
1972 static index_t attribute_element_index(const std::string& name);
1973
1982
1991 double result = 0.0;
1992 switch(element_type()) {
1993 case ET_UINT8:
1994 result = double(get_element<Numeric::uint8>(i));
1995 break;
1996 case ET_INT8:
1997 result = double(get_element<Numeric::int8>(i));
1998 break;
1999 case ET_UINT32:
2000 result = double(get_element<Numeric::uint32>(i));
2001 break;
2002 case ET_INT32:
2003 result = double(get_element<Numeric::int32>(i));
2004 break;
2005 case ET_FLOAT32:
2006 result = double(get_element<Numeric::float32>(i));
2007 break;
2008 case ET_FLOAT64:
2009 result = double(get_element<Numeric::float64>(i));
2010 break;
2011 case ET_VEC2:
2012 result = double(get_element<Numeric::float64>(i,2));
2013 break;
2014 case ET_VEC3:
2015 result = double(get_element<Numeric::float64>(i,3));
2016 break;
2017 case ET_NONE:
2019 }
2020 return result;
2021 }
2022
2031 template <class T> T get_element(index_t i,index_t multiplier=1) const {
2032 geo_debug_assert(is_bound());
2033 geo_debug_assert(i < size());
2034 return static_cast<const T*>(store_->data())[
2035 (i * store_->dimension() * multiplier) +
2036 element_index_
2037 ];
2038 }
2039
2046 double set_element_as_double(index_t i, double value) {
2047 double result = 0.0;
2048 switch(element_type()) {
2049 case ET_UINT8:
2050 set_element<Numeric::uint8>(Numeric::uint8(value), i);
2051 break;
2052 case ET_INT8:
2053 set_element<Numeric::int8>(Numeric::int8(value),i);
2054 break;
2055 case ET_UINT32:
2056 set_element<Numeric::uint32>(Numeric::uint32(value),i);
2057 break;
2058 case ET_INT32:
2059 set_element<Numeric::int32>(Numeric::int32(value),i);
2060 break;
2061 case ET_FLOAT32:
2062 set_element<Numeric::float32>(Numeric::float32(value),i);
2063 break;
2064 case ET_FLOAT64:
2065 set_element<Numeric::float64>(Numeric::float64(value),i);
2066 break;
2067 case ET_VEC2:
2068 set_element<Numeric::float64>(Numeric::float64(value),i,2);
2069 break;
2070 case ET_VEC3:
2071 set_element<Numeric::float64>(Numeric::float64(value),i,3);
2072 break;
2073 case ET_NONE:
2075 }
2076 return result;
2077 }
2078
2088 template <class T> void set_element(
2089 T value, index_t i, index_t multiplier=1
2090 ) const {
2091 geo_debug_assert(is_bound());
2092 geo_debug_assert(i < size());
2093 const_cast<T*>(static_cast<const T*>(store_->data()))[
2094 (i * store_->dimension() * multiplier) +
2095 element_index_
2096 ] = value;
2097 }
2098
2099 protected:
2100 const AttributesManager* manager_;
2101 const AttributeStore* store_;
2102 ElementType element_type_;
2103 index_t element_index_;
2104 };
2105
2106 /***********************************************************/
2107
2113 public:
2115 }
2116
2118 const AttributesManager& manager, const std::string& name
2119 ) : ScalarAttributeAdapterBase(manager, name) {
2120 }
2121
2130 return get_element_as_double(i);
2131 }
2132 };
2133
2134 /***********************************************************/
2135
2141 public:
2143 }
2144
2146 const AttributesManager& manager, const std::string& name
2147 ) : ScalarAttributeAdapterBase(manager, name) {
2148 }
2149
2150 Accessor operator[](index_t i) {
2151 return Accessor(*this, i);
2152 }
2153
2154 ConstAccessor operator[](index_t i) const {
2155 return ConstAccessor(*this, i);
2156 }
2157
2158 protected:
2159 };
2160
2161
2162}
2163
2164#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.
void create_vector_attribute(AttributesManager &manager, const std::string &name, index_t dimension)
Creates and binds a new vector attribute.
AttributesManager * manager() const
Gets the AttributesManager this Attribute is bound to.
~AttributeBase()
Attribute destructor.
index_t size() const
Gets the size.
AttributeBase(AttributesManager &manager, const std::string &name)
Creates or retrieves a persistent attribute attached to a given AttributesManager.
const vector< T > & get_vector() const
Gets a const reference to the internal vector<T> used to store the attribute.
void zero()
Sets all the elements of this Attribute to zero.
bool is_bound() const
Tests whether an Attribute is bound.
void unbind()
Unbinds this Attribute.
void redim(index_t new_dim)
Sets the dimension.
void destroy()
Destroys this attribute in the AttributesManager.
vector< T > & 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 ...
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...
bool can_get_vector()
Tests whether get_vector() can be called on this Attribute.
AttributeBase()
Creates an uninitialized (unbound) Attribute.
void bind(AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager.
bool bind_if_is_defined(AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager if it already exists in the AttributesManager.
Internal class for creating an AttributeStore from the type name of its elements.
Definition attributes.h:180
~AttributeStoreCreator() override
AttributeStoreCreator destructor.
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:69
AttributeStoreObserver()
Creates a new uninitialied AttributeStore.
Definition attributes.h:75
void register_me(AttributeStore *store)
Registers this observer to an AttributeStore.
index_t size() const
Gets the size.
Definition attributes.h:99
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:87
index_t nb_elements() const
Gets the total number of elements.
Definition attributes.h:117
bool disconnected() const
Tests whether this AttributeStoreObserver was disconnected.
Definition attributes.h:161
void disconnect()
Disconnects this AttributeStoreObserver from its AttributeStore.
Definition attributes.h:148
void unregister_me(AttributeStore *store)
Unregisters this observer from an AttributeStore.
index_t dimension() const
Gets the dimension.
Definition attributes.h:107
Memory::pointer base_addr() const
Gets a pointer to the storage.
Definition attributes.h:125
Notifies a set of AttributeStoreObservers each time the stored array changes size and/or base address...
Definition attributes.h:212
void * data()
Gets a pointer to the stored data.
Definition attributes.h:433
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:493
bool has_observers() const
Tests whether observers listen to this AttributeStore.
Definition attributes.h:293
void zero_item(index_t to)
Sets an item to zero.
Definition attributes.h:395
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:524
static void register_attribute_creator(AttributeStoreCreator *creator, const std::string &element_type_name, const std::string &element_typeid_name)
Registers a new element type.
Definition attributes.h:541
index_t size() const
Gets the size.
Definition attributes.h:255
const void * data() const
Gets a pointer to the stored data.
Definition attributes.h:441
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:264
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_type_name_is_known(const std::string &element_type_name)
Tests whether a given element type is registered in the system.
Definition attributes.h:461
virtual void compress(const vector< index_t > &old2new)
Compresses the stored attributes, by applying an index mapping that fills-in the gaps.
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:380
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:478
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:302
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:509
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.
size_t element_size() const
Gets the element size.
Definition attributes.h:449
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.
static void static_test_type()
Tests at compile time whether type can be used in an Attribute. If not the case generates a compile-t...
Managers a set of attributes attached to an object.
Definition attributes.h:849
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:867
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.
Definition attributes.h:964
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:884
void clear(bool keep_attributes, bool keep_memory=false)
Clears this AttributesManager.
index_t capacity() const
Gets the capacity.
Definition attributes.h:893
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
static void register_ascii_attribute_serializer(const std::string &type_name, AsciiAttributeSerializer read, AsciiAttributeSerializer write)
Declares a new attribute type that can be read from and written to ascii files.
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:796
AttributeStore * create_attribute_store(index_t dim) override
Creates a new attribute store.
Definition attributes.h:801
Stores an array of elements of a given type, and notifies a set of AttributeStoreObservers each time ...
Definition attributes.h:624
void scale_item(index_t to, double s) override
Scales an item.
Definition attributes.h:708
TypedAttributeStore(index_t dim=1)
Creates a new empty attribute store.
Definition attributes.h:633
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:726
void clear(bool keep_memory=false) override
Resizes this AttributeStore to 0.
Definition attributes.h:658
AttributeStore * clone() const override
Creates a new AttributeStore that is a carbon copy of this AttributeStore.
Definition attributes.h:696
void resize(index_t new_size) override
Resizes this AttributeStore.
Definition attributes.h:637
std::string element_typeid_name() const override
Gets the typeid name of the element type stored in this AttributeStore.
Definition attributes.h:692
void reserve(index_t new_capacity) override
Reserves memory.
Definition attributes.h:646
bool elements_type_matches(const std::string &type_name) const override
Tests whether this AttributeStore stores elements of a given type.
Definition attributes.h:688
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:715
void redim(index_t dim) override
Sets the dimension.
Definition attributes.h:668
Helper class to register new attribute types.
Definition attributes.h:812
geo_register_attribute_type(const std::string &type_name)
geo_register_attribute_type constructor
Definition attributes.h:823
Vector with aligned memory allocation.
Definition memory.h:660
Functions to read and write structured files.
Common include file, providing basic definitions. Should be included before anything else by all head...
Generic logging mechanism.
Types and functions for memory manipulation.
byte * pointer
Pointer to unsigned byte(s)
Definition memory.h:104
float float32
Definition numeric.h:147
uint8_t uint8
Definition numeric.h:135
int8_t int8
Definition numeric.h:123
double float64
Definition numeric.h:150
int32_t int32
Definition numeric.h:129
uint32_t uint32
Definition numeric.h:141
std::atomic_flag spinlock
A lightweight synchronization structure.
Global Vorpaline namespace.
Definition basic.h:55
bool write_ascii_attribute< bool >(FILE *file, Memory::pointer base_addr, index_t nb_elements)
Writes an ASCII attribute to a file.
Definition geofile.h:228
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:329
SmartPointer< AttributeStoreCreator > AttributeStoreCreator_var
An automatic reference-counted pointer to an AttributeStoreCreator.
Definition attributes.h:205
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:204
Types and functions for numbers manipulation.
Function and classes for process manipulation.