Geogram Version 1.9.6
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
547 protected:
556 virtual void notify(
557 Memory::pointer base_addr, index_t size, index_t dim
558 );
559
569
578
579
580 protected:
581 size_t element_size_;
582 index_t dimension_;
583 Memory::pointer cached_base_addr_;
584 index_t cached_size_;
585 index_t cached_capacity_;
586 std::set<AttributeStoreObserver*> observers_;
587 Process::spinlock lock_;
588
589 static std::map<std::string, AttributeStoreCreator_var>
590 type_name_to_creator_;
591
592 static std::map<std::string, std::string>
593 typeid_name_to_type_name_;
594
595 static std::map<std::string, std::string>
596 type_name_to_typeid_name_;
597
598 friend class AttributeStoreObserver;
599 };
600
601 /*********************************************************************/
602
608 template <class T> class TypedAttributeStore : public AttributeStore {
609 public:
610
618 AttributeStore(sizeof(T),dim) {
619 }
620
621 void resize(index_t new_size) override {
622 store_.resize(new_size*dimension_);
623 notify(
624 store_.empty() ? nullptr : Memory::pointer(store_.data()),
625 new_size,
626 dimension_
627 );
628 }
629
630 void reserve(index_t new_capacity) override {
631 if(new_capacity > capacity()) {
632 store_.reserve(new_capacity*dimension_);
633 cached_capacity_ = new_capacity;
634 notify(
635 store_.empty() ? nullptr : Memory::pointer(store_.data()),
636 size(),
637 dimension_
638 );
639 }
640 }
641
642 void clear(bool keep_memory=false) override {
643 if(keep_memory) {
644 store_.resize(0);
645 } else {
646 store_.clear();
647 }
648 notify(nullptr, 0, dimension_);
649 }
650
651
652 void redim(index_t dim) override {
653 if(dim == dimension()) {
654 return;
655 }
656 vector<T> new_store(size()*dim);
657 new_store.reserve(capacity()*dim);
658 index_t copy_dim = std::min(dim, dimension());
659 for(index_t i = 0; i < size(); ++i) {
660 for(index_t c = 0; c < copy_dim; ++c) {
661 new_store[dim * i + c] = store_[dimension_ * i + c];
662 }
663 }
664 store_.swap(new_store);
665 notify(
666 store_.empty() ? nullptr : Memory::pointer(store_.data()),
667 size(),
668 dim
669 );
670 }
671
672 bool elements_type_matches(const std::string& type_name) const override {
673 return type_name == typeid(T).name();
674 }
675
676 std::string element_typeid_name() const override {
677 return typeid(T).name();
678 }
679
680 AttributeStore* clone() const override {
681 TypedAttributeStore<T>* result =
683 result->resize(size());
684 result->store_ = store_;
685 return result;
686 }
687
688 vector<T>& get_vector() {
689 return store_;
690 }
691
692 void scale_item(index_t to, double s) override {
693 geo_assert(to < size());
694 for(index_t i=0; i<dimension_; ++i) {
695 scale_value(store_[to*dimension_+i], s);
696 }
697 }
698
699 void madd_item(index_t to, double s, index_t from) override {
700 geo_assert(from < size());
701 geo_assert(to < size());
702 for(index_t i=0; i<dimension_; ++i) {
703 madd_value(
704 store_[to*dimension_+i], s, store_[from*dimension_+i]
705 );
706 }
707 }
708
709 protected:
710 void notify(
711 Memory::pointer base_addr, index_t size, index_t dim
712 ) override {
713 AttributeStore::notify(base_addr, size, dim);
714 geo_assert(size*dim <= store_.size());
715 }
716
717 template<class TT> static void scale_value(TT& to, double s) {
718 geo_argused(to);
719 geo_argused(s);
720 }
721
722 static void scale_value(uint8_t& to, double s) {
723 to = uint8_t(double(to)*s != 0.0);
724 }
725
726 static void scale_value(int32_t& to, double s) {
727 to = int32_t(double(to)*s);
728 }
729
730 static void scale_value(uint32_t& to, double s) {
731 to = uint32_t(double(to)*s);
732 }
733
734 static void scale_value(float& to, double s) {
735 to = float(double(to)*s);
736 }
737
738 static void scale_value(double& to, double s) {
739 to *= s;
740 }
741
742 template<class TT> static void madd_value(TT& to, double s, TT& from) {
743 geo_argused(to);
744 geo_argused(s);
745 geo_argused(from);
746 }
747
748 static void madd_value(uint8_t& to, double s, uint8_t& from) {
749 to = uint8_t(double(to) + s*double(from) != 0.0);
750 }
751
752 static void madd_value(int32_t& to, double s, int32_t& from) {
753 to = int32_t(double(to) + s*double(from));
754 }
755
756 static void madd_value(uint32_t& to, double s, uint32_t& from) {
757 to = uint32_t(double(to) + s*double(from));
758 }
759
760 static void madd_value(float& to, double s, float& from) {
761 to = float(double(to) + s*double(from));
762 }
763
764 static void madd_value(double& to, double s, double& from) {
765 to += s*from;
766 }
767
768
769 private:
770 vector<T> store_;
771 };
772
773 /*********************************************************************/
774
779 template <class T>
781 public:
786 return new TypedAttributeStore<T>(dim);
787 }
788 };
789
790 /*********************************************************************/
791
796 template <class T> class geo_register_attribute_type {
797 public:
807 geo_register_attribute_type(const std::string& type_name) {
809 new TypedAttributeStoreCreator<T>, type_name, typeid(T).name()
810 );
811 if(type_name == "bool") {
813 type_name,
816 );
817 } else {
819 type_name,
820 read_ascii_attribute<T>,
821 write_ascii_attribute<T>
822 );
823 }
824 }
825 };
826
827 /*********************************************************************/
828
833 class GEOGRAM_API AttributesManager {
834 public:
839
840
845
851 index_t nb() const {
852 return index_t(attributes_.size());
853 }
854
861
868 index_t size() const {
869 return size_;
870 }
871
878 return capacity_;
879 }
880
887 void resize(index_t new_size);
888
895 void reserve(index_t new_capacity);
896
905 void clear(bool keep_attributes, bool keep_memory = false);
906
907
911 void zero();
912
921 void bind_attribute_store(const std::string& name, AttributeStore* as);
922
929 AttributeStore* find_attribute_store(const std::string& name);
930
938 const std::string& name
939 ) const;
940
941
948 bool is_defined(const std::string& name) const {
949 return (find_attribute_store(name) != nullptr);
950 }
951
957 void delete_attribute_store(const std::string& name);
958
965
982 const vector<index_t>& permutation
983 );
984
1000 void compress(const vector<index_t>& old2new);
1001
1006 void copy(const AttributesManager& rhs);
1007
1008
1015 void copy_item(index_t to, index_t from);
1016
1023
1024
1030
1038 void scale_item(index_t to, double s);
1039
1048 void madd_item(index_t to, double s, index_t from);
1049
1059 const std::string& name, const std::string& new_name
1060 );
1061
1071 const std::string& old_name, const std::string& new_name
1072 );
1073
1074 private:
1082 AttributesManager(const AttributesManager& rhs) = delete;
1083
1091 const AttributesManager& operator=(const AttributesManager& rhs) = delete;
1092
1093 private:
1094 index_t size_;
1095 index_t capacity_;
1096 std::map<std::string, AttributeStore*> attributes_;
1097 } ;
1098
1099
1100 /*********************************************************************/
1101
1102
1107 template <class T> class AttributeBase : public AttributeStoreObserver {
1108 public:
1109
1114 manager_(nullptr),
1115 store_(nullptr) {
1116 }
1117
1127 AttributeBase(AttributesManager& manager, const std::string& name) :
1128 manager_(nullptr),
1129 store_(nullptr) {
1130 bind(manager, name);
1131 }
1132
1138 bool is_bound() const {
1139 return (store_ != nullptr && !disconnected_);
1140 }
1141
1146 void unbind() {
1148 // If the AttributesManager was destroyed before, do not
1149 // do anything. This can occur in Lua scripting when using
1150 // Attribute wrapper objects.
1151 if(!disconnected_) {
1152 unregister_me(store_);
1153 }
1154 manager_ = nullptr;
1155 store_ = nullptr;
1156 }
1157
1167 void bind(AttributesManager& manager, const std::string& name) {
1168 geo_assert(!is_bound());
1169 manager_ = &manager;
1170 store_ = manager_->find_attribute_store(name);
1171 if(store_ == nullptr) {
1172 store_ = new TypedAttributeStore<T>();
1173 manager_->bind_attribute_store(name,store_);
1174 } else {
1175 geo_assert(store_->elements_type_matches(typeid(T).name()));
1176 }
1177 register_me(store_);
1178 }
1179
1180
1190 AttributesManager& manager, const std::string& name
1191 ) {
1192 geo_assert(!is_bound());
1193 manager_ = &manager;
1194 store_ = manager_->find_attribute_store(name);
1195 if(store_ != nullptr) {
1196 geo_assert(store_->elements_type_matches(typeid(T).name()));
1197 register_me(store_);
1198 return true;
1199 }
1200 return false;
1201 }
1202
1212 AttributesManager& manager, const std::string& name
1213 ) {
1214 if( is_bound() ) {
1215 unbind();
1216 }
1217 store_ = manager.find_attribute_store(name);
1218 if(store_ != nullptr) {
1219 if( !store_->elements_type_matches(typeid(T).name()) ) {
1220 store_ = nullptr;
1221 return false;
1222 }
1223 manager_ = &manager;
1224 register_me(store_);
1225 return true;
1226 }
1227 return false;
1228 }
1229
1238 const std::string& name,
1240 ) {
1241 geo_assert(!is_bound());
1242 manager_ = &manager;
1243 geo_assert(manager_->find_attribute_store(name) == nullptr);
1244 store_ = new TypedAttributeStore<T>(dimension);
1245 manager_->bind_attribute_store(name,store_);
1246 register_me(store_);
1247 }
1248
1255 void destroy() {
1257 unregister_me(store_);
1258 manager_->delete_attribute_store(store_);
1259 store_ = nullptr;
1260 manager_ = nullptr;
1261 }
1262
1272 void redim(index_t new_dim) {
1274 store_->redim(new_dim);
1275 }
1276
1285 if(is_bound()) {
1286 unbind();
1287 }
1288 }
1289
1290
1298 static bool is_defined(
1299 AttributesManager& manager, const std::string& name,
1300 index_t dim = 0
1301 ) {
1303 return (
1304 store != nullptr &&
1305 store->elements_type_matches(typeid(T).name()) &&
1306 ((dim == 0) || (store->dimension() == dim))
1307 );
1308 }
1309
1314 index_t size() const {
1315 return size_;
1316 }
1317
1322 void zero() {
1324 store_->zero();
1325 }
1326
1337 return(
1338 dynamic_cast<TypedAttributeStore<T>*>(store_) != nullptr
1339 );
1340 }
1341
1353 TypedAttributeStore<T>* typed_store =
1354 dynamic_cast<TypedAttributeStore<T>*>(store_);
1355 geo_assert(typed_store != nullptr);
1356 return typed_store->get_vector();
1357 }
1358
1365 const vector<T>& get_vector() const {
1366 TypedAttributeStore<T>* typed_store =
1367 dynamic_cast<TypedAttributeStore<T>*>(store_);
1368 geo_assert(typed_store != nullptr);
1369 return typed_store->get_vector();
1370 }
1371
1377 return manager_;
1378 }
1379
1380 protected:
1381 AttributesManager* manager_;
1382 AttributeStore* store_;
1383 } ;
1384
1385 /*********************************************************************/
1386
1393 template <class T> class Attribute : public AttributeBase<T> {
1394 public:
1396
1402 static void static_test_type() {
1403 // Attributes are only implemented for classes that
1404 // can be copied with memcpy() and read/written to
1405 // files using fread()/fwrite()
1406#if __GNUG__ && __GNUC__ < 5 && !__clang__
1407 static_assert(
1408 __has_trivial_copy(T),
1409 "Attribute only implemented for types that can be copied with memcpy()"
1410 );
1411#else
1412 static_assert(
1413 std::is_trivially_copyable<T>::value,
1414 "Attribute only implemented for types that can be copied with memcpy()"
1415 );
1416#endif
1417 }
1418
1424 }
1425
1435 Attribute(AttributesManager& manager, const std::string& name) :
1436 superclass(manager, name) {
1438 }
1439
1448 return ((T*)(void*)superclass::base_addr_)[i];
1449 }
1450
1456 const T& operator[](index_t i) const {
1459 return ((const T*)(void*)superclass::base_addr_)[i];
1460 }
1461
1467 void fill(const T& val) {
1469 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1470 (*this)[i] = val;
1471 }
1472 }
1473
1480 void copy(const Attribute<T>& rhs) {
1481 geo_assert(rhs.size() == superclass::size());
1483 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1484 (*this)[i] = rhs[i];
1485 }
1486 }
1487
1492 T* data() {
1493 return (T*)AttributeStoreObserver::base_addr_;
1494 }
1495
1500 const T* data() const {
1501 return (const T*)AttributeStoreObserver::base_addr_;
1502 }
1503
1504
1505 private:
1509 Attribute(const Attribute<T>& rhs) = delete;
1513 Attribute<T>& operator=(const Attribute<T>& rhs) = delete;
1514 };
1515
1516 /*********************************************************************/
1517
1526 template <> class Attribute<bool> : public AttributeBase<Numeric::uint8> {
1527 public:
1529
1530 Attribute() : superclass() {
1531 }
1532
1533 Attribute(AttributesManager& manager, const std::string& name) :
1534 superclass(manager,name) {
1535 }
1536
1537 class BoolAttributeAccessor;
1538
1539
1544 class ConstBoolAttributeAccessor {
1545 public:
1550 const Attribute<bool>& attribute,
1551 index_t index
1552 ) :
1553 attribute_(&attribute),
1554 index_(index) {
1555 }
1556
1561 operator bool() const {
1562 return (attribute_->element(index_) != 0);
1563 }
1564
1565 private:
1566 const Attribute<bool>* attribute_;
1567 index_t index_;
1568
1569 friend class BoolAttributeAccessor;
1570 };
1571
1576 class BoolAttributeAccessor {
1577 public:
1582 Attribute<bool>& attribute,
1583 index_t index
1584 ) :
1585 attribute_(&attribute),
1586 index_(index) {
1587 }
1588
1593 operator bool() const {
1594 return (attribute_->element(index_) != 0);
1595 }
1596
1602 BoolAttributeAccessor(const BoolAttributeAccessor& rhs) {
1603 attribute_ = rhs.attribute_;
1604 index_ = rhs.index_;
1605 }
1606
1611 BoolAttributeAccessor& operator=(bool x) {
1612 attribute_->element(index_) = Numeric::uint8(x);
1613 return *this;
1614 }
1615
1621 BoolAttributeAccessor& operator=(
1622 const BoolAttributeAccessor& rhs
1623 ) {
1624 if(&rhs != this) {
1625 attribute_->element(index_) =
1626 rhs.attribute_->element(rhs.index_);
1627 }
1628 return *this;
1629 }
1630
1636 BoolAttributeAccessor& operator=(
1637 const ConstBoolAttributeAccessor& rhs
1638 ) {
1639 attribute_->element(index_) =
1640 rhs.attribute_->element(rhs.index_);
1641 return *this;
1642 }
1643
1644 private:
1645 Attribute<bool>* attribute_;
1646 index_t index_;
1647 };
1648
1649
1650 BoolAttributeAccessor operator[](index_t i) {
1651 return BoolAttributeAccessor(*this,i);
1652 }
1653
1654 ConstBoolAttributeAccessor operator[](index_t i) const {
1655 return ConstBoolAttributeAccessor(*this,i);
1656 }
1657
1663 void fill(bool val) {
1664 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1665 element(i) = Numeric::uint8(val);
1666 }
1667 }
1668
1675 void copy(const Attribute<bool>& rhs) {
1676 geo_assert(rhs.size() == superclass::size());
1678 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1679 element(i) = rhs.element(i);
1680 }
1681 }
1682
1683 protected:
1684
1685 friend class BoolAttributeAccessor;
1686 friend class ConstBoolAttributeAccessor;
1687
1695 return ((Numeric::uint8*)superclass::base_addr_)[i];
1696 }
1697
1705 return ((const Numeric::uint8*)superclass::base_addr_)[i];
1706 }
1707
1708 private:
1712 Attribute(const Attribute<bool>& rhs) = delete;
1716 Attribute<bool>& operator=(const Attribute<bool>& rhs) = delete;
1717 } ;
1718
1719 /***********************************************************/
1720
1725 class GEOGRAM_API ScalarAttributeAdapterBase :
1726 public AttributeStoreObserver {
1727
1728 public:
1733 ET_NONE=0,
1734 ET_UINT8=1,
1735 ET_INT8=2,
1736 ET_UINT32=3,
1737 ET_INT32=4,
1738 ET_FLOAT32=5,
1739 ET_FLOAT64=6,
1740 ET_VEC2=7,
1741 ET_VEC3=8
1742 };
1743
1744
1749 class Accessor {
1750 public:
1751 Accessor(
1752 ScalarAttributeAdapterBase& attribute,
1753 index_t index
1754 ) : attribute_(attribute), index_(index) {
1755 }
1756
1757 operator double() const {
1758 return attribute_.get_element_as_double(index_);
1759 }
1760
1761 void operator=(double x) {
1762 attribute_.set_element_as_double(index_, x);
1763 }
1764
1765 private:
1766 ScalarAttributeAdapterBase& attribute_;
1767 index_t index_;
1768 };
1769
1775 public:
1777 const ScalarAttributeAdapterBase& attribute,
1778 index_t index
1779 ) : attribute_(attribute), index_(index) {
1780 }
1781
1782 operator double() const {
1783 return attribute_.get_element_as_double(index_);
1784 }
1785
1786 private:
1787 const ScalarAttributeAdapterBase& attribute_;
1788 index_t index_;
1789 };
1790
1795 manager_(nullptr),
1796 store_(nullptr),
1797 element_type_(ET_NONE),
1798 element_index_(index_t(-1)) {
1799 }
1800
1811 const AttributesManager& manager, const std::string& name
1812 ) :
1813 manager_(nullptr),
1814 store_(nullptr) {
1815 bind_if_is_defined(manager, name);
1816 }
1817
1823 bool is_bound() const {
1824 return (store_ != nullptr);
1825 }
1826
1831 void unbind() {
1832 geo_assert(is_bound());
1833 unregister_me(const_cast<AttributeStore*>(store_));
1834 manager_ = nullptr;
1835 store_ = nullptr;
1836 element_type_ = ET_NONE;
1837 element_index_ = index_t(-1);
1838 }
1839
1850 const AttributesManager& manager, const std::string& name
1851 );
1852
1861 if(is_bound()) {
1862 unbind();
1863 }
1864 }
1865
1875 static bool is_defined(
1876 const AttributesManager& manager, const std::string& name
1877 );
1878
1883 index_t size() const {
1884 return (store_ == nullptr) ? 0 : store_->size();
1885 }
1886
1895 return element_type_;
1896 }
1897
1905 return element_index_;
1906 }
1907
1913 return store_;
1914 }
1915
1916
1924 static bool can_be_bound_to(const AttributeStore* store) {
1925 return element_type(store) != ET_NONE;
1926 }
1927
1936
1937 protected:
1946 static std::string attribute_base_name(const std::string& name);
1947
1956 static index_t attribute_element_index(const std::string& name);
1957
1966
1975 double result = 0.0;
1976 switch(element_type()) {
1977 case ET_UINT8:
1978 result = double(get_element<Numeric::uint8>(i));
1979 break;
1980 case ET_INT8:
1981 result = double(get_element<Numeric::int8>(i));
1982 break;
1983 case ET_UINT32:
1984 result = double(get_element<Numeric::uint32>(i));
1985 break;
1986 case ET_INT32:
1987 result = double(get_element<Numeric::int32>(i));
1988 break;
1989 case ET_FLOAT32:
1990 result = double(get_element<Numeric::float32>(i));
1991 break;
1992 case ET_FLOAT64:
1993 result = double(get_element<Numeric::float64>(i));
1994 break;
1995 case ET_VEC2:
1996 result = double(get_element<Numeric::float64>(i,2));
1997 break;
1998 case ET_VEC3:
1999 result = double(get_element<Numeric::float64>(i,3));
2000 break;
2001 case ET_NONE:
2003 }
2004 return result;
2005 }
2006
2015 template <class T> T get_element(index_t i,index_t multiplier=1) const {
2016 geo_debug_assert(is_bound());
2017 geo_debug_assert(i < size());
2018 return static_cast<const T*>(store_->data())[
2019 (i * store_->dimension() * multiplier) +
2020 element_index_
2021 ];
2022 }
2023
2030 double set_element_as_double(index_t i, double value) {
2031 double result = 0.0;
2032 switch(element_type()) {
2033 case ET_UINT8:
2034 set_element<Numeric::uint8>(Numeric::uint8(value), i);
2035 break;
2036 case ET_INT8:
2037 set_element<Numeric::int8>(Numeric::int8(value),i);
2038 break;
2039 case ET_UINT32:
2040 set_element<Numeric::uint32>(Numeric::uint32(value),i);
2041 break;
2042 case ET_INT32:
2043 set_element<Numeric::int32>(Numeric::int32(value),i);
2044 break;
2045 case ET_FLOAT32:
2046 set_element<Numeric::float32>(Numeric::float32(value),i);
2047 break;
2048 case ET_FLOAT64:
2049 set_element<Numeric::float64>(Numeric::float64(value),i);
2050 break;
2051 case ET_VEC2:
2052 set_element<Numeric::float64>(Numeric::float64(value),i,2);
2053 break;
2054 case ET_VEC3:
2055 set_element<Numeric::float64>(Numeric::float64(value),i,3);
2056 break;
2057 case ET_NONE:
2059 }
2060 return result;
2061 }
2062
2072 template <class T> void set_element(
2073 T value, index_t i, index_t multiplier=1
2074 ) const {
2075 geo_debug_assert(is_bound());
2076 geo_debug_assert(i < size());
2077 const_cast<T*>(static_cast<const T*>(store_->data()))[
2078 (i * store_->dimension() * multiplier) +
2079 element_index_
2080 ] = value;
2081 }
2082
2083 protected:
2084 const AttributesManager* manager_;
2085 const AttributeStore* store_;
2086 ElementType element_type_;
2087 index_t element_index_;
2088 };
2089
2090 /***********************************************************/
2091
2097 public:
2099 }
2100
2102 const AttributesManager& manager, const std::string& name
2103 ) : ScalarAttributeAdapterBase(manager, name) {
2104 }
2105
2114 return get_element_as_double(i);
2115 }
2116 };
2117
2118 /***********************************************************/
2119
2125 public:
2127 }
2128
2130 const AttributesManager& manager, const std::string& name
2131 ) : ScalarAttributeAdapterBase(manager, name) {
2132 }
2133
2134 Accessor operator[](index_t i) {
2135 return Accessor(*this, i);
2136 }
2137
2138 ConstAccessor operator[](index_t i) const {
2139 return ConstAccessor(*this, i);
2140 }
2141
2142 protected:
2143 };
2144
2145
2146}
2147
2148#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
Common include file, providing basic definitions. Should be included before anything else by all head...
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.
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:833
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:851
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:948
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:868
void clear(bool keep_attributes, bool keep_memory=false)
Clears this AttributesManager.
index_t capacity() const
Gets the capacity.
Definition attributes.h:877
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:780
AttributeStore * create_attribute_store(index_t dim) override
Creates a new attribute store.
Definition attributes.h:785
Stores an array of elements of a given type, and notifies a set of AttributeStoreObservers each time ...
Definition attributes.h:608
void scale_item(index_t to, double s) override
Scales an item.
Definition attributes.h:692
TypedAttributeStore(index_t dim=1)
Creates a new empty attribute store.
Definition attributes.h:617
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:710
void clear(bool keep_memory=false) override
Resizes this AttributeStore to 0.
Definition attributes.h:642
AttributeStore * clone() const override
Creates a new AttributeStore that is a carbon copy of this AttributeStore.
Definition attributes.h:680
void resize(index_t new_size) override
Resizes this AttributeStore.
Definition attributes.h:621
std::string element_typeid_name() const override
Gets the typeid name of the element type stored in this AttributeStore.
Definition attributes.h:676
void reserve(index_t new_capacity) override
Reserves memory.
Definition attributes.h:630
bool elements_type_matches(const std::string &type_name) const override
Tests whether this AttributeStore stores elements of a given type.
Definition attributes.h:672
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:699
void redim(index_t dim) override
Sets the dimension.
Definition attributes.h:652
Helper class to register new attribute types.
Definition attributes.h:796
geo_register_attribute_type(const std::string &type_name)
geo_register_attribute_type constructor
Definition attributes.h:807
Vector with aligned memory allocation.
Definition memory.h:660
Functions to read and write structured files.
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 algorithm.h:65
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.