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 ------------------------------
41template <typename TPoint>
43DGtal::PolygonalSurface<TPoint>::PolygonalSurface
44( Clone<HalfEdgeDataStructure> aHeds,
45 Clone<PositionsStorage> pos )
46 : myHEDS( aHeds ), myPositions( pos )
48 isHEDSValid = ( myPositions.size() == myHEDS.nbVertices() );
51//-----------------------------------------------------------------------------
52template <typename TPoint>
55DGtal::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//-----------------------------------------------------------------------------
74template <typename TPoint>
77DGtal::PolygonalSurface<TPoint>::clear()
82 myPolygonalFaces.clear();
85//-----------------------------------------------------------------------------
86template <typename TPoint>
88typename DGtal::PolygonalSurface<TPoint>::VertexIndex
89DGtal::PolygonalSurface<TPoint>::addVertex( const Point& vdata )
91 VertexIndex vi = myPositions.size();
92 myPositions.push_back( vdata );
96//-----------------------------------------------------------------------------
97template <typename TPoint>
99typename DGtal::PolygonalSurface<TPoint>::FaceIndex
100DGtal::PolygonalSurface<TPoint>::addTriangle
101( VertexIndex v0, VertexIndex v1, VertexIndex v2 )
103 FaceIndex fi = myPolygonalFaces.size();
104 myPolygonalFaces.push_back( PolygonalFace( { v0, v1, v2 } ) );
107//-----------------------------------------------------------------------------
108template <typename TPoint>
110typename DGtal::PolygonalSurface<TPoint>::FaceIndex
111DGtal::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//-----------------------------------------------------------------------------
119template <typename TPoint>
121typename DGtal::PolygonalSurface<TPoint>::FaceIndex
122DGtal::PolygonalSurface<TPoint>::addPolygonalFace
123( const PolygonalFace& f )
125 FaceIndex fi = myPolygonalFaces.size();
126 myPolygonalFaces.push_back( f );
130//-----------------------------------------------------------------------------
131template <typename TPoint>
133typename DGtal::PolygonalSurface<TPoint>::Point&
134DGtal::PolygonalSurface<TPoint>::position( Vertex v )
136 ASSERT( 0 <= v && v < myPositions.size() );
137 return myPositions[ v ];
139//-----------------------------------------------------------------------------
140template <typename TPoint>
142const typename DGtal::PolygonalSurface<TPoint>::Point&
143DGtal::PolygonalSurface<TPoint>::position( Vertex v ) const
145 ASSERT( 0 <= v && v < myPositions.size() );
146 return myPositions[ v ];
148//-----------------------------------------------------------------------------
149template <typename TPoint>
151typename DGtal::PolygonalSurface<TPoint>::Size
152DGtal::PolygonalSurface<TPoint>::size() const
154 return myPositions.size();
156//-----------------------------------------------------------------------------
157template <typename TPoint>
159typename DGtal::PolygonalSurface<TPoint>::Size
160DGtal::PolygonalSurface<TPoint>::bestCapacity() const
164//-----------------------------------------------------------------------------
165template <typename TPoint>
167typename DGtal::PolygonalSurface<TPoint>::Size
168DGtal::PolygonalSurface<TPoint>::degree( const Vertex & v ) const
171 return myHEDS.nbNeighboringVertices( v );
174//-----------------------------------------------------------------------------
175template <typename TPoint>
176template <typename OutputIterator>
179DGtal::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//-----------------------------------------------------------------------------
190template <typename TPoint>
191template <typename OutputIterator, typename VertexPredicate>
194DGtal::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//-----------------------------------------------------------------------------
205template <typename TPoint>
207typename DGtal::PolygonalSurface<TPoint>::ArcRange
208DGtal::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//-----------------------------------------------------------------------------
224template <typename TPoint>
226typename DGtal::PolygonalSurface<TPoint>::ArcRange
227DGtal::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//-----------------------------------------------------------------------------
243template <typename TPoint>
245typename DGtal::PolygonalSurface<TPoint>::FaceRange
246DGtal::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//-----------------------------------------------------------------------------
262template <typename TPoint>
264typename DGtal::PolygonalSurface<TPoint>::Vertex
265DGtal::PolygonalSurface<TPoint>::head( const Arc & a ) const
267 return myHEDS.halfEdge( a ).toVertex;
270//-----------------------------------------------------------------------------
271template <typename TPoint>
273typename DGtal::PolygonalSurface<TPoint>::Vertex
274DGtal::PolygonalSurface<TPoint>::tail( const Arc & a ) const
276 return head( opposite( a ) );
279//-----------------------------------------------------------------------------
280template <typename TPoint>
282typename DGtal::PolygonalSurface<TPoint>::Arc
283DGtal::PolygonalSurface<TPoint>::opposite( const Arc & a ) const
285 return myHEDS.halfEdge( a ).opposite;
288//-----------------------------------------------------------------------------
289template <typename TPoint>
291typename DGtal::PolygonalSurface<TPoint>::Arc
292DGtal::PolygonalSurface<TPoint>::next( const Arc & a ) const
294 return myHEDS.halfEdge( a ).next;
296//-----------------------------------------------------------------------------
297template <typename TPoint>
299typename DGtal::PolygonalSurface<TPoint>::Arc
300DGtal::PolygonalSurface<TPoint>::arc
301( const Vertex & t, const Vertex & h ) const
303 return myHEDS.halfEdgeIndexFromArc( t, h );
306//-----------------------------------------------------------------------------
307template <typename TPoint>
309typename DGtal::PolygonalSurface<TPoint>::Face
310DGtal::PolygonalSurface<TPoint>::faceAroundArc( const Arc & a ) const
312 return myHEDS.halfEdge( a ).face;
314//-----------------------------------------------------------------------------
315template <typename TPoint>
317typename DGtal::PolygonalSurface<TPoint>::FaceRange
318DGtal::PolygonalSurface<TPoint>::facesAroundArc( const Arc & a ) const
321 Face f = faceAroundArc( a );
322 if ( f != INVALID_FACE ) result.push_back( f );
326//-----------------------------------------------------------------------------
327template <typename TPoint>
329typename DGtal::PolygonalSurface<TPoint>::VertexRange
330DGtal::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//-----------------------------------------------------------------------------
347template <typename TPoint>
349typename DGtal::PolygonalSurface<TPoint>::ArcRange
350DGtal::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//-----------------------------------------------------------------------------
367template <typename TPoint>
370DGtal::PolygonalSurface<TPoint>::isVertexBoundary( const Vertex& v ) const
372 return myHEDS.isVertexBoundary( v );
375//-----------------------------------------------------------------------------
376template <typename TPoint>
379DGtal::PolygonalSurface<TPoint>::isArcBoundary( const Arc& v ) const
381 return INVALID_FACE == myHEDS.halfEdge( v ).face;
384//-----------------------------------------------------------------------------
385template <typename TPoint>
387typename DGtal::PolygonalSurface<TPoint>::FaceRange
388DGtal::PolygonalSurface<TPoint>::allFaces() const
390 FaceRange result( nbFaces() );
391 for ( Face fi = 0; fi < result.size(); ++fi )
395//-----------------------------------------------------------------------------
396template <typename TPoint>
398typename DGtal::PolygonalSurface<TPoint>::ArcRange
399DGtal::PolygonalSurface<TPoint>::allArcs() const
401 ArcRange result( nbArcs() );
402 for ( Arc fi = 0; fi < result.size(); ++fi )
406//-----------------------------------------------------------------------------
407template <typename TPoint>
409typename DGtal::PolygonalSurface<TPoint>::VertexRange
410DGtal::PolygonalSurface<TPoint>::allVertices() const
412 VertexRange result( nbVertices() );
413 for ( Vertex fi = 0; fi < result.size(); ++fi )
418//-----------------------------------------------------------------------------
419template <typename TPoint>
421typename DGtal::PolygonalSurface<TPoint>::ArcRange
422DGtal::PolygonalSurface<TPoint>::allBoundaryArcs() const
424 return myHEDS.boundaryHalfEdgeIndices();
427//-----------------------------------------------------------------------------
428template <typename TPoint>
430typename DGtal::PolygonalSurface<TPoint>::VertexRange
431DGtal::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.
444template <typename TPoint>
447DGtal::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.
458template <typename TPoint>
461DGtal::PolygonalSurface<TPoint>::isValid() const
468///////////////////////////////////////////////////////////////////////////////
469// Implementation of inline functions //
471template <typename TPoint>
474DGtal::operator<< ( std::ostream & out,
475 const PolygonalSurface<TPoint> & object )
477 object.selfDisplay( out );
482///////////////////////////////////////////////////////////////////////////////