Radium Engine  1.5.0
IndexedGeometry.cpp
1 #include <Core/Geometry/IndexedGeometry.hpp>
2 #include <iterator>
3 
4 namespace Ra {
5 namespace Core {
6 namespace Geometry {
7 
8 MultiIndexedGeometry::MultiIndexedGeometry( const MultiIndexedGeometry& other ) :
9  AttribArrayGeometry( other ) {
10  deepCopy( other );
11 }
12 
13 MultiIndexedGeometry::MultiIndexedGeometry( MultiIndexedGeometry&& other ) :
14  AttribArrayGeometry( std::move( other ) ), m_indices( std::move( other.m_indices ) ) {}
15 
16 MultiIndexedGeometry::MultiIndexedGeometry( const AttribArrayGeometry& other ) :
17  AttribArrayGeometry( other ) {}
18 
19 MultiIndexedGeometry::MultiIndexedGeometry( AttribArrayGeometry&& other ) :
20  AttribArrayGeometry( std::move( other ) ) {}
21 
22 MultiIndexedGeometry& MultiIndexedGeometry::operator=( const MultiIndexedGeometry& other ) {
23  invalidateAabb();
24  AttribArrayGeometry::operator=( other );
25  deepCopy( other );
26  notify();
27  return *this;
28 }
29 
30 MultiIndexedGeometry& MultiIndexedGeometry::operator=( MultiIndexedGeometry&& other ) {
31  invalidateAabb();
32  AttribArrayGeometry::operator=( std::move( other ) );
33  m_indices = std::move( other.m_indices );
34  notify();
35  return *this;
36 }
37 
38 void MultiIndexedGeometry::clear() {
39  invalidateAabb();
40  AttribArrayGeometry::clear();
41  deepClear();
42  notify();
43 }
44 
45 void MultiIndexedGeometry::copy( const MultiIndexedGeometry& other ) {
46  invalidateAabb();
47  AttribArrayGeometry::copyBaseGeometry( other );
48  deepCopy( other );
49  notify();
50 }
51 
53 void MultiIndexedGeometry::checkConsistency() const {
54 #ifdef CORE_DEBUG
55 #endif
56 }
57 
58 bool MultiIndexedGeometry::append( const MultiIndexedGeometry& other ) {
59  bool dataHasBeenCopied = false;
60  for ( const auto& [key, value] : other.m_indices ) {
61  auto it = m_indices.find( key );
62  if ( it == m_indices.end() ) // copy entire layer
63  {
64  m_indices[key] = std::make_pair(
65  value.first, std::unique_ptr<GeometryIndexLayerBase> { value.second->clone() } );
66 
67  dataHasBeenCopied = true;
68  }
69  else {
70  // try to append to an existing layer: should always work
71  if ( it->second.second->append( *( value.second ) ) ) { dataHasBeenCopied = true; }
72  else {
73  CORE_ASSERT( false,
74  "Inconsistency: layers with different semantics shares the same key" );
75  }
76  }
77  }
78 
79  if ( dataHasBeenCopied ) {
80  invalidateAabb();
81  notify();
82  }
83  return true;
84 }
85 
88 
89 bool MultiIndexedGeometry::containsLayer( const LayerSemantic& semanticName ) const {
90  for ( const auto& [key, value] : m_indices ) {
91  if ( key.first.find( semanticName ) != key.first.end() ) return true;
92  }
93  return false;
94 }
95 
96 bool MultiIndexedGeometry::containsLayer( const LayerSemanticCollection& semantics ) const {
97  for ( const auto& [key, value] : m_indices ) {
98  if ( key.first == semantics ) return true;
99  }
100  return false;
101 }
102 
105 
106 size_t MultiIndexedGeometry::countLayers( const LayerSemantic& semanticName ) const {
107  size_t c = 0;
108  for ( const auto& [key, value] : m_indices ) {
109  if ( key.first.find( semanticName ) != key.first.end() ) ++c;
110  }
111  return c;
112 }
113 
114 size_t MultiIndexedGeometry::countLayers( const LayerSemanticCollection& semantics ) const {
115  size_t c = 0;
116  for ( const auto& [key, value] : m_indices ) {
117  if ( key.first == semantics ) ++c;
118  }
119  return c;
120 }
121 
124 
125 std::pair<MultiIndexedGeometry::LayerKeyType, const GeometryIndexLayerBase&>
126 MultiIndexedGeometry::getFirstLayerOccurrence( const LayerSemantic& semanticName ) const {
127  for ( const auto& [key, value] : m_indices ) {
128  if ( key.first.find( semanticName ) != key.first.end() )
129  return { key, *( value.second.get() ) };
130  }
131  throw std::out_of_range( "Layer entry not found" );
132 }
133 
134 std::pair<MultiIndexedGeometry::LayerKeyType, const GeometryIndexLayerBase&>
135 MultiIndexedGeometry::getFirstLayerOccurrence( const LayerSemanticCollection& semantics ) const {
136  for ( const auto& [key, value] : m_indices ) {
137  if ( key.first == semantics ) return { key, *( value.second.get() ) };
138  }
139  throw std::out_of_range( "Layer entry not found" );
140 }
141 
144 
145 std::pair<MultiIndexedGeometry::LayerKeyType, GeometryIndexLayerBase&>
146 MultiIndexedGeometry::getFirstLayerOccurrenceWithLock( const LayerSemantic& semanticName ) {
147  for ( auto& [key, value] : m_indices ) {
148  if ( key.first.find( semanticName ) != key.first.end() ) {
149  CORE_ASSERT( !value.first, "try to get already locked layer" );
150  value.first = true;
151  return { key, *( value.second.get() ) };
152  }
153  }
154  throw std::out_of_range( "Layer entry not found" );
155 }
156 
157 std::pair<MultiIndexedGeometry::LayerKeyType, GeometryIndexLayerBase&>
158 MultiIndexedGeometry::getFirstLayerOccurrenceWithLock( const LayerSemanticCollection& semantics ) {
159  for ( auto& [key, value] : m_indices ) {
160  if ( key.first == semantics ) {
161  CORE_ASSERT( !value.first, "try to get already locked layer" );
162  value.first = true;
163  return { key, *( value.second.get() ) };
164  }
165  }
166  throw std::out_of_range( "Layer entry not found" );
167 }
168 
169 GeometryIndexLayerBase& MultiIndexedGeometry::getLayerWithLock( const LayerKeyType& layerKey ) {
170  auto& p = m_indices.at( layerKey );
171  CORE_ASSERT( !p.first, "try to get already locked layer" );
172  p.first = true;
173  return *( p.second.get() );
174 }
175 
178 
179 void MultiIndexedGeometry::unlockFirstLayerOccurrence( const LayerSemantic& semanticName ) {
180  for ( auto& [key, value] : m_indices ) {
181  if ( key.first.find( semanticName ) != key.first.end() ) {
182  CORE_ASSERT( value.first, "try to release unlocked layer" );
183  value.first = false;
184  notify();
185  return;
186  }
187  }
188  throw std::out_of_range( "Layer entry not found" );
189 }
190 
191 void MultiIndexedGeometry::unlockFirstLayerOccurrence( const LayerSemanticCollection& semantics ) {
192  for ( auto& [key, value] : m_indices ) {
193  if ( key.first == semantics ) {
194  CORE_ASSERT( value.first, "try to release unlocked layer" );
195  value.first = false;
196  notify();
197  return;
198  }
199  }
200  throw std::out_of_range( "Layer entry not found" );
201 }
202 
203 void MultiIndexedGeometry::unlockLayer( const LayerKeyType& layerKey ) {
204  auto& p = m_indices.at( layerKey );
205  CORE_ASSERT( p.first, "try to release unlocked layer" );
206  p.first = false;
207  notify();
208 }
209 
212 
213 std::pair<bool, GeometryIndexLayerBase&>
214 MultiIndexedGeometry::addLayer( std::unique_ptr<GeometryIndexLayerBase>&& layer,
215  const bool withLock,
216  const std::string& layerName ) {
217  LayerKeyType key { layer->semantics(), layerName };
218  std::pair<LayerKeyType, EntryType> elt { key, std::make_pair( false, std::move( layer ) ) };
219  auto [pos, inserted] = m_indices.insert( std::move( elt ) );
220  notify();
221 
222  if ( withLock ) {
223  CORE_ASSERT( !pos->second.first, "try to get already locked layer" );
224  pos->second.first = true;
225  }
228 
229  return { inserted, *( pos->second.second ) };
230 }
233 
234 void MultiIndexedGeometry::deepCopy( const MultiIndexedGeometry& other ) {
235  for ( const auto& [key, value] : other.m_indices ) {
236  m_indices[key] = std::make_pair(
237  value.first, std::unique_ptr<GeometryIndexLayerBase> { value.second->clone() } );
238  }
239 }
240 
241 void MultiIndexedGeometry::deepClear() {
242  m_indices.clear();
243 }
244 
247 
248 std::size_t MultiIndexedGeometry::KeyHash::operator()( const LayerKeyType& k ) const {
249  // Mix semantic collection into a single identifier string
250  std::ostringstream stream;
251  std::copy( k.first.begin(), k.first.end(), std::ostream_iterator<std::string>( stream, "" ) );
252  std::string result = stream.str();
253  std::sort( result.begin(), result.end() );
254 
255  // Combine with layer name hash
256  return std::hash<std::string> {}( result ) ^ ( std::hash<std::string> {}( k.second ) << 1 );
257 }
258 
261 
262 void PointCloudIndexLayer::linearIndices( const AttribArrayGeometry& attr ) {
263  auto nbVert = attr.vertices().size();
264  collection().resize( nbVert );
265  collection().getMap() = IndexContainerType::Matrix::LinSpaced( nbVert, 0, nbVert - 1 );
266 }
267 
268 } // namespace Geometry
269 } // namespace Core
270 } // namespace Ra
This class represents vertex + attributes per vertex. Toplogy is handled in MultiIndexedGeometry subc...
const PointAttribHandle::Container & vertices() const
Access the vertices positions.
Base class for index collections stored in MultiIndexedGeometry.
AbstractGeometry with per-vertex attributes and layers of indices. Each layer represents a different ...
Definition: Cage.cpp:3