DGtal  1.0.0
PolygonalSurface.ih
1 /**
2  * This program is free software: you can redistribute it and/or modify
3  * it under the terms of the GNU Lesser General Public License as
4  * published by the Free Software Foundation, either version 3 of the
5  * License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program. If not, see <http://www.gnu.org/licenses/>.
14  *
15  **/
16 
17 /**
18  * @file PolygonalSurface.ih
19  * @author Jacques-Olivier Lachaud (\c jacques-olivier.lachaud@univ-savoie.fr )
20  * Laboratory of Mathematics (CNRS, UMR 5127), University of Savoie, France
21  *
22  * @date 2017/02/05
23  *
24  * Implementation of inline methods defined in PolygonalSurface.h
25  *
26  * This file is part of the DGtal library.
27  */
28 
29 
30 //////////////////////////////////////////////////////////////////////////////
31 #include <cstdlib>
32 //////////////////////////////////////////////////////////////////////////////
33 
34 ///////////////////////////////////////////////////////////////////////////////
35 // IMPLEMENTATION of inline methods.
36 ///////////////////////////////////////////////////////////////////////////////
37 
38 ///////////////////////////////////////////////////////////////////////////////
39 // ----------------------- Standard services ------------------------------
40 
41 template <typename TPoint>
42 inline
43 DGtal::PolygonalSurface<TPoint>::PolygonalSurface
44 ( Clone<HalfEdgeDataStructure> heds,
45  Clone<PositionsStorage> pos )
46  : myHEDS( heds ), myPositions( pos )
47 {
48  isHEDSValid = ( myPositions.size() == myHEDS.nbVertices() );
49 }
50 
51 //-----------------------------------------------------------------------------
52 template <typename TPoint>
53 inline
54 bool
55 DGtal::PolygonalSurface<TPoint>::build()
56 {
57  if ( isHEDSValid ) {
58  trace.warning() << "[DGtal::PolygonalSurface<TPoint>::build()]"
59  << " attempting to rebuild a polygonal surface." << std::endl;
60  return false;
61  }
62  isHEDSValid = myHEDS.build( myPolygonalFaces );
63  if ( myHEDS.nbVertices() != myPositions.size() ) {
64  trace.warning() << "[DGtal::PolygonalSurface<TPoint>::build()]"
65  << " the size of vertex data array (s1) and the number of vertices (s2) in the polygonal surface does not match:"
66  << " s1=" << myPositions.size()
67  << " s2=" << myHEDS.nbVertices() << std::endl;
68  isHEDSValid = false;
69  }
70  return isHEDSValid;
71 }
72 
73 //-----------------------------------------------------------------------------
74 template <typename TPoint>
75 inline
76 void
77 DGtal::PolygonalSurface<TPoint>::clear()
78 {
79  isHEDSValid = false;
80  myHEDS.clear();
81  myPositions.clear();
82  myPolygonalFaces.clear();
83 
84 }
85 //-----------------------------------------------------------------------------
86 template <typename TPoint>
87 inline
88 typename DGtal::PolygonalSurface<TPoint>::VertexIndex
89 DGtal::PolygonalSurface<TPoint>::addVertex( const Point& vdata )
90 {
91  VertexIndex vi = myPositions.size();
92  myPositions.push_back( vdata );
93  return vi;
94 }
95 
96 //-----------------------------------------------------------------------------
97 template <typename TPoint>
98 inline
99 typename DGtal::PolygonalSurface<TPoint>::FaceIndex
100 DGtal::PolygonalSurface<TPoint>::addTriangle
101 ( VertexIndex v0, VertexIndex v1, VertexIndex v2 )
102 {
103  FaceIndex fi = myPolygonalFaces.size();
104  myPolygonalFaces.push_back( PolygonalFace( { v0, v1, v2 } ) );
105  return fi;
106 }
107 //-----------------------------------------------------------------------------
108 template <typename TPoint>
109 inline
110 typename DGtal::PolygonalSurface<TPoint>::FaceIndex
111 DGtal::PolygonalSurface<TPoint>::addQuadrangle
112 ( VertexIndex v0, VertexIndex v1, VertexIndex v2, VertexIndex v3 )
113 {
114  FaceIndex fi = myPolygonalFaces.size();
115  myPolygonalFaces.push_back( PolygonalFace( { v0, v1, v2, v3 } ) );
116  return fi;
117 }
118 //-----------------------------------------------------------------------------
119 template <typename TPoint>
120 inline
121 typename DGtal::PolygonalSurface<TPoint>::FaceIndex
122 DGtal::PolygonalSurface<TPoint>::addPolygonalFace
123 ( const PolygonalFace& f )
124 {
125  FaceIndex fi = myPolygonalFaces.size();
126  myPolygonalFaces.push_back( f );
127  return fi;
128 }
129 
130 //-----------------------------------------------------------------------------
131 template <typename TPoint>
132 inline
133 typename DGtal::PolygonalSurface<TPoint>::Point&
134 DGtal::PolygonalSurface<TPoint>::position( Vertex v )
135 {
136  ASSERT( 0 <= v && v < myPositions.size() );
137  return myPositions[ v ];
138 }
139 //-----------------------------------------------------------------------------
140 template <typename TPoint>
141 inline
142 const typename DGtal::PolygonalSurface<TPoint>::Point&
143 DGtal::PolygonalSurface<TPoint>::position( Vertex v ) const
144 {
145  ASSERT( 0 <= v && v < myPositions.size() );
146  return myPositions[ v ];
147 }
148 //-----------------------------------------------------------------------------
149 template <typename TPoint>
150 inline
151 typename DGtal::PolygonalSurface<TPoint>::Size
152 DGtal::PolygonalSurface<TPoint>::size() const
153 {
154  return myPositions.size();
155 }
156 //-----------------------------------------------------------------------------
157 template <typename TPoint>
158 inline
159 typename DGtal::PolygonalSurface<TPoint>::Size
160 DGtal::PolygonalSurface<TPoint>::bestCapacity() const
161 {
162  return 8;
163 }
164 //-----------------------------------------------------------------------------
165 template <typename TPoint>
166 inline
167 typename DGtal::PolygonalSurface<TPoint>::Size
168 DGtal::PolygonalSurface<TPoint>::degree( const Vertex & v ) const
169 {
170  ASSERT( isValid() );
171  return myHEDS.nbNeighboringVertices( v );
172 }
173 
174 //-----------------------------------------------------------------------------
175 template <typename TPoint>
176 template <typename OutputIterator>
177 inline
178 void
179 DGtal::PolygonalSurface<TPoint>::writeNeighbors
180 ( OutputIterator &it, const Vertex & v ) const
181 {
182  ASSERT( isValid() );
183  typedef HalfEdgeDataStructure::VertexIndexRange VertexIndexRange;
184  VertexIndexRange neighbors;
185  myHEDS.getNeighboringVertices( v, neighbors );
186  for ( Vertex nv : neighbors ) *it++ = nv;
187 }
188 
189 //-----------------------------------------------------------------------------
190 template <typename TPoint>
191 template <typename OutputIterator, typename VertexPredicate>
192 inline
193 void
194 DGtal::PolygonalSurface<TPoint>::writeNeighbors
195 ( OutputIterator &it, const Vertex & v, const VertexPredicate & pred) const
196 {
197  ASSERT( isValid() );
198  typedef HalfEdgeDataStructure::VertexIndexRange VertexIndexRange;
199  VertexIndexRange neighbors;
200  myHEDS.getNeighboringVertices( v, neighbors );
201  for ( Vertex nv : neighbors ) if ( pred( nv ) ) *it++ = nv;
202 }
203 
204 //-----------------------------------------------------------------------------
205 template <typename TPoint>
206 inline
207 typename DGtal::PolygonalSurface<TPoint>::ArcRange
208 DGtal::PolygonalSurface<TPoint>::outArcs( const Vertex & v ) const
209 {
210  ArcRange result;
211  const Index start_hei = myHEDS.halfEdgeIndexFromVertexIndex( v );
212  Index hei = start_hei;
213  do
214  {
215  const HalfEdge& he = myHEDS.halfEdge( hei );
216  if( INVALID_FACE != he.face ) result.push_back( hei );
217  hei = myHEDS.halfEdge( he.opposite ).next;
218  }
219  while ( hei != start_hei );
220  return result;
221 }
222 
223 //-----------------------------------------------------------------------------
224 template <typename TPoint>
225 inline
226 typename DGtal::PolygonalSurface<TPoint>::ArcRange
227 DGtal::PolygonalSurface<TPoint>::inArcs( const Vertex & v ) const
228 {
229  ArcRange result;
230  const Index start_hei = myHEDS.halfEdgeIndexFromVertexIndex( v );
231  Index hei = start_hei;
232  do
233  {
234  const HalfEdge& he = myHEDS.halfEdge( hei );
235  if( INVALID_FACE != he.face ) result.push_back( he.opposite );
236  hei = myHEDS.halfEdge( he.opposite ).next;
237  }
238  while ( hei != start_hei );
239  return result;
240 }
241 
242 //-----------------------------------------------------------------------------
243 template <typename TPoint>
244 inline
245 typename DGtal::PolygonalSurface<TPoint>::FaceRange
246 DGtal::PolygonalSurface<TPoint>::facesAroundVertex( const Vertex & v ) const
247 {
248  FaceRange result;
249  const Index start_hei = myHEDS.halfEdgeIndexFromVertexIndex( v );
250  Index hei = start_hei;
251  do
252  {
253  const HalfEdge& he = myHEDS.halfEdge( hei );
254  if( INVALID_FACE != he.face ) result.push_back( he.face );
255  hei = myHEDS.halfEdge( he.opposite ).next;
256  }
257  while ( hei != start_hei );
258  return result;
259 }
260 
261 //-----------------------------------------------------------------------------
262 template <typename TPoint>
263 inline
264 typename DGtal::PolygonalSurface<TPoint>::Vertex
265 DGtal::PolygonalSurface<TPoint>::head( const Arc & a ) const
266 {
267  return myHEDS.halfEdge( a ).toVertex;
268 }
269 
270 //-----------------------------------------------------------------------------
271 template <typename TPoint>
272 inline
273 typename DGtal::PolygonalSurface<TPoint>::Vertex
274 DGtal::PolygonalSurface<TPoint>::tail( const Arc & a ) const
275 {
276  return head( opposite( a ) );
277 }
278 
279 //-----------------------------------------------------------------------------
280 template <typename TPoint>
281 inline
282 typename DGtal::PolygonalSurface<TPoint>::Arc
283 DGtal::PolygonalSurface<TPoint>::opposite( const Arc & a ) const
284 {
285  return myHEDS.halfEdge( a ).opposite;
286 }
287 
288 //-----------------------------------------------------------------------------
289 template <typename TPoint>
290 inline
291 typename DGtal::PolygonalSurface<TPoint>::Arc
292 DGtal::PolygonalSurface<TPoint>::next( const Arc & a ) const
293 {
294  return myHEDS.halfEdge( a ).next;
295 }
296 //-----------------------------------------------------------------------------
297 template <typename TPoint>
298 inline
299 typename DGtal::PolygonalSurface<TPoint>::Arc
300 DGtal::PolygonalSurface<TPoint>::arc
301 ( const Vertex & t, const Vertex & h ) const
302 {
303  return myHEDS.halfEdgeIndexFromArc( t, h );
304 }
305 
306 //-----------------------------------------------------------------------------
307 template <typename TPoint>
308 inline
309 typename DGtal::PolygonalSurface<TPoint>::Face
310 DGtal::PolygonalSurface<TPoint>::faceAroundArc( const Arc & a ) const
311 {
312  return myHEDS.halfEdge( a ).face;
313 }
314 //-----------------------------------------------------------------------------
315 template <typename TPoint>
316 inline
317 typename DGtal::PolygonalSurface<TPoint>::FaceRange
318 DGtal::PolygonalSurface<TPoint>::facesAroundArc( const Arc & a ) const
319 {
320  FaceRange result;
321  Face f = faceAroundArc( a );
322  if ( f != INVALID_FACE ) result.push_back( f );
323  return result;
324 }
325 
326 //-----------------------------------------------------------------------------
327 template <typename TPoint>
328 inline
329 typename DGtal::PolygonalSurface<TPoint>::VertexRange
330 DGtal::PolygonalSurface<TPoint>::verticesAroundFace( const Face & f ) const
331 {
332  VertexRange result;
333  const Index start_hei = myHEDS.halfEdgeIndexFromFaceIndex( f );
334  Index hei = start_hei;
335  do {
336  const HalfEdge& he = myHEDS.halfEdge( hei );
337  ASSERT( ( he.face == f )
338  && "[PolygonalSurface::verticesAroundFace] invalid face." );
339  result.push_back( he.toVertex );
340  hei = he.next;
341  } while ( hei != start_hei );
342  ASSERT( result.size() >= 3 );
343  return result;
344 }
345 
346 //-----------------------------------------------------------------------------
347 template <typename TPoint>
348 inline
349 typename DGtal::PolygonalSurface<TPoint>::ArcRange
350 DGtal::PolygonalSurface<TPoint>::arcsAroundFace( const Face & f ) const
351 {
352  ArcRange result;
353  const Index start_hei = myHEDS.halfEdgeIndexFromFaceIndex( f );
354  Index hei = start_hei;
355  do {
356  result.push_back( hei );
357  const HalfEdge& he = myHEDS.halfEdge( hei );
358  ASSERT( ( he.face == f )
359  && "[PolygonalSurface::arcsAroundFace] invalid face." );
360  hei = he.next;
361  } while ( hei != start_hei );
362  ASSERT( result.size() >= 3 );
363  return result;
364 }
365 
366 //-----------------------------------------------------------------------------
367 template <typename TPoint>
368 inline
369 bool
370 DGtal::PolygonalSurface<TPoint>::isVertexBoundary( const Vertex& v ) const
371 {
372  return myHEDS.isVertexBoundary( v );
373 }
374 
375 //-----------------------------------------------------------------------------
376 template <typename TPoint>
377 inline
378 bool
379 DGtal::PolygonalSurface<TPoint>::isArcBoundary( const Arc& v ) const
380 {
381  return INVALID_FACE == myHEDS.halfEdge( v ).face;
382 }
383 
384 //-----------------------------------------------------------------------------
385 template <typename TPoint>
386 inline
387 typename DGtal::PolygonalSurface<TPoint>::FaceRange
388 DGtal::PolygonalSurface<TPoint>::allFaces() const
389 {
390  FaceRange result( nbFaces() );
391  for ( Face fi = 0; fi < result.size(); ++fi )
392  result[ fi ] = fi;
393  return result;
394 }
395 //-----------------------------------------------------------------------------
396 template <typename TPoint>
397 inline
398 typename DGtal::PolygonalSurface<TPoint>::ArcRange
399 DGtal::PolygonalSurface<TPoint>::allArcs() const
400 {
401  ArcRange result( nbArcs() );
402  for ( Arc fi = 0; fi < result.size(); ++fi )
403  result[ fi ] = fi;
404  return result;
405 }
406 //-----------------------------------------------------------------------------
407 template <typename TPoint>
408 inline
409 typename DGtal::PolygonalSurface<TPoint>::VertexRange
410 DGtal::PolygonalSurface<TPoint>::allVertices() const
411 {
412  VertexRange result( nbVertices() );
413  for ( Vertex fi = 0; fi < result.size(); ++fi )
414  result[ fi ] = fi;
415  return result;
416 }
417 
418 //-----------------------------------------------------------------------------
419 template <typename TPoint>
420 inline
421 typename DGtal::PolygonalSurface<TPoint>::ArcRange
422 DGtal::PolygonalSurface<TPoint>::allBoundaryArcs() const
423 {
424  return myHEDS.boundaryHalfEdgeIndices();
425 }
426 
427 //-----------------------------------------------------------------------------
428 template <typename TPoint>
429 inline
430 typename DGtal::PolygonalSurface<TPoint>::VertexRange
431 DGtal::PolygonalSurface<TPoint>::allBoundaryVertices() const
432 {
433  return myHEDS.boundaryVertices();
434 }
435 
436 
437 ///////////////////////////////////////////////////////////////////////////////
438 // Interface - public :
439 
440 /**
441  * Writes/Displays the object on an output stream.
442  * @param out the output stream where the object is written.
443  */
444 template <typename TPoint>
445 inline
446 void
447 DGtal::PolygonalSurface<TPoint>::selfDisplay ( std::ostream & out ) const
448 {
449  out << "[PolygonalSurface #V=" << myHEDS.nbVertices()
450  << " #E=" << myHEDS.nbEdges() << " #F=" << myHEDS.nbFaces()
451  << " Chi=" << Euler() << "]";
452 }
453 
454 /**
455  * Checks the validity/consistency of the object.
456  * @return 'true' if the object is valid, 'false' otherwise.
457  */
458 template <typename TPoint>
459 inline
460 bool
461 DGtal::PolygonalSurface<TPoint>::isValid() const
462 {
463  return isHEDSValid;
464 }
465 
466 
467 
468 ///////////////////////////////////////////////////////////////////////////////
469 // Implementation of inline functions //
470 
471 template <typename TPoint>
472 inline
473 std::ostream&
474 DGtal::operator<< ( std::ostream & out,
475  const PolygonalSurface<TPoint> & object )
476 {
477  object.selfDisplay( out );
478  return out;
479 }
480 
481 // //
482 ///////////////////////////////////////////////////////////////////////////////
483 
484