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 IndexedDigitalSurface.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 IndexedDigitalSurface.h
26 * This file is part of the DGtal library.
30//////////////////////////////////////////////////////////////////////////////
33#include "DGtal/topology/DigitalSurface.h"
34#include "DGtal/topology/CanonicSCellEmbedder.h"
35//////////////////////////////////////////////////////////////////////////////
37///////////////////////////////////////////////////////////////////////////////
38// IMPLEMENTATION of inline methods.
39///////////////////////////////////////////////////////////////////////////////
41///////////////////////////////////////////////////////////////////////////////
42// ----------------------- Standard services ------------------------------
44//-----------------------------------------------------------------------------
45template <typename TDigitalSurfaceContainer>
48DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::build
49( ConstAlias< DigitalSurfaceContainer > surfContainer )
52 trace.warning() << "[DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::build()]"
53 << " attempting to rebuild a polygonal surface." << std::endl;
56 myContainer = CountedConstPtrOrConstPtr< DigitalSurfaceContainer >( surfContainer );
57 DigitalSurface< DigitalSurfaceContainer > surface( *myContainer );
58 CanonicSCellEmbedder< KSpace > embedder( myContainer->space() );
59 // Numbering surfels / vertices
61 for ( SCell aSurfel : surface )
63 myPositions.push_back( embedder( aSurfel ) );
64 mySurfel2VertexIndex[ aSurfel ] = i++;
66 // Numbering pointels / faces
68 auto faces = surface.allClosedFaces();
69 for ( auto aFace : faces )
71 auto vtcs = surface.verticesAroundFace( aFace );
72 PolygonalFace idx_face( vtcs.size() );
73 std::transform( vtcs.cbegin(), vtcs.cend(), idx_face.begin(),
75 ( const SCell& v ) { return mySurfel2VertexIndex[ v ]; } );
76 myPolygonalFaces.push_back( idx_face );
77 myPointel2FaceIndex[ surface.pivot( aFace ) ] = j++;
79 isHEDSValid = myHEDS.build( myPolygonalFaces );
80 if ( myHEDS.nbVertices() != myPositions.size() ) {
81 trace.warning() << "[DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::build()]"
82 << " the size of vertex data array (s1) and the number of vertices (s2) in the polygonal surface does not match:"
83 << " s1=" << myPositions.size()
84 << " s2=" << myHEDS.nbVertices() << std::endl;
88 { // We build the mapping for vertices and faces
89 myVertexIndex2Surfel.resize( nbVertices() );
90 myFaceIndex2Pointel .resize( nbFaces() );
91 myArc2Linel .resize( nbArcs() );
92 for ( auto p : mySurfel2VertexIndex )
93 myVertexIndex2Surfel[ p.second ] = p.first;
94 for ( auto p : myPointel2FaceIndex )
95 myFaceIndex2Pointel [ p.second ] = p.first;
96 // We build the mapping for arcs
98 for ( Arc fi = 0; fi < myArc2Linel.size(); ++fi )
100 auto vi_vj = myHEDS.arcFromHalfEdgeIndex( fi );
101 SCell surfi = myVertexIndex2Surfel[ vi_vj.first ];
102 SCell surfj = myVertexIndex2Surfel[ vi_vj.second ];
103 SCell lnl = surface.separator( surface.arc( surfi, surfj ) );
104 myLinel2Arc[ lnl ] = fi;
105 myArc2Linel[ fi ] = lnl;
106 // trace.info() << "- Arc " << fi
107 // << " (" << vi_vj.first << "," << vi_vj.second << ") "
108 // << " (" << surfi << "," << surfj << ") "
109 // << " lnl=" << lnl << space().sDim( lnl ) << std::endl;
115//-----------------------------------------------------------------------------
116template <typename TDigitalSurfaceContainer>
119DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::clear()
125 myPolygonalFaces.clear();
126 mySurfel2VertexIndex.clear();
128 myPointel2FaceIndex.clear();
129 myVertexIndex2Surfel.clear();
131 myFaceIndex2Pointel.clear();
134//-----------------------------------------------------------------------------
135template <typename TDigitalSurfaceContainer>
137typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::RealPoint&
138DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::position( Vertex v )
140 ASSERT( 0 <= v && v < myPositions.size() );
141 return myPositions[ v ];
143//-----------------------------------------------------------------------------
144template <typename TDigitalSurfaceContainer>
146const typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::RealPoint&
147DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::position( Vertex v ) const
149 ASSERT( 0 <= v && v < myPositions.size() );
150 return myPositions[ v ];
152//-----------------------------------------------------------------------------
153template <typename TDigitalSurfaceContainer>
155typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::Size
156DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::size() const
158 return myPositions.size();
160//-----------------------------------------------------------------------------
161template <typename TDigitalSurfaceContainer>
163typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::Size
164DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::bestCapacity() const
168//-----------------------------------------------------------------------------
169template <typename TDigitalSurfaceContainer>
171typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::Size
172DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::degree( const Vertex & v ) const
175 return myHEDS.nbNeighboringVertices( v );
178//-----------------------------------------------------------------------------
179template <typename TDigitalSurfaceContainer>
180template <typename OutputIterator>
183DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::writeNeighbors
184( OutputIterator &it, const Vertex & v ) const
187 typedef HalfEdgeDataStructure::VertexIndexRange VertexIndexRange;
188 VertexIndexRange neighbors;
189 myHEDS.getNeighboringVertices( v, neighbors );
190 for ( Vertex nv : neighbors ) *it++ = nv;
193//-----------------------------------------------------------------------------
194template <typename TDigitalSurfaceContainer>
195template <typename OutputIterator, typename VertexPredicate>
198DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::writeNeighbors
199( OutputIterator &it, const Vertex & v, const VertexPredicate & pred) const
202 typedef HalfEdgeDataStructure::VertexIndexRange VertexIndexRange;
203 VertexIndexRange neighbors;
204 myHEDS.getNeighboringVertices( v, neighbors );
205 for ( Vertex nv : neighbors ) if ( pred( nv ) ) *it++ = nv;
208//-----------------------------------------------------------------------------
209template <typename TDigitalSurfaceContainer>
211typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::ArcRange
212DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::outArcs( const Vertex & v ) const
215 const Index start_hei = myHEDS.halfEdgeIndexFromVertexIndex( v );
216 Index hei = start_hei;
219 const HalfEdge& he = myHEDS.halfEdge( hei );
220 if( INVALID_FACE != he.face ) result.push_back( hei );
221 hei = myHEDS.halfEdge( he.opposite ).next;
223 while ( hei != start_hei );
227//-----------------------------------------------------------------------------
228template <typename TDigitalSurfaceContainer>
230typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::ArcRange
231DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::inArcs( const Vertex & v ) const
234 const Index start_hei = myHEDS.halfEdgeIndexFromVertexIndex( v );
235 Index hei = start_hei;
238 const HalfEdge& he = myHEDS.halfEdge( hei );
239 if( INVALID_FACE != he.face ) result.push_back( he.opposite );
240 hei = myHEDS.halfEdge( he.opposite ).next;
242 while ( hei != start_hei );
246//-----------------------------------------------------------------------------
247template <typename TDigitalSurfaceContainer>
249typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::FaceRange
250DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::facesAroundVertex( const Vertex & v ) const
253 const Index start_hei = myHEDS.halfEdgeIndexFromVertexIndex( v );
254 Index hei = start_hei;
257 const HalfEdge& he = myHEDS.halfEdge( hei );
258 if( INVALID_FACE != he.face ) result.push_back( he.face );
259 hei = myHEDS.halfEdge( he.opposite ).next;
261 while ( hei != start_hei );
265//-----------------------------------------------------------------------------
266template <typename TDigitalSurfaceContainer>
268typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::Vertex
269DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::head( const Arc & a ) const
271 return myHEDS.halfEdge( a ).toVertex;
274//-----------------------------------------------------------------------------
275template <typename TDigitalSurfaceContainer>
277typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::Vertex
278DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::tail( const Arc & a ) const
280 return head( opposite( a ) );
283//-----------------------------------------------------------------------------
284template <typename TDigitalSurfaceContainer>
286typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::Arc
287DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::opposite( const Arc & a ) const
289 return myHEDS.halfEdge( a ).opposite;
292//-----------------------------------------------------------------------------
293template <typename TDigitalSurfaceContainer>
295typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::Arc
296DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::next( const Arc & a ) const
298 return myHEDS.halfEdge( a ).next;
300//-----------------------------------------------------------------------------
301template <typename TDigitalSurfaceContainer>
303typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::Arc
304DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::arc
305( const Vertex & t, const Vertex & h ) const
307 return myHEDS.halfEdgeIndexFromArc( t, h );
310//-----------------------------------------------------------------------------
311template <typename TDigitalSurfaceContainer>
313typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::Face
314DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::faceAroundArc( const Arc & a ) const
316 return myHEDS.halfEdge( a ).face;
318//-----------------------------------------------------------------------------
319template <typename TDigitalSurfaceContainer>
321typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::FaceRange
322DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::facesAroundArc( const Arc & a ) const
325 Face f = faceAroundArc( a );
326 if ( f != INVALID_FACE ) result.push_back( f );
330//-----------------------------------------------------------------------------
331template <typename TDigitalSurfaceContainer>
333typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::VertexRange
334DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::verticesAroundFace( const Face & f ) const
337 const Index start_hei = myHEDS.halfEdgeIndexFromFaceIndex( f );
338 Index hei = start_hei;
340 const HalfEdge& he = myHEDS.halfEdge( hei );
341 ASSERT( ( he.face == f )
342 && "[IndexedDigitalSurface::verticesAroundFace] invalid face." );
343 result.push_back( he.toVertex );
345 } while ( hei != start_hei );
346 ASSERT( result.size() >= 3 );
350//-----------------------------------------------------------------------------
351template <typename TDigitalSurfaceContainer>
354DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::isVertexBoundary( const Vertex& v ) const
356 return myHEDS.isVertexBoundary( v );
359//-----------------------------------------------------------------------------
360template <typename TDigitalSurfaceContainer>
363DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::isArcBoundary( const Arc& v ) const
365 return INVALID_FACE == myHEDS.halfEdge( v ).face;
368//-----------------------------------------------------------------------------
369template <typename TDigitalSurfaceContainer>
371typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::FaceRange
372DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::allFaces() const
374 FaceRange result( nbFaces() );
375 for ( Face fi = 0; fi < result.size(); ++fi )
379//-----------------------------------------------------------------------------
380template <typename TDigitalSurfaceContainer>
382typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::ArcRange
383DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::allArcs() const
385 ArcRange result( nbArcs() );
386 for ( Arc fi = 0; fi < result.size(); ++fi )
390//-----------------------------------------------------------------------------
391template <typename TDigitalSurfaceContainer>
393typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::VertexRange
394DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::allVertices() const
396 VertexRange result( nbVertices() );
397 for ( Vertex fi = 0; fi < result.size(); ++fi )
402//-----------------------------------------------------------------------------
403template <typename TDigitalSurfaceContainer>
405typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::ArcRange
406DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::allBoundaryArcs() const
408 return myHEDS.boundaryHalfEdgeIndices();
411//-----------------------------------------------------------------------------
412template <typename TDigitalSurfaceContainer>
414typename DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::VertexRange
415DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::allBoundaryVertices() const
417 return myHEDS.boundaryVertices();
421///////////////////////////////////////////////////////////////////////////////
422// Interface - public :
425 * Writes/Displays the object on an output stream.
426 * @param out the output stream where the object is written.
428template <typename TDigitalSurfaceContainer>
431DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::selfDisplay ( std::ostream & out ) const
433 out << "[IndexedDigitalSurface #V=" << myHEDS.nbVertices()
434 << " #E=" << myHEDS.nbEdges() << " #F=" << myHEDS.nbFaces()
435 << " Chi=" << Euler() << "]";
439 * Checks the validity/consistency of the object.
440 * @return 'true' if the object is valid, 'false' otherwise.
442template <typename TDigitalSurfaceContainer>
445DGtal::IndexedDigitalSurface<TDigitalSurfaceContainer>::isValid() const
452///////////////////////////////////////////////////////////////////////////////
453// Implementation of inline functions //
455template <typename TDigitalSurfaceContainer>
458DGtal::operator<< ( std::ostream & out,
459 const IndexedDigitalSurface<TDigitalSurfaceContainer> & object )
461 object.selfDisplay( out );
466///////////////////////////////////////////////////////////////////////////////