Graphite  Version 3
An experimental 3D geometry processing program
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 
44 
45 #include <geogram/basic/common.h>
46 #include <geogram/basic/memory.h>
47 #include <geogram/basic/numeric.h>
48 #include <geogram/basic/process.h>
49 #include <geogram/basic/geofile.h>
50 #include <geogram/basic/logger.h>
51 
52 #include <map>
53 #include <typeinfo>
54 #include <set>
55 #include <type_traits>
56 
62 namespace 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 
108  index_t dimension() const {
109  return dimension_;
110  }
111 
119  return size_ * dimension_;
120  }
121 
127 
133 
141  void disconnect() {
142  base_addr_ = nullptr;
143  size_ = 0;
144  dimension_ = 0;
145  disconnected_ = true;
146  }
147 
148  protected:
149  Memory::pointer base_addr_;
150  index_t size_;
151  index_t dimension_;
152  bool disconnected_;
153  };
154 
155 
156  /*********************************************************************/
157 
158 
163  class GEOGRAM_API AttributeStoreCreator : public Counted {
164  public:
165 
170 
177 
178 
179  private:
180  std::string element_type_name_;
181  std::string element_typeid_name_;
182  };
183 
189 
195  class GEOGRAM_API AttributeStore {
196  public:
206  AttributeStore(index_t elemsize, index_t dim=1);
207 
211  virtual ~AttributeStore();
212 
213 
223  virtual bool elements_type_matches(
224  const std::string& type_name
225  ) const = 0;
226 
232  virtual std::string element_typeid_name() const = 0;
233 
238  index_t size() const {
239  return cached_size_;
240  }
241 
247  index_t capacity() const {
248  return cached_capacity_;
249  }
250 
255  virtual void resize(index_t new_size) = 0;
256 
262  virtual void reserve(index_t new_capacity) = 0;
263 
269  virtual void clear(bool keep_memory = false) = 0;
270 
276  bool has_observers() const {
277  return !observers_.empty();
278  }
279 
285  index_t dimension() const {
286  return dimension_;
287  }
288 
298  virtual void redim(index_t dim) = 0;
299 
300 
318  virtual void apply_permutation(
319  const vector<index_t>& permutation
320  );
321 
339  virtual void compress(const vector<index_t>& old2new);
340 
348  virtual void zero();
349 
355  virtual AttributeStore* clone() const = 0;
356 
357 
363  void copy_item(index_t to, index_t from) {
364  geo_debug_assert(from < cached_size_);
365  geo_debug_assert(to < cached_size_);
366  index_t item_size = element_size_ * dimension_;
367  Memory::copy(
368  cached_base_addr_+to*item_size,
369  cached_base_addr_+from*item_size,
370  item_size
371  );
372  }
373 
378  void zero_item(index_t to) {
379  geo_debug_assert(to < cached_size_);
380  index_t item_size = element_size_ * dimension_;
382  cached_base_addr_+to*item_size,
383  item_size
384  );
385  }
386 
394  virtual void scale_item(index_t to, double s);
395 
404  virtual void madd_item(index_t to, double s, index_t from);
405 
411 
416  void* data() {
417  return cached_base_addr_;
418  }
419 
424  const void* data() const {
425  return cached_base_addr_;
426  }
427 
432  size_t element_size() const {
433  return size_t(element_size_);
434  }
435 
445  const std::string& element_type_name
446  ) {
447  return (
448  type_name_to_creator_.find(element_type_name) !=
449  type_name_to_creator_.end()
450  );
451  }
452 
462  const std::string& element_typeid_name
463  ) {
464  return (
465  typeid_name_to_type_name_.find(element_typeid_name) !=
466  typeid_name_to_type_name_.end()
467  );
468  }
469 
477  const std::string& element_type_name,
478  index_t dimension
479  ) {
480  geo_assert(element_type_name_is_known(element_type_name));
481  return type_name_to_creator_[element_type_name]->
482  create_attribute_store(dimension);
483  }
484 
493  const std::string& element_typeid_name
494  ) {
495  geo_assert(element_typeid_name_is_known(element_typeid_name));
496  return typeid_name_to_type_name_[element_typeid_name];
497  }
498 
508  const std::string& element_type_name
509  ) {
510  geo_assert(element_type_name_is_known(element_type_name));
511  return type_name_to_typeid_name_[element_type_name];
512  }
513 
525  AttributeStoreCreator* creator,
526  const std::string& element_type_name,
527  const std::string& element_typeid_name
528  ) {
529  if(element_type_name_is_known(element_type_name)) {
530  Logger::warn("Attributes") << element_type_name
531  << " already registered"
532  << std::endl;
533  if(element_typeid_name_is_known(element_typeid_name)) {
534  bool already_registered_attribute_has_same_type = (
535  type_name_to_typeid_name_[element_type_name] ==
536  element_typeid_name
537  );
538  geo_assert(already_registered_attribute_has_same_type);
539  }
540  }
541  type_name_to_creator_[element_type_name] = creator;
542  typeid_name_to_type_name_[element_typeid_name] = element_type_name;
543  type_name_to_typeid_name_[element_type_name] = element_typeid_name;
544  }
545 
546  protected:
555  virtual void notify(
556  Memory::pointer base_addr, index_t size, index_t dim
557  );
558 
568 
577 
578 
579  protected:
580  index_t element_size_;
581  index_t dimension_;
582  Memory::pointer cached_base_addr_;
583  index_t cached_size_;
584  index_t cached_capacity_;
585  std::set<AttributeStoreObserver*> observers_;
586  Process::spinlock lock_;
587 
588  static std::map<std::string, AttributeStoreCreator_var>
589  type_name_to_creator_;
590 
591  static std::map<std::string, std::string>
592  typeid_name_to_type_name_;
593 
594  static std::map<std::string, std::string>
595  type_name_to_typeid_name_;
596 
597  friend class AttributeStoreObserver;
598  };
599 
600  /*********************************************************************/
601 
607  template <class T> class TypedAttributeStore : public AttributeStore {
608  public:
609 
617  AttributeStore(index_t(sizeof(T)),dim) {
618  }
619 
620  void resize(index_t new_size) override {
621  store_.resize(new_size*dimension_);
622  notify(
623  store_.empty() ? nullptr : Memory::pointer(store_.data()),
624  new_size,
625  dimension_
626  );
627  }
628 
629  void reserve(index_t new_capacity) override {
630  if(new_capacity > capacity()) {
631  store_.reserve(new_capacity*dimension_);
632  cached_capacity_ = new_capacity;
633  notify(
634  store_.empty() ? nullptr : Memory::pointer(store_.data()),
635  size(),
636  dimension_
637  );
638  }
639  }
640 
641  void clear(bool keep_memory=false) override {
642  if(keep_memory) {
643  store_.resize(0);
644  } else {
645  store_.clear();
646  }
647  notify(nullptr, 0, dimension_);
648  }
649 
650 
651  void redim(index_t dim) override {
652  if(dim == dimension()) {
653  return;
654  }
655  vector<T> new_store(size()*dim);
656  new_store.reserve(capacity()*dim);
657  index_t copy_dim = std::min(dim, dimension());
658  for(index_t i = 0; i < size(); ++i) {
659  for(index_t c = 0; c < copy_dim; ++c) {
660  new_store[dim * i + c] = store_[dimension_ * i + c];
661  }
662  }
663  store_.swap(new_store);
664  notify(
665  store_.empty() ? nullptr : Memory::pointer(store_.data()),
666  size(),
667  dim
668  );
669  }
670 
672  const std::string& type_name
673  ) const override {
674  return type_name == typeid(T).name();
675  }
676 
677  std::string element_typeid_name() const override {
678  return typeid(T).name();
679  }
680 
681  AttributeStore* clone() const override {
682  TypedAttributeStore<T>* result =
684  result->resize(size());
685  result->store_ = store_;
686  return result;
687  }
688 
689  vector<T>& get_vector() {
690  return store_;
691  }
692 
693  void scale_item(index_t to, double s) override {
694  geo_assert(to < size());
695  for(index_t i=0; i<dimension_; ++i) {
696  scale_value(store_[to*dimension_+i], s);
697  }
698  }
699 
700  void madd_item(index_t to, double s, index_t from) override {
701  geo_assert(from < size());
702  geo_assert(to < size());
703  for(index_t i=0; i<dimension_; ++i) {
704  madd_value(
705  store_[to*dimension_+i], s, store_[from*dimension_+i]
706  );
707  }
708  }
709 
710  protected:
711  void notify(
712  Memory::pointer base_addr, index_t size, index_t dim
713  ) override {
714  AttributeStore::notify(base_addr, size, dim);
715  geo_assert(size*dim <= store_.size());
716  }
717 
718  template<class TT> static void scale_value(TT& to, double s) {
719  geo_argused(to);
720  geo_argused(s);
721  }
722 
723  static void scale_value(uint8_t& to, double s) {
724  to = uint8_t(double(to)*s != 0.0);
725  }
726 
727  static void scale_value(int32_t& to, double s) {
728  to = int32_t(double(to)*s);
729  }
730 
731  static void scale_value(uint32_t& to, double s) {
732  to = uint32_t(double(to)*s);
733  }
734 
735  static void scale_value(float& to, double s) {
736  to = float(double(to)*s);
737  }
738 
739  static void scale_value(double& to, double s) {
740  to *= s;
741  }
742 
743  template<class TT> static void madd_value(TT& to, double s, TT& from) {
744  geo_argused(to);
745  geo_argused(s);
746  geo_argused(from);
747  }
748 
749  static void madd_value(uint8_t& to, double s, uint8_t& from) {
750  to = uint8_t(double(to) + s*double(from) != 0.0);
751  }
752 
753  static void madd_value(int32_t& to, double s, int32_t& from) {
754  to = int32_t(double(to) + s*double(from));
755  }
756 
757  static void madd_value(uint32_t& to, double s, uint32_t& from) {
758  to = uint32_t(double(to) + s*double(from));
759  }
760 
761  static void madd_value(float& to, double s, float& from) {
762  to = float(double(to) + s*double(from));
763  }
764 
765  static void madd_value(double& to, double s, double& from) {
766  to += s*from;
767  }
768 
769 
770  private:
771  vector<T> store_;
772  };
773 
774  /*********************************************************************/
775 
780  template <class T>
782  public:
787  return new TypedAttributeStore<T>(dim);
788  }
789  };
790 
791  /*********************************************************************/
792 
797  template <class T> class geo_register_attribute_type {
798  public:
808  geo_register_attribute_type(const std::string& type_name) {
810  new TypedAttributeStoreCreator<T>, type_name, typeid(T).name()
811  );
812  if(type_name == "bool") {
814  type_name,
817  );
818  } else {
820  type_name,
821  read_ascii_attribute<T>,
822  write_ascii_attribute<T>
823  );
824  }
825  }
826  };
827 
828  /*********************************************************************/
829 
834  class GEOGRAM_API AttributesManager {
835  public:
840 
841 
846 
852  index_t nb() const {
853  return index_t(attributes_.size());
854  }
855 
862 
869  index_t size() const {
870  return size_;
871  }
872 
878  index_t capacity() const {
879  return capacity_;
880  }
881 
888  void resize(index_t new_size);
889 
896  void reserve(index_t new_capacity);
897 
906  void clear(bool keep_attributes, bool keep_memory = false);
907 
908 
912  void zero();
913 
922  void bind_attribute_store(const std::string& name, AttributeStore* as);
923 
930  AttributeStore* find_attribute_store(const std::string& name);
931 
939  const std::string& name
940  ) const;
941 
942 
949  bool is_defined(const std::string& name) const {
950  return (find_attribute_store(name) != nullptr);
951  }
952 
958  void delete_attribute_store(const std::string& name);
959 
966 
983  const vector<index_t>& permutation
984  );
985 
1001  void compress(const vector<index_t>& old2new);
1002 
1007  void copy(const AttributesManager& rhs);
1008 
1009 
1016  void copy_item(index_t to, index_t from);
1017 
1024 
1025 
1030  void zero_item(index_t to);
1031 
1039  void scale_item(index_t to, double s);
1040 
1049  void madd_item(index_t to, double s, index_t from);
1050 
1060  const std::string& name, const std::string& new_name
1061  );
1062 
1072  const std::string& old_name, const std::string& new_name
1073  );
1074 
1075  private:
1084 
1092  const AttributesManager& operator=(const AttributesManager& rhs);
1093 
1094  private:
1095  index_t size_;
1096  index_t capacity_;
1097  std::map<std::string, AttributeStore*> attributes_;
1098  } ;
1099 
1100 
1101  /*********************************************************************/
1102 
1103 
1108  template <class T> class AttributeBase : public AttributeStoreObserver {
1109  public:
1110 
1115  manager_(nullptr),
1116  store_(nullptr) {
1117  }
1118 
1128  AttributeBase(AttributesManager& manager, const std::string& name) :
1129  manager_(nullptr),
1130  store_(nullptr) {
1131  bind(manager, name);
1132  }
1133 
1139  bool is_bound() const {
1140  return (store_ != nullptr && !disconnected_);
1141  }
1142 
1147  void unbind() {
1148  geo_assert(is_bound());
1149  // If the AttributesManager was destroyed before, do not
1150  // do anything. This can occur in Lua scripting when using
1151  // Attribute wrapper objects.
1152  if(!disconnected_) {
1153  unregister_me(store_);
1154  }
1155  manager_ = nullptr;
1156  store_ = nullptr;
1157  }
1158 
1168  void bind(AttributesManager& manager, const std::string& name) {
1169  geo_assert(!is_bound());
1170  manager_ = &manager;
1171  store_ = manager_->find_attribute_store(name);
1172  if(store_ == nullptr) {
1173  store_ = new TypedAttributeStore<T>();
1174  manager_->bind_attribute_store(name,store_);
1175  } else {
1176  geo_assert(store_->elements_type_matches(typeid(T).name()));
1177  }
1178  register_me(store_);
1179  }
1180 
1181 
1191  AttributesManager& manager, const std::string& name
1192  ) {
1193  geo_assert(!is_bound());
1194  manager_ = &manager;
1195  store_ = manager_->find_attribute_store(name);
1196  if(store_ != nullptr) {
1197  geo_assert(store_->elements_type_matches(typeid(T).name()));
1198  register_me(store_);
1199  return true;
1200  }
1201  return false;
1202  }
1203 
1213  AttributesManager& manager, const std::string& name
1214  ) {
1215  if( is_bound() ) {
1216  unbind();
1217  }
1218  store_ = manager.find_attribute_store(name);
1219  if(store_ != nullptr) {
1220  if( !store_->elements_type_matches(typeid(T).name()) ) {
1221  store_ = nullptr;
1222  return false;
1223  }
1224  manager_ = &manager;
1225  register_me(store_);
1226  return true;
1227  }
1228  return false;
1229  }
1230 
1239  const std::string& name,
1241  ) {
1242  geo_assert(!is_bound());
1243  manager_ = &manager;
1244  geo_assert(manager_->find_attribute_store(name) == nullptr);
1245  store_ = new TypedAttributeStore<T>(dimension);
1246  manager_->bind_attribute_store(name,store_);
1247  register_me(store_);
1248  }
1249 
1256  void destroy() {
1257  geo_assert(is_bound());
1258  unregister_me(store_);
1259  manager_->delete_attribute_store(store_);
1260  store_ = nullptr;
1261  manager_ = nullptr;
1262  }
1263 
1273  void redim(index_t new_dim) {
1274  geo_assert(is_bound());
1275  store_->redim(new_dim);
1276  }
1277 
1286  if(is_bound()) {
1287  unbind();
1288  }
1289  }
1290 
1291 
1299  static bool is_defined(
1300  AttributesManager& manager, const std::string& name,
1301  index_t dim = 0
1302  ) {
1304  return (
1305  store != nullptr &&
1306  store->elements_type_matches(typeid(T).name()) &&
1307  ((dim == 0) || (store->dimension() == dim))
1308  );
1309  }
1310 
1315  index_t size() const {
1316  return size_;
1317  }
1318 
1323  void zero() {
1325  store_->zero();
1326  }
1327 
1338  return(
1339  dynamic_cast<TypedAttributeStore<T>*>(store_) != nullptr
1340  );
1341  }
1342 
1354  TypedAttributeStore<T>* typed_store =
1355  dynamic_cast<TypedAttributeStore<T>*>(store_);
1356  geo_assert(typed_store != nullptr);
1357  return typed_store->get_vector();
1358  }
1359 
1366  const vector<T>& get_vector() const {
1367  TypedAttributeStore<T>* typed_store =
1368  dynamic_cast<TypedAttributeStore<T>*>(store_);
1369  geo_assert(typed_store != nullptr);
1370  return typed_store->get_vector();
1371  }
1372 
1378  return manager_;
1379  }
1380 
1381  protected:
1382  AttributesManager* manager_;
1383  AttributeStore* store_;
1384  } ;
1385 
1386  /*********************************************************************/
1387 
1394  template <class T> class Attribute : public AttributeBase<T> {
1395  public:
1396  typedef AttributeBase<T> superclass;
1397 
1403  static void static_test_type() {
1404  // Attributes are only implemented for classes that
1405  // can be copied with memcpy() and read/written to
1406  // files using fread()/fwrite()
1407 #if __GNUG__ && __GNUC__ < 5 && !__clang__
1408  static_assert(
1409  __has_trivial_copy(T),
1410  "Attribute only implemented for types that can be copied with memcpy()"
1411  );
1412 #else
1413  static_assert(
1414  std::is_trivially_copyable<T>::value,
1415  "Attribute only implemented for types that can be copied with memcpy()"
1416  );
1417 #endif
1418  }
1419 
1424  static_test_type();
1425  }
1426 
1436  Attribute(AttributesManager& manager, const std::string& name) :
1437  superclass(manager, name) {
1438  static_test_type();
1439  }
1440 
1448  return ((T*)(void*)superclass::base_addr_)[i];
1449  }
1450 
1456  const T& operator[](index_t i) const {
1458  return ((const T*)(void*)superclass::base_addr_)[i];
1459  }
1460 
1466  void fill(const T& val) {
1467  for(index_t i=0; i<superclass::nb_elements(); ++i) {
1468  (*this)[i] = val;
1469  }
1470  }
1471 
1478  void copy(const Attribute<T>& rhs) {
1479  geo_assert(rhs.size() == superclass::size());
1481  for(index_t i=0; i<superclass::nb_elements(); ++i) {
1482  (*this)[i] = rhs[i];
1483  }
1484  }
1485 
1490  T* data() {
1491  return (T*)AttributeStoreObserver::base_addr_;
1492  }
1493 
1498  const T* data() const {
1499  return (const T*)AttributeStoreObserver::base_addr_;
1500  }
1501 
1502 
1503  private:
1507  Attribute(const Attribute<T>& rhs);
1511  Attribute<T>& operator=(const Attribute<T>& rhs);
1512  };
1513 
1514  /*********************************************************************/
1515 
1524  template <> class Attribute<bool> : public AttributeBase<Numeric::uint8> {
1525  public:
1527 
1528  Attribute() : superclass() {
1529  }
1530 
1531  Attribute(AttributesManager& manager, const std::string& name) :
1532  superclass(manager,name) {
1533  }
1534 
1535  class BoolAttributeAccessor;
1536 
1537 
1542  class ConstBoolAttributeAccessor {
1543  public:
1548  const Attribute<bool>& attribute,
1549  index_t index
1550  ) :
1551  attribute_(&attribute),
1552  index_(index) {
1553  }
1554 
1559  operator bool() const {
1560  return (attribute_->element(index_) != 0);
1561  }
1562 
1563  private:
1564  const Attribute<bool>* attribute_;
1565  index_t index_;
1566 
1567  friend class BoolAttributeAccessor;
1568  };
1569 
1574  class BoolAttributeAccessor {
1575  public:
1580  Attribute<bool>& attribute,
1581  index_t index
1582  ) :
1583  attribute_(&attribute),
1584  index_(index) {
1585  }
1586 
1591  operator bool() const {
1592  return (attribute_->element(index_) != 0);
1593  }
1594 
1600  BoolAttributeAccessor(const BoolAttributeAccessor& rhs) {
1601  attribute_ = rhs.attribute_;
1602  index_ = rhs.index_;
1603  }
1604 
1609  BoolAttributeAccessor& operator=(bool x) {
1610  attribute_->element(index_) = Numeric::uint8(x);
1611  return *this;
1612  }
1613 
1619  BoolAttributeAccessor& operator=(
1620  const BoolAttributeAccessor& rhs
1621  ) {
1622  if(&rhs != this) {
1623  attribute_->element(index_) =
1624  rhs.attribute_->element(rhs.index_);
1625  }
1626  return *this;
1627  }
1628 
1634  BoolAttributeAccessor& operator=(
1635  const ConstBoolAttributeAccessor& rhs
1636  ) {
1637  attribute_->element(index_) =
1638  rhs.attribute_->element(rhs.index_);
1639  return *this;
1640  }
1641 
1642  private:
1643  Attribute<bool>* attribute_;
1644  index_t index_;
1645  };
1646 
1647 
1648  BoolAttributeAccessor operator[](index_t i) {
1649  return BoolAttributeAccessor(*this,i);
1650  }
1651 
1652  ConstBoolAttributeAccessor operator[](index_t i) const {
1653  return ConstBoolAttributeAccessor(*this,i);
1654  }
1655 
1661  void fill(bool val) {
1662  for(index_t i=0; i<superclass::nb_elements(); ++i) {
1663  element(i) = Numeric::uint8(val);
1664  }
1665  }
1666 
1667  protected:
1668 
1669  friend class BoolAttributeAccessor;
1670  friend class ConstBoolAttributeAccessor;
1671 
1679  return ((Numeric::uint8*)superclass::base_addr_)[i];
1680  }
1681 
1687  const Numeric::uint8& element(index_t i) const {
1689  return ((const Numeric::uint8*)superclass::base_addr_)[i];
1690  }
1691 
1692  private:
1696  Attribute(const Attribute<bool>& rhs);
1700  Attribute<bool>& operator=(const Attribute<bool>& rhs);
1701  } ;
1702 
1703  /***********************************************************/
1704 
1709  class GEOGRAM_API ScalarAttributeAdapterBase :
1710  public AttributeStoreObserver {
1711 
1712  public:
1717  ET_NONE=0,
1718  ET_UINT8=1,
1719  ET_INT8=2,
1720  ET_UINT32=3,
1721  ET_INT32=4,
1722  ET_FLOAT32=5,
1723  ET_FLOAT64=6,
1724  ET_VEC2=7,
1725  ET_VEC3=8
1726  };
1727 
1728 
1733  class Accessor {
1734  public:
1735  Accessor(
1736  ScalarAttributeAdapterBase& attribute,
1737  index_t index
1738  ) : attribute_(attribute), index_(index) {
1739  }
1740 
1741  operator double() const {
1742  return attribute_.get_element_as_double(index_);
1743  }
1744 
1745  void operator=(double x) {
1746  attribute_.set_element_as_double(index_, x);
1747  }
1748 
1749  private:
1750  ScalarAttributeAdapterBase& attribute_;
1751  index_t index_;
1752  };
1753 
1759  public:
1760  ConstAccessor(
1761  const ScalarAttributeAdapterBase& attribute,
1762  index_t index
1763  ) : attribute_(attribute), index_(index) {
1764  }
1765 
1766  operator double() const {
1767  return attribute_.get_element_as_double(index_);
1768  }
1769 
1770  private:
1771  const ScalarAttributeAdapterBase& attribute_;
1772  index_t index_;
1773  };
1774 
1779  manager_(nullptr),
1780  store_(nullptr),
1781  element_type_(ET_NONE),
1782  element_index_(index_t(-1)) {
1783  }
1784 
1795  const AttributesManager& manager, const std::string& name
1796  ) :
1797  manager_(nullptr),
1798  store_(nullptr) {
1799  bind_if_is_defined(manager, name);
1800  }
1801 
1807  bool is_bound() const {
1808  return (store_ != nullptr);
1809  }
1810 
1815  void unbind() {
1816  geo_assert(is_bound());
1817  unregister_me(const_cast<AttributeStore*>(store_));
1818  manager_ = nullptr;
1819  store_ = nullptr;
1820  element_type_ = ET_NONE;
1821  element_index_ = index_t(-1);
1822  }
1823 
1834  const AttributesManager& manager, const std::string& name
1835  );
1836 
1845  if(is_bound()) {
1846  unbind();
1847  }
1848  }
1849 
1859  static bool is_defined(
1860  const AttributesManager& manager, const std::string& name
1861  );
1862 
1867  index_t size() const {
1868  return (store_ == nullptr) ? 0 : store_->size();
1869  }
1870 
1879  return element_type_;
1880  }
1881 
1889  return element_index_;
1890  }
1891 
1897  return store_;
1898  }
1899 
1900 
1908  static bool can_be_bound_to(const AttributeStore* store) {
1909  return element_type(store) != ET_NONE;
1910  }
1911 
1920 
1921  protected:
1930  static std::string attribute_base_name(const std::string& name);
1931 
1940  static index_t attribute_element_index(const std::string& name);
1941 
1950 
1958  double get_element_as_double(index_t i) const {
1959  double result = 0.0;
1960  switch(element_type()) {
1961  case ET_UINT8:
1962  result = double(get_element<Numeric::uint8>(i));
1963  break;
1964  case ET_INT8:
1965  result = double(get_element<Numeric::int8>(i));
1966  break;
1967  case ET_UINT32:
1968  result = double(get_element<Numeric::uint32>(i));
1969  break;
1970  case ET_INT32:
1971  result = double(get_element<Numeric::int32>(i));
1972  break;
1973  case ET_FLOAT32:
1974  result = double(get_element<Numeric::float32>(i));
1975  break;
1976  case ET_FLOAT64:
1977  result = double(get_element<Numeric::float64>(i));
1978  break;
1979  case ET_VEC2:
1980  result = double(get_element<Numeric::float64>(i,2));
1981  break;
1982  case ET_VEC3:
1983  result = double(get_element<Numeric::float64>(i,3));
1984  break;
1985  case ET_NONE:
1987  }
1988  return result;
1989  }
1990 
1999  template <class T> T get_element(index_t i,index_t multiplier=1) const {
2000  geo_debug_assert(is_bound());
2001  geo_debug_assert(i < size());
2002  return static_cast<const T*>(store_->data())[
2003  (i * store_->dimension() * multiplier) +
2004  element_index_
2005  ];
2006  }
2007 
2014  double set_element_as_double(index_t i, double value) {
2015  double result = 0.0;
2016  switch(element_type()) {
2017  case ET_UINT8:
2018  set_element<Numeric::uint8>(Numeric::uint8(value), i);
2019  break;
2020  case ET_INT8:
2021  set_element<Numeric::int8>(Numeric::int8(value),i);
2022  break;
2023  case ET_UINT32:
2024  set_element<Numeric::uint32>(Numeric::uint32(value),i);
2025  break;
2026  case ET_INT32:
2027  set_element<Numeric::int32>(Numeric::int32(value),i);
2028  break;
2029  case ET_FLOAT32:
2030  set_element<Numeric::float32>(Numeric::float32(value),i);
2031  break;
2032  case ET_FLOAT64:
2033  set_element<Numeric::float64>(Numeric::float64(value),i);
2034  break;
2035  case ET_VEC2:
2036  set_element<Numeric::float64>(Numeric::float64(value),i,2);
2037  break;
2038  case ET_VEC3:
2039  set_element<Numeric::float64>(Numeric::float64(value),i,3);
2040  break;
2041  case ET_NONE:
2043  }
2044  return result;
2045  }
2046 
2056  template <class T> void set_element(
2057  T value, index_t i, index_t multiplier=1
2058  ) const {
2059  geo_debug_assert(is_bound());
2060  geo_debug_assert(i < size());
2061  const_cast<T*>(static_cast<const T*>(store_->data()))[
2062  (i * store_->dimension() * multiplier) +
2063  element_index_
2064  ] = value;
2065  }
2066 
2067  protected:
2068  const AttributesManager* manager_;
2069  const AttributeStore* store_;
2070  ElementType element_type_;
2071  index_t element_index_;
2072  };
2073 
2074  /***********************************************************/
2075 
2081  public:
2083  }
2084 
2086  const AttributesManager& manager, const std::string& name
2087  ) : ScalarAttributeAdapterBase(manager, name) {
2088  }
2089 
2097  double operator[](index_t i) {
2098  return get_element_as_double(i);
2099  }
2100  };
2101 
2102  /***********************************************************/
2103 
2109  public:
2111  }
2112 
2114  const AttributesManager& manager, const std::string& name
2115  ) : ScalarAttributeAdapterBase(manager, name) {
2116  }
2117 
2118  Accessor operator[](index_t i) {
2119  return Accessor(*this, i);
2120  }
2121 
2122  ConstAccessor operator[](index_t i) const {
2123  return ConstAccessor(*this, i);
2124  }
2125 
2126  protected:
2127  };
2128 
2129 
2130 }
2131 
2132 #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.
Definition: attributes.h:1108
void create_vector_attribute(AttributesManager &manager, const std::string &name, index_t dimension)
Creates and binds a new vector attribute.
Definition: attributes.h:1237
~AttributeBase()
Attribute destructor.
Definition: attributes.h:1285
index_t size() const
Gets the size.
Definition: attributes.h:1315
AttributeBase(AttributesManager &manager, const std::string &name)
Creates or retrieves a persistent attribute attached to a given AttributesManager.
Definition: attributes.h:1128
void zero()
Sets all the elements of this Attribute to zero.
Definition: attributes.h:1323
bool is_bound() const
Tests whether an Attribute is bound.
Definition: attributes.h:1139
void unbind()
Unbinds this Attribute.
Definition: attributes.h:1147
void redim(index_t new_dim)
Sets the dimension.
Definition: attributes.h:1273
void destroy()
Destroys this attribute in the AttributesManager.
Definition: attributes.h:1256
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 tyopes...
Definition: attributes.h:1212
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...
Definition: attributes.h:1299
bool can_get_vector()
Tests whether get_vector() can be called on this Attribute.
Definition: attributes.h:1337
AttributesManager * manager() const
Gets the AttributesManager this Attribute is bound to.
Definition: attributes.h:1377
const vector< T > & get_vector() const
Gets a const reference to the internal vector<T> used to store the attribute.
Definition: attributes.h:1366
vector< T > & get_vector()
Gets a reference to the internal vector<T> used to store the attribute.
Definition: attributes.h:1353
AttributeBase()
Creates an uninitialized (unbound) Attribute.
Definition: attributes.h:1114
void bind(AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager.
Definition: attributes.h:1168
bool bind_if_is_defined(AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager if it already exists in the AttributesManager.
Definition: attributes.h:1190
Internal class for creating an AttributeStore from the type name of its elements.
Definition: attributes.h:163
~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: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
void disconnect()
Disconnects this AttributeStoreObserver from its AttributeStore.
Definition: attributes.h:141
void unregister_me(AttributeStore *store)
Unregisters this observer from an AttributeStore.
index_t dimension() const
Gets the dimension.
Definition: attributes.h:108
Notifies a set of AttributeStoreObservers each time the stored array changes size and/or base address...
Definition: attributes.h:195
AttributeStore(index_t elemsize, index_t dim=1)
AttributeStore constructor.
bool has_observers() const
Tests whether observers listen to this AttributeStore.
Definition: attributes.h:276
void zero_item(index_t to)
Sets an item to zero.
Definition: attributes.h:378
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:507
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:524
const void * data() const
Gets a pointer to the stored data.
Definition: attributes.h:424
index_t size() const
Gets the size.
Definition: attributes.h:238
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...
index_t capacity() const
Gets the capacity.
Definition: attributes.h:247
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:444
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:363
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:461
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 AttributeStore * clone() const =0
Creates a new AttributeStore that is a carbon copy of this AttributeStore.
virtual void scale_item(index_t to, double s)
Scales an item.
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:476
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:285
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:492
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.
void * data()
Gets a pointer to the stored data.
Definition: attributes.h:416
size_t element_size() const
Gets the element size.
Definition: attributes.h:432
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.
Definition: attributes.h:1579
BoolAttributeAccessor & operator=(const ConstBoolAttributeAccessor &rhs)
Copies a bool from another attribute.
Definition: attributes.h:1634
BoolAttributeAccessor & operator=(bool x)
Assigns a bool to a BoolAttributeAccessor.
Definition: attributes.h:1609
BoolAttributeAccessor(const BoolAttributeAccessor &rhs)
Copy-constructor.
Definition: attributes.h:1600
BoolAttributeAccessor & operator=(const BoolAttributeAccessor &rhs)
Copies a bool from another attribute.
Definition: attributes.h:1619
ConstBoolAttributeAccessor(const Attribute< bool > &attribute, index_t index)
ConstBoolAttributeAccessor constructor.
Definition: attributes.h:1547
Specialization of Attribute for booleans.
Definition: attributes.h:1524
Numeric::uint8 & element(index_t i)
Gets a modifiable element by index.
Definition: attributes.h:1677
const Numeric::uint8 & element(index_t i) const
Gets an element by index.
Definition: attributes.h:1687
void fill(bool val)
Sets all the elements in this attribute to a specified value.
Definition: attributes.h:1661
Manages an attribute attached to a set of object.
Definition: attributes.h:1394
T & operator[](index_t i)
Gets a modifiable element by index.
Definition: attributes.h:1446
Attribute(AttributesManager &manager, const std::string &name)
Creates or retrieves a persistent attribute attached to a given AttributesManager.
Definition: attributes.h:1436
Attribute()
Creates an uninitialized (unbound) Attribute.
Definition: attributes.h:1423
const T & operator[](index_t i) const
Gets an element by index.
Definition: attributes.h:1456
void fill(const T &val)
Sets all the elements in this attribute to a specified value.
Definition: attributes.h:1466
T * data()
Gets the pointer to the data.
Definition: attributes.h:1490
void copy(const Attribute< T > &rhs)
Copies all the values from another attribute.
Definition: attributes.h:1478
const T * data() const
Gets the pointer to the data.
Definition: attributes.h:1498
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...
Definition: attributes.h:1403
Managers a set of attributes attached to an object.
Definition: attributes.h:834
void delete_attribute_store(AttributeStore *as)
Deletes an AttributeStore.
AttributeStore * find_attribute_store(const std::string &name)
Finds an AttributeStore by name.
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:852
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.
void apply_permutation(const vector< index_t > &permutation)
Applies a permutation to the stored attributes.
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:949
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:869
void clear(bool keep_attributes, bool keep_memory=false)
Clears this AttributesManager.
index_t capacity() const
Gets the capacity.
Definition: attributes.h:878
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.
const AttributeStore * find_attribute_store(const std::string &name) const
Finds an AttributeStore by name.
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.
Definition: attributes.h:2080
double operator[](index_t i)
Gets a property value.
Definition: attributes.h:2097
Readwrite access to an attribute as a double regardless its type.
Definition: attributes.h:2108
Accessor class used by ScalarAttributeAdapter to implement indexing operator.
Definition: attributes.h:1733
Accessor class used by ScalarAttributeAdapter to implement indexing operator (const version).
Definition: attributes.h:1758
Access to an attribute as a double regardless its type.
Definition: attributes.h:1710
index_t element_index() const
Gets the element index.
Definition: attributes.h:1888
T get_element(index_t i, index_t multiplier=1) const
Gets an element.
Definition: attributes.h:1999
ElementType
Internal representation of the attribute.
Definition: attributes.h:1716
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.
Definition: attributes.h:1807
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.
Definition: attributes.h:1958
~ScalarAttributeAdapterBase()
ReadonlyScalarAttributeAdapterBase destructor.
Definition: attributes.h:1844
static ElementType element_type(const AttributeStore *store)
Gets the element type stored in an AttributeStore.
ScalarAttributeAdapterBase()
ScalarAttributeAdapterBase constructor.
Definition: attributes.h:1778
static bool can_be_bound_to(const AttributeStore *store)
Tests whether a ScalarAttributeAdapterBase can be bound to a given attribute store.
Definition: attributes.h:1908
void unbind()
Unbinds this Attribute.
Definition: attributes.h:1815
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.
Definition: attributes.h:1794
double set_element_as_double(index_t i, double value)
Sets an attribute value.
Definition: attributes.h:2014
void set_element(T value, index_t i, index_t multiplier=1) const
Sets an element.
Definition: attributes.h:2056
const AttributeStore * attribute_store() const
Gets the AttributeStore.
Definition: attributes.h:1896
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.
Definition: attributes.h:1867
ElementType element_type() const
Gets the internal representation of the elements.
Definition: attributes.h:1878
A smart pointer with reference-counted copy semantics.
Definition: smart_pointer.h:76
Implementation of AttributeStoreCreator for a specific type.
Definition: attributes.h:781
AttributeStore * create_attribute_store(index_t dim) override
Creates a new attribute store.
Definition: attributes.h:786
Stores an array of elements of a given type, and notifies a set of AttributeStoreObservers each time ...
Definition: attributes.h:607
void scale_item(index_t to, double s) override
Scales an item.
Definition: attributes.h:693
TypedAttributeStore(index_t dim=1)
Creates a new empty attribute store.
Definition: attributes.h:616
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:711
void clear(bool keep_memory=false) override
Resizes this AttributeStore to 0.
Definition: attributes.h:641
void resize(index_t new_size) override
Resizes this AttributeStore.
Definition: attributes.h:620
std::string element_typeid_name() const override
Gets the typeid name of the element type stored in this AttributeStore.
Definition: attributes.h:677
void reserve(index_t new_capacity) override
Reserves memory.
Definition: attributes.h:629
bool elements_type_matches(const std::string &type_name) const override
Tests whether this AttributeStore stores elements of a given type.
Definition: attributes.h:671
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:700
void redim(index_t dim) override
Sets the dimension.
Definition: attributes.h:651
AttributeStore * clone() const override
Creates a new AttributeStore that is a carbon copy of this AttributeStore.
Definition: attributes.h:681
Helper class to register new attribute types.
Definition: attributes.h:797
geo_register_attribute_type(const std::string &type_name)
geo_register_attribute_type constructor
Definition: attributes.h:808
Common include file, providing basic definitions. Should be included before anything else by all head...
Functions to read and write structured files.
Types and functions for memory manipulation.
byte * pointer
Pointer to unsigned byte(s)
Definition: memory.h:104
void clear(void *addr, size_t size)
Clears a memory block.
Definition: memory.h:116
void copy(void *to, const void *from, size_t size)
Copies a memory block.
Definition: memory.h:129
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.
Definition: thread_sync.h:149
Global Vorpaline namespace.
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:188
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.