MEPP2 Project
AIFProperties.h
Go to the documentation of this file.
1 // Copyright (c) 2012-2019 University of Lyon and CNRS (France).
2 // All rights reserved.
3 //
4 // This file is part of MEPP2; you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as
6 // published by the Free Software Foundation; either version 3 of
7 // the License, or (at your option) any later version.
8 //
9 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 #pragma once
12 
13 #include <vector>
14 #include <limits>
15 #include <stdexcept>
16 #include <cmath>
17 
18 namespace FEVV {
19 namespace DataStructures {
20 namespace AIF {
21 template< typename CoordinateT = double, unsigned short DIM = 3 >
22 class AIFVector;
23 /*
24  * The class to store vertex coordinates.
25  * It extends std::array<...,3>
26  * with a constructor that takes 3 coordinates.
27  * See FEVV/Filters/Generic/scaling.hpp usecase.
28  */
29 template< typename CoordinateT = double, unsigned short DIM = 3 >
30 class AIFPoint : public std::array< CoordinateT, DIM >
31 {
32 public:
33  typedef CoordinateT CoordinateType;
34  typedef std::array< CoordinateType, DIM > SuperClass;
35  // TODO-elo refactor all function to handle DIM!=3 case !
36 
40  AIFPoint(void)
41  {
42  if(DIM != 3)
43  throw std::runtime_error("AIFPoint only support dim=3 for now.");
44 
45  (*this)[0] = 0;
46  (*this)[1] = 0;
47  (*this)[2] = 0;
48  }
49 
54  {
55  if(DIM != 3)
56  throw std::runtime_error("AIFPoint only support dim=3 for now.");
57 
58  (*this)[0] = x;
59  (*this)[1] = y;
60  (*this)[2] = z;
61  }
62 
70  {
72  (*this)[0] + other[0], (*this)[1] + other[1], (*this)[2] + other[2]);
73  }
74 
81  friend std::ostream &operator<<(std::ostream &stream,
83  {
84  // stream << "("; // do not add this to get the same output as CGAL or
85  for(auto itVal = p.begin(); itVal != p.end(); ++itVal)
86  {
87  stream << (*itVal);
88  if(itVal != (p.end() - 1))
89  stream << " ";
90  }
91  // stream << ")";
92 
93  return stream;
94  }
95 
103  {
105  (*this)[0] - other[0], (*this)[1] - other[1], (*this)[2] - other[2]);
106  }
114  {
116  (*this)[0] + v[0], (*this)[1] + v[1], (*this)[2] + v[2]);
117  }
118 
125  {
126  if((*this)[0] < p[0])
127  return true;
128  else if((*this)[0] > p[0])
129  return false;
130 
131  if((*this)[1] < p[1])
132  return true;
133  else if((*this)[1] > p[1])
134  return false;
135 
136  if((*this)[2] < p[2])
137  return true;
138  else
139  return false;
140  }
141 
148  {
149  if( this == &p )
150  return true;
151 
152  if( fabs((*this)[0] - p[0]) > std::numeric_limits<CoordinateType>::epsilon() )
153  return false;
154 
155  if( fabs((*this)[1] - p[1]) > std::numeric_limits<CoordinateType>::epsilon() )
156  return false;
157 
158  if( fabs((*this)[2] - p[2]) > std::numeric_limits<CoordinateType>::epsilon() )
159  return false;
160 
161  return true;
162  }
163 };
164 
165 
166 /*
167  * A class to store a vector (usefull for normals).
168  * It extends std::array<...,3>
169  * with a constructor that takes 3 coordinates.
170  */
171 template< typename CoordinateT /*=double*/, unsigned short DIM /*=3*/ >
172 class AIFVector : public std::array< CoordinateT, DIM >
173 {
174 public:
175  typedef CoordinateT CoordinateType;
176  // TODO-elo refactor all function to handle DIM!=3 case !
177 
181  AIFVector(void)
182  {
183  if(DIM != 3)
184  throw std::runtime_error("AIFVector only support dim=3 for now.");
185 
186  (*this)[0] = 0;
187  (*this)[1] = 0;
188  (*this)[2] = 0;
189  }
190 
195  {
196  if(DIM != 3)
197  throw std::runtime_error("AIFVector only support dim=3 for now.");
198 
199  (*this)[0] = x;
200  (*this)[1] = y;
201  (*this)[2] = z;
202  }
203 
208  CoordinateType length(void) const
209  {
210  CoordinateType tmp = 0;
211  for(auto v : *this)
212  tmp += v * v;
213  return sqrt(tmp);
214  }
215 
223  {
224  return AIFVector(
225  (*this)[0] + other[0], (*this)[1] + other[1], (*this)[2] + other[2]);
226  }
234  {
235  return AIFVector(
236  (*this)[0] - other[0], (*this)[1] - other[1], (*this)[2] - other[2]);
237  }
244  {
246  (*this)[0] / k, (*this)[1] / k, (*this)[2] / k);
247  }
254  double operator*(const AIFVector< CoordinateType, DIM > &other) const
255  {
256  return ((*this)[0] * other[0] + (*this)[1] * other[1] +
257  (*this)[2] * other[2]);
258  }
265  {
267  (*this)[0] * k, (*this)[1] * k, (*this)[2] * k);
268  }
276  {
277  return p + *this;
278  }
279 
287  {
288  if((*this)[0] < v[0])
289  return true;
290  else if((*this)[0] > v[0])
291  return false;
292 
293  if((*this)[1] < v[1])
294  return true;
295  else if((*this)[1] > v[1])
296  return false;
297 
298  if((*this)[2] < v[2])
299  return true;
300  else
301  return false;
302  }
303 
310  {
311  if( this == &v )
312  return true;
313 
314  if( fabs((*this)[0] - v[0]) > std::numeric_limits<CoordinateType>::epsilon() )
315  return false;
316 
317  if( fabs((*this)[1] - v[1]) > std::numeric_limits<CoordinateType>::epsilon() )
318  return false;
319 
320  if( fabs((*this)[2] - v[2]) > std::numeric_limits<CoordinateType>::epsilon() )
321  return false;
322 
323  return true;
324  }
325 
335  {
336  return v * s;
337  }
338 
345  friend std::ostream& operator<<(std::ostream& stream, const AIFVector<CoordinateType, DIM>& v)
346  {
347  //stream << "("; // do not add this to get the same output as CGAL or OpenMesh
348  for(auto itVal = v.begin(); itVal != v.end(); ++itVal)
349  {
350  stream << (*itVal);
351  if( itVal != (v.end() - 1) )
352  stream << " ";
353  }
354  //stream << ")";
355 
356  return stream;
357  }
358 };
359 
360 /*
361  * Base class for property maps.
362  * To be able to store pointers to property maps of different types
363  * in the same container.
364  */
366 {
367 public:
368  virtual ~BasePropertyMap() {}
369  virtual void forcePolymorphic(void) {}
370  virtual void remove(std::size_t /*idx*/, std::size_t /*cLastIdx*/) {}
371 };
372 
373 /*
374  * The purpose of this class is just to boost::vector_property_map
375  * with an operator[] that takes a vertex_descriptor as parameter.
376  * See FEVV/Filters/Generic/scaling.hpp usecase.
377  */
378 template< typename T >
379 class PropertyMap : public boost::vector_property_map< T >,
380  public BasePropertyMap
381 {
382 public:
384  using boost::vector_property_map< T >::operator[];
385 
387  T &operator[](const AIFVertex::ptr v) const { return (*this)[v->GetIndex()]; }
388 
390  T &operator[](const AIFEdge::ptr v) const { return (*this)[v->GetIndex()]; }
391 
393  T &operator[](const AIFFace::ptr v) const { return (*this)[v->GetIndex()]; }
394 
396  std::size_t size(void) const
397  {
398  return std::distance(this->storage_begin(), this->storage_end());
399  // no access to underlying std::vector :(
400  }
401 
407  void remove(std::size_t idx, std::size_t cLastIdx)
408  {
409  // Remove element at #idx in the property map.
410  // If #idx is not the last element of the cell container,
411  // then replace #idx by the last element of the cell container.
412  // element, then remove the last element.
413  // It's like AIFCellContainer::remove(), except that we can NOT remove
414  // the last element because it is not allowed by
415  // boost::vector_property_map interface.
416  // Hence the need to pass the cLastIdx parameter, because the size of
417  // the property map and the size of the cell container can be different.
418 
419  if(this->size() == 0 || cLastIdx >= this->size())
420  return;
421 
422  if(idx != cLastIdx)
423  (*this)[idx] = (*this)[cLastIdx];
424 
425  // not allowed by boost::vector_property_map
426  // this->pop_back();
427  }
428 };
429 
430 
431 /*
432  * An associative property map, needed for example to store texture
433  * per HalfEdge.
434  * Note1: boost::associative_property_map is an adaptor that converts an
435  * associative container such as std::map into property map ; the adaptor only
436  * retains a reference to the container, so the lifetime of the container must
437  * encompass the use of the adaptor ; see the description of
438  * boost::associative_property_map for more details. Note2: the present class
439  * completes boost::associative_property_map by also storing the underlying
440  * associative container.
441  */
442 template< typename KeyType, typename ValueType >
444  : public boost::associative_property_map< std::map< KeyType, ValueType > >,
445  public BasePropertyMap
446 {
447 public:
449  {
450  // at AssocPropertyMap creation, the boost::associative_property_map part
451  // of the object does not point to a valid associative container because
452  // none has been provided to boost::associative_property_map constructor;
453  // so the following line initializes the boost::associative_property_map
454  // part of the object with the container stored in the object
455  boost::associative_property_map< std::map< KeyType, ValueType > >::
456  operator=(
457  boost::associative_property_map< std::map< KeyType, ValueType > >(map));
458  }
459 
460 private:
461  std::map< KeyType, ValueType > map; // the real associative container
462 };
463 
464 
469 {
470 public:
472  {
473  // delete property maps
474  for(auto &m : m_PropertyMaps)
475  if(m.second != NULL)
476  {
477  delete m.second;
478  m.second = NULL; // in case of cross-reference
479  }
480  }
481 
488  bool isPropertyMap(const std::string &name) const
489  {
490  if(m_PropertyMaps.count(name) > 0)
491  return true;
492  else
493  return false;
494  }
502  bool isAPropertyMapStartingWithPrefix(const std::string &prefix) const
503  {
504  auto iter = m_PropertyMaps.lower_bound(prefix);
505  if( iter != m_PropertyMaps.end() )
506  {
507  return (iter->first.compare(0, prefix.size(), prefix) == 0);
508  }
509  return false;
510  }
511 
518  std::vector< std::string > GetPropertyMapNamesStartingWithPrefix(const std::string &prefix) const
519  {
520  std::vector< std::string > res;
521  auto iter = m_PropertyMaps.lower_bound(prefix);
522  auto iter_end = m_PropertyMaps.end();
523  for( ; iter!=iter_end; ++iter)
524  {
525  if (iter->first.compare(0, prefix.size(), prefix) == 0)
526  res.push_back(iter->first);
527  }
528  return res;
529  }
530 
537  template< typename T >
538  PropertyMap< T > *getPropertyMap(const std::string &name) const
539  {
540  if(!isPropertyMap(name))
541  throw std::runtime_error("Property map '" + name + "' doesn't exist.");
542 
543  PropertyMap< T > *pm =
544  dynamic_cast< PropertyMap< T > * >(m_PropertyMaps.at(name));
545  if(!pm)
546  throw std::runtime_error("Property map '" + name +
547  "' is not of the given type.");
548 
549  return pm;
550  }
551 
558  template< typename T >
559  PropertyMap< T > *addPropertyMap(const std::string &name)
560  {
561  if(!isPropertyMap(name))
562  {
563  // create property map
564  m_PropertyMaps[name] = new PropertyMap< T >;
565  }
566 
567  return getPropertyMap< T >(name);
568  }
569 
575  void removePropertyMap(const std::string &name)
576  {
577  if(!isPropertyMap(name))
578  return;
579 
580  delete m_PropertyMaps.at(name);
581  m_PropertyMaps.erase(name);
582  }
583 
587  void clear() {
588  // delete property maps
589  for (auto &m : m_PropertyMaps)
590  if (m.second != NULL)
591  {
592  delete m.second;
593  m.second = NULL; // in case of cross-reference
594  }
595  m_PropertyMaps.clear();
596  }
597 
605  template< typename T >
606  void setProperty(const std::string &name, std::size_t idx, const T &value)
607  {
608  PropertyMap< T > *prop_map = getPropertyMap< T >(name);
609  (*prop_map)[idx] = value;
610  }
611 
619  template< typename T >
620  T &getProperty(const std::string &name, std::size_t idx)
621  {
622  PropertyMap< T > *prop_map = getPropertyMap< T >(name);
623  return (*prop_map)[idx];
624  }
625 
633  template< typename T >
634  T &getProperty(const std::string &name, std::size_t idx) const
635  {
636  const PropertyMap< T > *prop_map = getPropertyMap< T >(name);
637  return (*prop_map)[idx];
638  }
639 
646  void removeProperties(std::size_t idx, std::size_t cLastIdx)
647  {
648  for(auto it : m_PropertyMaps)
649  {
650  auto map = it.second;
651  map->remove(idx, cLastIdx);
652  }
653  }
654 
655  //------------------Associative prop maps -------------------------------
656 
663  template< typename KeyType, typename ValueType >
665  getAssocPropertyMap(const std::string &name)
666  {
667  if(!isPropertyMap(name))
668  throw std::runtime_error("Property map '" + name + "' doesn't exist.");
669 
671  dynamic_cast< AssocPropertyMap< KeyType, ValueType > * >(
672  m_PropertyMaps.at(name));
673  if(!pm)
674  throw std::runtime_error("Property map '" + name +
675  "' is not of the given type.");
676 
677  return pm;
678  }
679 
686  template< typename KeyType, typename ValueType >
688  addAssocPropertyMap(const std::string &name)
689  {
690  if(!isPropertyMap(name))
691  {
692  // create property map
694  }
695 
696  return getAssocPropertyMap< KeyType, ValueType >(name);
697  }
698 
699 private:
700  std::map< const std::string, BasePropertyMap * > m_PropertyMaps;
701 };
702 
703 
704 } // namespace AIF
705 } // namespace DataStructures
706 } // namespace FEVV
707 
FEVV::DataStructures::AIF::AIFPoint::CoordinateType
CoordinateT CoordinateType
Definition: AIFProperties.h:33
FEVV::DataStructures::AIF::AssocPropertyMap
Definition: AIFProperties.h:446
FEVV::DataStructures::AIF::AIFPoint::operator+
const AIFPoint< CoordinateType, DIM > operator+(const AIFPoint< CoordinateType, DIM > &other) const
Definition: AIFProperties.h:69
FEVV::DataStructures::AIF::PropertyMapContainer::addAssocPropertyMap
AssocPropertyMap< KeyType, ValueType > * addAssocPropertyMap(const std::string &name)
Definition: AIFProperties.h:688
FEVV::DataStructures::AIF::AIFVertex::ptr
boost::shared_ptr< self > ptr
Definition: AIFVertex.hpp:47
FEVV::DataStructures::AIF::AIFVector::operator/
AIFVector< CoordinateType, DIM > operator/(double k) const
Definition: AIFProperties.h:243
FEVV::DataStructures::AIF::PropertyMapContainer::getProperty
T & getProperty(const std::string &name, std::size_t idx)
Definition: AIFProperties.h:620
FEVV::DataStructures::AIF::PropertyMapContainer::removePropertyMap
void removePropertyMap(const std::string &name)
Definition: AIFProperties.h:575
FEVV::DataStructures::AIF::BasePropertyMap::~BasePropertyMap
virtual ~BasePropertyMap()
Definition: AIFProperties.h:368
FEVV::DataStructures::AIF::AIFPoint::AIFPoint
AIFPoint(CoordinateType x, CoordinateType y, CoordinateType z)
Definition: AIFProperties.h:53
FEVV::DataStructures::AIF::PropertyMapContainer::isAPropertyMapStartingWithPrefix
bool isAPropertyMapStartingWithPrefix(const std::string &prefix) const
Definition: AIFProperties.h:502
FEVV::DataStructures::AIF::AIFVector::operator<
bool operator<(const AIFVector< CoordinateType, DIM > &v) const
Definition: AIFProperties.h:286
FEVV::DataStructures::AIF::PropertyMapContainer::getPropertyMap
PropertyMap< T > * getPropertyMap(const std::string &name) const
Definition: AIFProperties.h:538
FEVV::DataStructures::AIF::PropertyMapContainer::GetPropertyMapNamesStartingWithPrefix
std::vector< std::string > GetPropertyMapNamesStartingWithPrefix(const std::string &prefix) const
Definition: AIFProperties.h:518
FEVV::DataStructures::AIF::PropertyMapContainer::m_PropertyMaps
std::map< const std::string, BasePropertyMap * > m_PropertyMaps
Definition: AIFProperties.h:700
FEVV::DataStructures::AIF::BasePropertyMap::remove
virtual void remove(std::size_t, std::size_t)
Definition: AIFProperties.h:370
FEVV::DataStructures::AIF::BasePropertyMap
Definition: AIFProperties.h:366
FEVV::DataStructures::AIF::AIFFace::ptr
boost::shared_ptr< self > ptr
Definition: AIFFace.hpp:52
FEVV::DataStructures::AIF::AssocPropertyMap::map
std::map< KeyType, ValueType > map
Definition: AIFProperties.h:461
FEVV::DataStructures::AIF::PropertyMapContainer::setProperty
void setProperty(const std::string &name, std::size_t idx, const T &value)
Definition: AIFProperties.h:606
FEVV::DataStructures::AIF::AssocPropertyMap::AssocPropertyMap
AssocPropertyMap(void)
Definition: AIFProperties.h:448
FEVV::DataStructures::AIF::AIFVector::operator*
AIFVector< CoordinateType, DIM > operator*(double k) const
Definition: AIFProperties.h:264
FEVV::DataStructures::AIF::PropertyMapContainer::removeProperties
void removeProperties(std::size_t idx, std::size_t cLastIdx)
Definition: AIFProperties.h:646
FEVV::DataStructures::AIF::AIFVector::operator*
friend AIFVector< CoordinateType, DIM > operator*(double s, const AIFVector< CoordinateType, DIM > &v)
Definition: AIFProperties.h:334
FEVV::DataStructures::AIF::PropertyMapContainer::~PropertyMapContainer
~PropertyMapContainer()
Definition: AIFProperties.h:471
FEVV::DataStructures::AIF::BasePropertyMap::forcePolymorphic
virtual void forcePolymorphic(void)
Definition: AIFProperties.h:369
FEVV::DataStructures::AIF::PropertyMap
Definition: AIFProperties.h:381
FEVV::DataStructures::AIF::PropertyMapContainer
Definition: AIFProperties.h:469
FEVV
Interfaces for plugins These interfaces will be used for different plugins.
Definition: Assert.h:16
FEVV::DataStructures::AIF::PropertyMapContainer::getAssocPropertyMap
AssocPropertyMap< KeyType, ValueType > * getAssocPropertyMap(const std::string &name)
Definition: AIFProperties.h:665
FEVV::DataStructures::AIF::AIFVector::CoordinateType
CoordinateT CoordinateType
Definition: AIFProperties.h:175
FEVV::DataStructures::AIF::PropertyMap::operator[]
T & operator[](const AIFFace::ptr v) const
add operator[] for face_descriptor
Definition: AIFProperties.h:393
FEVV::DataStructures::AIF::PropertyMap::size
std::size_t size(void) const
number of elements in the property map
Definition: AIFProperties.h:396
FEVV::DataStructures::AIF::PropertyMap::remove
void remove(std::size_t idx, std::size_t cLastIdx)
Definition: AIFProperties.h:407
FEVV::DataStructures::AIF::AIFPoint::operator==
bool operator==(const AIFPoint< CoordinateType, DIM > &p) const
Definition: AIFProperties.h:147
FEVV::DataStructures::AIF::AIFVector::AIFVector
AIFVector(void)
Definition: AIFProperties.h:181
FEVV::DataStructures::AIF::AIFVector::operator-
AIFVector< CoordinateType, DIM > operator-(const AIFVector< CoordinateType, DIM > &other) const
Definition: AIFProperties.h:233
FEVV::DataStructures::AIF::AIFVector::operator<<
friend std::ostream & operator<<(std::ostream &stream, const AIFVector< CoordinateType, DIM > &v)
Definition: AIFProperties.h:345
FEVV::DataStructures::AIF::AIFEdge::ptr
boost::shared_ptr< self > ptr
Definition: AIFEdge.hpp:56
FEVV::DataStructures::AIF::AIFVector
Definition: AIFProperties.h:173
FEVV::DataStructures::AIF::AIFVector::operator==
bool operator==(const AIFVector< CoordinateType, DIM > &v) const
Definition: AIFProperties.h:309
FEVV::DataStructures::AIF::PropertyMap::operator[]
T & operator[](const AIFVertex::ptr v) const
add operator[] for vertex_descriptor
Definition: AIFProperties.h:387
FEVV::DataStructures::AIF::PropertyMapContainer::getProperty
T & getProperty(const std::string &name, std::size_t idx) const
Definition: AIFProperties.h:634
FEVV::DataStructures::AIF::PropertyMapContainer::isPropertyMap
bool isPropertyMap(const std::string &name) const
Definition: AIFProperties.h:488
FEVV::Filters::fabs
double fabs(const v_Curv< HalfedgeGraph > &input)
Definition: curvature.hpp:54
FEVV::DataStructures::AIF::PropertyMapContainer::addPropertyMap
PropertyMap< T > * addPropertyMap(const std::string &name)
Definition: AIFProperties.h:559
FEVV::DataStructures::AIF::AIFPoint::SuperClass
std::array< CoordinateType, DIM > SuperClass
Definition: AIFProperties.h:34
FEVV::DataStructures::AIF::AIFPoint::operator-
AIFVector< CoordinateType, DIM > operator-(const AIFPoint< CoordinateType, DIM > &other) const
Definition: AIFProperties.h:102
FEVV::DataStructures::AIF::AIFPoint::operator<<
friend std::ostream & operator<<(std::ostream &stream, const AIFPoint< CoordinateType, DIM > &p)
Definition: AIFProperties.h:81
FEVV::DataStructures::AIF::AIFVector::operator+
AIFPoint< CoordinateType, DIM > operator+(const AIFPoint< CoordinateType, DIM > &p) const
Definition: AIFProperties.h:275
FEVV::DataStructures::AIF::AIFVector::AIFVector
AIFVector(CoordinateType x, CoordinateType y, CoordinateType z)
Definition: AIFProperties.h:194
FEVV::DataStructures::AIF::AIFPoint::operator+
AIFPoint< CoordinateType, DIM > operator+(const AIFVector< CoordinateType, DIM > &v) const
Definition: AIFProperties.h:113
FEVV::DataStructures::AIF::AIFVector::length
CoordinateType length(void) const
Definition: AIFProperties.h:208
FEVV::DataStructures::AIF::AIFVector::operator+
AIFVector< CoordinateType, DIM > operator+(const AIFVector< CoordinateType, DIM > &other) const
Definition: AIFProperties.h:222
epsilon
const float epsilon
Definition: core.h:51
FEVV::DataStructures::AIF::PropertyMap::operator[]
T & operator[](const AIFEdge::ptr v) const
add operator[] for edge_descriptor
Definition: AIFProperties.h:390
FEVV::DataStructures::AIF::AIFPoint
Definition: AIFProperties.h:31
FEVV::DataStructures::AIF::AIFPoint::AIFPoint
AIFPoint(void)
Definition: AIFProperties.h:40
FEVV::DataStructures::AIF::PropertyMapContainer::clear
void clear()
Definition: AIFProperties.h:587
FEVV::DataStructures::AIF::AIFPoint::operator<
bool operator<(const AIFPoint< CoordinateType, DIM > &p) const
Definition: AIFProperties.h:124
FEVV::DataStructures::AIF::AIFVector::operator*
double operator*(const AIFVector< CoordinateType, DIM > &other) const
Definition: AIFProperties.h:254