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.
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.
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/>.
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
24 * Implementation of inline methods defined in PolygonalSurface.h
26 * This file is part of the DGtal library.
30 //////////////////////////////////////////////////////////////////////////////
32 //////////////////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////////////////
35 // IMPLEMENTATION of inline methods.
36 ///////////////////////////////////////////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////////////////
39 // ----------------------- Standard services ------------------------------
41 template <typename TPoint>
43 DGtal::PolygonalSurface<TPoint>::PolygonalSurface
44 ( Clone<HalfEdgeDataStructure> aHeds,
45 Clone<PositionsStorage> pos )
46 : myHEDS( aHeds ), myPositions( pos )
48 isHEDSValid = ( myPositions.size() == myHEDS.nbVertices() );
51 //-----------------------------------------------------------------------------
52 template <typename TPoint>
55 DGtal::PolygonalSurface<TPoint>::build()
58 trace.warning() << "[DGtal::PolygonalSurface<TPoint>::build()]"
59 << " attempting to rebuild a polygonal surface." << std::endl;
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;
73 //-----------------------------------------------------------------------------
74 template <typename TPoint>
77 DGtal::PolygonalSurface<TPoint>::clear()
82 myPolygonalFaces.clear();
85 //-----------------------------------------------------------------------------
86 template <typename TPoint>
88 typename DGtal::PolygonalSurface<TPoint>::VertexIndex
89 DGtal::PolygonalSurface<TPoint>::addVertex( const Point& vdata )
91 VertexIndex vi = myPositions.size();
92 myPositions.push_back( vdata );
96 //-----------------------------------------------------------------------------
97 template <typename TPoint>
99 typename DGtal::PolygonalSurface<TPoint>::FaceIndex
100 DGtal::PolygonalSurface<TPoint>::addTriangle
101 ( VertexIndex v0, VertexIndex v1, VertexIndex v2 )
103 FaceIndex fi = myPolygonalFaces.size();
104 myPolygonalFaces.push_back( PolygonalFace( { v0, v1, v2 } ) );
107 //-----------------------------------------------------------------------------
108 template <typename TPoint>
110 typename DGtal::PolygonalSurface<TPoint>::FaceIndex
111 DGtal::PolygonalSurface<TPoint>::addQuadrangle
112 ( VertexIndex v0, VertexIndex v1, VertexIndex v2, VertexIndex v3 )
114 FaceIndex fi = myPolygonalFaces.size();
115 myPolygonalFaces.push_back( PolygonalFace( { v0, v1, v2, v3 } ) );
118 //-----------------------------------------------------------------------------
119 template <typename TPoint>
121 typename DGtal::PolygonalSurface<TPoint>::FaceIndex
122 DGtal::PolygonalSurface<TPoint>::addPolygonalFace
123 ( const PolygonalFace& f )
125 FaceIndex fi = myPolygonalFaces.size();
126 myPolygonalFaces.push_back( f );
130 //-----------------------------------------------------------------------------
131 template <typename TPoint>
133 typename DGtal::PolygonalSurface<TPoint>::Point&
134 DGtal::PolygonalSurface<TPoint>::position( Vertex v )
136 ASSERT( v < myPositions.size() );
137 return myPositions[ v ];
139 //-----------------------------------------------------------------------------
140 template <typename TPoint>
142 const typename DGtal::PolygonalSurface<TPoint>::Point&
143 DGtal::PolygonalSurface<TPoint>::position( Vertex v ) const
145 ASSERT( v < myPositions.size() );
146 return myPositions[ v ];
148 //-----------------------------------------------------------------------------
149 template <typename TPoint>
151 typename DGtal::PolygonalSurface<TPoint>::Size
152 DGtal::PolygonalSurface<TPoint>::size() const
154 return myPositions.size();
156 //-----------------------------------------------------------------------------
157 template <typename TPoint>
159 typename DGtal::PolygonalSurface<TPoint>::Size
160 DGtal::PolygonalSurface<TPoint>::bestCapacity() const
164 //-----------------------------------------------------------------------------
165 template <typename TPoint>
167 typename DGtal::PolygonalSurface<TPoint>::Size
168 DGtal::PolygonalSurface<TPoint>::degree( const Vertex & v ) const
171 return myHEDS.nbNeighboringVertices( v );
174 //-----------------------------------------------------------------------------
175 template <typename TPoint>
176 template <typename OutputIterator>
179 DGtal::PolygonalSurface<TPoint>::writeNeighbors
180 ( OutputIterator &it, const Vertex & v ) const
183 typedef HalfEdgeDataStructure::VertexIndexRange VertexIndexRange;
184 VertexIndexRange neighbors;
185 myHEDS.getNeighboringVertices( v, neighbors );
186 for ( Vertex nv : neighbors ) *it++ = nv;
189 //-----------------------------------------------------------------------------
190 template <typename TPoint>
191 template <typename OutputIterator, typename VertexPredicate>
194 DGtal::PolygonalSurface<TPoint>::writeNeighbors
195 ( OutputIterator &it, const Vertex & v, const VertexPredicate & pred) const
198 typedef HalfEdgeDataStructure::VertexIndexRange VertexIndexRange;
199 VertexIndexRange neighbors;
200 myHEDS.getNeighboringVertices( v, neighbors );
201 for ( Vertex nv : neighbors ) if ( pred( nv ) ) *it++ = nv;
204 //-----------------------------------------------------------------------------
205 template <typename TPoint>
207 typename DGtal::PolygonalSurface<TPoint>::ArcRange
208 DGtal::PolygonalSurface<TPoint>::outArcs( const Vertex & v ) const
211 const Index start_hei = myHEDS.halfEdgeIndexFromVertexIndex( v );
212 Index hei = start_hei;
215 const HalfEdge& he = myHEDS.halfEdge( hei );
216 if( INVALID_FACE != he.face ) result.push_back( hei );
217 hei = myHEDS.halfEdge( he.opposite ).next;
219 while ( hei != start_hei );
223 //-----------------------------------------------------------------------------
224 template <typename TPoint>
226 typename DGtal::PolygonalSurface<TPoint>::ArcRange
227 DGtal::PolygonalSurface<TPoint>::inArcs( const Vertex & v ) const
230 const Index start_hei = myHEDS.halfEdgeIndexFromVertexIndex( v );
231 Index hei = start_hei;
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;
238 while ( hei != start_hei );
242 //-----------------------------------------------------------------------------
243 template <typename TPoint>
245 typename DGtal::PolygonalSurface<TPoint>::FaceRange
246 DGtal::PolygonalSurface<TPoint>::facesAroundVertex( const Vertex & v ) const
249 const Index start_hei = myHEDS.halfEdgeIndexFromVertexIndex( v );
250 Index hei = start_hei;
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;
257 while ( hei != start_hei );
261 //-----------------------------------------------------------------------------
262 template <typename TPoint>
264 typename DGtal::PolygonalSurface<TPoint>::Vertex
265 DGtal::PolygonalSurface<TPoint>::head( const Arc & a ) const
267 return myHEDS.halfEdge( a ).toVertex;
270 //-----------------------------------------------------------------------------
271 template <typename TPoint>
273 typename DGtal::PolygonalSurface<TPoint>::Vertex
274 DGtal::PolygonalSurface<TPoint>::tail( const Arc & a ) const
276 return head( opposite( a ) );
279 //-----------------------------------------------------------------------------
280 template <typename TPoint>
282 typename DGtal::PolygonalSurface<TPoint>::Arc
283 DGtal::PolygonalSurface<TPoint>::opposite( const Arc & a ) const
285 return myHEDS.halfEdge( a ).opposite;
288 //-----------------------------------------------------------------------------
289 template <typename TPoint>
291 typename DGtal::PolygonalSurface<TPoint>::Arc
292 DGtal::PolygonalSurface<TPoint>::next( const Arc & a ) const
294 return myHEDS.halfEdge( a ).next;
296 //-----------------------------------------------------------------------------
297 template <typename TPoint>
299 typename DGtal::PolygonalSurface<TPoint>::Arc
300 DGtal::PolygonalSurface<TPoint>::arc
301 ( const Vertex & t, const Vertex & h ) const
303 return myHEDS.halfEdgeIndexFromArc( t, h );
306 //-----------------------------------------------------------------------------
307 template <typename TPoint>
309 typename DGtal::PolygonalSurface<TPoint>::Face
310 DGtal::PolygonalSurface<TPoint>::faceAroundArc( const Arc & a ) const
312 return myHEDS.halfEdge( a ).face;
314 //-----------------------------------------------------------------------------
315 template <typename TPoint>
317 typename DGtal::PolygonalSurface<TPoint>::FaceRange
318 DGtal::PolygonalSurface<TPoint>::facesAroundArc( const Arc & a ) const
321 Face f = faceAroundArc( a );
322 if ( f != INVALID_FACE ) result.push_back( f );
326 //-----------------------------------------------------------------------------
327 template <typename TPoint>
329 typename DGtal::PolygonalSurface<TPoint>::VertexRange
330 DGtal::PolygonalSurface<TPoint>::verticesAroundFace( const Face & f ) const
333 const Index start_hei = myHEDS.halfEdgeIndexFromFaceIndex( f );
334 Index hei = start_hei;
336 const HalfEdge& he = myHEDS.halfEdge( hei );
337 ASSERT( ( he.face == f )
338 && "[PolygonalSurface::verticesAroundFace] invalid face." );
339 result.push_back( he.toVertex );
341 } while ( hei != start_hei );
342 ASSERT( result.size() >= 3 );
346 //-----------------------------------------------------------------------------
347 template <typename TPoint>
349 typename DGtal::PolygonalSurface<TPoint>::ArcRange
350 DGtal::PolygonalSurface<TPoint>::arcsAroundFace( const Face & f ) const
353 const Index start_hei = myHEDS.halfEdgeIndexFromFaceIndex( f );
354 Index hei = start_hei;
356 result.push_back( hei );
357 const HalfEdge& he = myHEDS.halfEdge( hei );
358 ASSERT( ( he.face == f )
359 && "[PolygonalSurface::arcsAroundFace] invalid face." );
361 } while ( hei != start_hei );
362 ASSERT( result.size() >= 3 );
366 //-----------------------------------------------------------------------------
367 template <typename TPoint>
370 DGtal::PolygonalSurface<TPoint>::isVertexBoundary( const Vertex& v ) const
372 return myHEDS.isVertexBoundary( v );
375 //-----------------------------------------------------------------------------
376 template <typename TPoint>
379 DGtal::PolygonalSurface<TPoint>::isArcBoundary( const Arc& v ) const
381 return INVALID_FACE == myHEDS.halfEdge( v ).face;
384 //-----------------------------------------------------------------------------
385 template <typename TPoint>
387 typename DGtal::PolygonalSurface<TPoint>::FaceRange
388 DGtal::PolygonalSurface<TPoint>::allFaces() const
390 FaceRange result( nbFaces() );
391 for ( Face fi = 0; fi < result.size(); ++fi )
395 //-----------------------------------------------------------------------------
396 template <typename TPoint>
398 typename DGtal::PolygonalSurface<TPoint>::ArcRange
399 DGtal::PolygonalSurface<TPoint>::allArcs() const
401 ArcRange result( nbArcs() );
402 for ( Arc fi = 0; fi < result.size(); ++fi )
406 //-----------------------------------------------------------------------------
407 template <typename TPoint>
409 typename DGtal::PolygonalSurface<TPoint>::VertexRange
410 DGtal::PolygonalSurface<TPoint>::allVertices() const
412 VertexRange result( nbVertices() );
413 for ( Vertex fi = 0; fi < result.size(); ++fi )
418 //-----------------------------------------------------------------------------
419 template <typename TPoint>
421 typename DGtal::PolygonalSurface<TPoint>::ArcRange
422 DGtal::PolygonalSurface<TPoint>::allBoundaryArcs() const
424 return myHEDS.boundaryHalfEdgeIndices();
427 //-----------------------------------------------------------------------------
428 template <typename TPoint>
430 typename DGtal::PolygonalSurface<TPoint>::VertexRange
431 DGtal::PolygonalSurface<TPoint>::allBoundaryVertices() const
433 return myHEDS.boundaryVertices();
437 ///////////////////////////////////////////////////////////////////////////////
438 // Interface - public :
441 * Writes/Displays the object on an output stream.
442 * @param out the output stream where the object is written.
444 template <typename TPoint>
447 DGtal::PolygonalSurface<TPoint>::selfDisplay ( std::ostream & out ) const
449 out << "[PolygonalSurface #V=" << myHEDS.nbVertices()
450 << " #E=" << myHEDS.nbEdges() << " #F=" << myHEDS.nbFaces()
451 << " Chi=" << Euler() << "]";
455 * Checks the validity/consistency of the object.
456 * @return 'true' if the object is valid, 'false' otherwise.
458 template <typename TPoint>
461 DGtal::PolygonalSurface<TPoint>::isValid() const
468 ///////////////////////////////////////////////////////////////////////////////
469 // Implementation of inline functions //
471 template <typename TPoint>
474 DGtal::operator<< ( std::ostream & out,
475 const PolygonalSurface<TPoint> & object )
477 object.selfDisplay( out );
482 ///////////////////////////////////////////////////////////////////////////////