DGtal 1.4.0
Loading...
Searching...
No Matches
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
41template <typename TPoint>
42inline
43DGtal::PolygonalSurface<TPoint>::PolygonalSurface
44( Clone<HalfEdgeDataStructure> aHeds,
45 Clone<PositionsStorage> pos )
46 : myHEDS( aHeds ), myPositions( pos )
47{
48 isHEDSValid = ( myPositions.size() == myHEDS.nbVertices() );
49}
50
51//-----------------------------------------------------------------------------
52template <typename TPoint>
53inline
54bool
55DGtal::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//-----------------------------------------------------------------------------
74template <typename TPoint>
75inline
76void
77DGtal::PolygonalSurface<TPoint>::clear()
78{
79 isHEDSValid = false;
80 myHEDS.clear();
81 myPositions.clear();
82 myPolygonalFaces.clear();
83
84}
85//-----------------------------------------------------------------------------
86template <typename TPoint>
87inline
88typename DGtal::PolygonalSurface<TPoint>::VertexIndex
89DGtal::PolygonalSurface<TPoint>::addVertex( const Point& vdata )
90{
91 VertexIndex vi = myPositions.size();
92 myPositions.push_back( vdata );
93 return vi;
94}
95
96//-----------------------------------------------------------------------------
97template <typename TPoint>
98inline
99typename DGtal::PolygonalSurface<TPoint>::FaceIndex
100DGtal::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//-----------------------------------------------------------------------------
108template <typename TPoint>
109inline
110typename DGtal::PolygonalSurface<TPoint>::FaceIndex
111DGtal::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//-----------------------------------------------------------------------------
119template <typename TPoint>
120inline
121typename DGtal::PolygonalSurface<TPoint>::FaceIndex
122DGtal::PolygonalSurface<TPoint>::addPolygonalFace
123( const PolygonalFace& f )
124{
125 FaceIndex fi = myPolygonalFaces.size();
126 myPolygonalFaces.push_back( f );
127 return fi;
128}
129
130//-----------------------------------------------------------------------------
131template <typename TPoint>
132inline
133typename DGtal::PolygonalSurface<TPoint>::Point&
134DGtal::PolygonalSurface<TPoint>::position( Vertex v )
135{
136 ASSERT( v < myPositions.size() );
137 return myPositions[ v ];
138}
139//-----------------------------------------------------------------------------
140template <typename TPoint>
141inline
142const typename DGtal::PolygonalSurface<TPoint>::Point&
143DGtal::PolygonalSurface<TPoint>::position( Vertex v ) const
144{
145 ASSERT( v < myPositions.size() );
146 return myPositions[ v ];
147}
148//-----------------------------------------------------------------------------
149template <typename TPoint>
150inline
151typename DGtal::PolygonalSurface<TPoint>::Size
152DGtal::PolygonalSurface<TPoint>::size() const
153{
154 return myPositions.size();
155}
156//-----------------------------------------------------------------------------
157template <typename TPoint>
158inline
159typename DGtal::PolygonalSurface<TPoint>::Size
160DGtal::PolygonalSurface<TPoint>::bestCapacity() const
161{
162 return 8;
163}
164//-----------------------------------------------------------------------------
165template <typename TPoint>
166inline
167typename DGtal::PolygonalSurface<TPoint>::Size
168DGtal::PolygonalSurface<TPoint>::degree( const Vertex & v ) const
169{
170 ASSERT( isValid() );
171 return myHEDS.nbNeighboringVertices( v );
172}
173
174//-----------------------------------------------------------------------------
175template <typename TPoint>
176template <typename OutputIterator>
177inline
178void
179DGtal::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//-----------------------------------------------------------------------------
190template <typename TPoint>
191template <typename OutputIterator, typename VertexPredicate>
192inline
193void
194DGtal::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//-----------------------------------------------------------------------------
205template <typename TPoint>
206inline
207typename DGtal::PolygonalSurface<TPoint>::ArcRange
208DGtal::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//-----------------------------------------------------------------------------
224template <typename TPoint>
225inline
226typename DGtal::PolygonalSurface<TPoint>::ArcRange
227DGtal::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//-----------------------------------------------------------------------------
243template <typename TPoint>
244inline
245typename DGtal::PolygonalSurface<TPoint>::FaceRange
246DGtal::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//-----------------------------------------------------------------------------
262template <typename TPoint>
263inline
264typename DGtal::PolygonalSurface<TPoint>::Vertex
265DGtal::PolygonalSurface<TPoint>::head( const Arc & a ) const
266{
267 return myHEDS.halfEdge( a ).toVertex;
268}
269
270//-----------------------------------------------------------------------------
271template <typename TPoint>
272inline
273typename DGtal::PolygonalSurface<TPoint>::Vertex
274DGtal::PolygonalSurface<TPoint>::tail( const Arc & a ) const
275{
276 return head( opposite( a ) );
277}
278
279//-----------------------------------------------------------------------------
280template <typename TPoint>
281inline
282typename DGtal::PolygonalSurface<TPoint>::Arc
283DGtal::PolygonalSurface<TPoint>::opposite( const Arc & a ) const
284{
285 return myHEDS.halfEdge( a ).opposite;
286}
287
288//-----------------------------------------------------------------------------
289template <typename TPoint>
290inline
291typename DGtal::PolygonalSurface<TPoint>::Arc
292DGtal::PolygonalSurface<TPoint>::next( const Arc & a ) const
293{
294 return myHEDS.halfEdge( a ).next;
295}
296//-----------------------------------------------------------------------------
297template <typename TPoint>
298inline
299typename DGtal::PolygonalSurface<TPoint>::Arc
300DGtal::PolygonalSurface<TPoint>::arc
301( const Vertex & t, const Vertex & h ) const
302{
303 return myHEDS.halfEdgeIndexFromArc( t, h );
304}
305
306//-----------------------------------------------------------------------------
307template <typename TPoint>
308inline
309typename DGtal::PolygonalSurface<TPoint>::Face
310DGtal::PolygonalSurface<TPoint>::faceAroundArc( const Arc & a ) const
311{
312 return myHEDS.halfEdge( a ).face;
313}
314//-----------------------------------------------------------------------------
315template <typename TPoint>
316inline
317typename DGtal::PolygonalSurface<TPoint>::FaceRange
318DGtal::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//-----------------------------------------------------------------------------
327template <typename TPoint>
328inline
329typename DGtal::PolygonalSurface<TPoint>::VertexRange
330DGtal::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//-----------------------------------------------------------------------------
347template <typename TPoint>
348inline
349typename DGtal::PolygonalSurface<TPoint>::ArcRange
350DGtal::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//-----------------------------------------------------------------------------
367template <typename TPoint>
368inline
369bool
370DGtal::PolygonalSurface<TPoint>::isVertexBoundary( const Vertex& v ) const
371{
372 return myHEDS.isVertexBoundary( v );
373}
374
375//-----------------------------------------------------------------------------
376template <typename TPoint>
377inline
378bool
379DGtal::PolygonalSurface<TPoint>::isArcBoundary( const Arc& v ) const
380{
381 return INVALID_FACE == myHEDS.halfEdge( v ).face;
382}
383
384//-----------------------------------------------------------------------------
385template <typename TPoint>
386inline
387typename DGtal::PolygonalSurface<TPoint>::FaceRange
388DGtal::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//-----------------------------------------------------------------------------
396template <typename TPoint>
397inline
398typename DGtal::PolygonalSurface<TPoint>::ArcRange
399DGtal::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//-----------------------------------------------------------------------------
407template <typename TPoint>
408inline
409typename DGtal::PolygonalSurface<TPoint>::VertexRange
410DGtal::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//-----------------------------------------------------------------------------
419template <typename TPoint>
420inline
421typename DGtal::PolygonalSurface<TPoint>::ArcRange
422DGtal::PolygonalSurface<TPoint>::allBoundaryArcs() const
423{
424 return myHEDS.boundaryHalfEdgeIndices();
425}
426
427//-----------------------------------------------------------------------------
428template <typename TPoint>
429inline
430typename DGtal::PolygonalSurface<TPoint>::VertexRange
431DGtal::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 */
444template <typename TPoint>
445inline
446void
447DGtal::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 */
458template <typename TPoint>
459inline
460bool
461DGtal::PolygonalSurface<TPoint>::isValid() const
462{
463 return isHEDSValid;
464}
465
466
467
468///////////////////////////////////////////////////////////////////////////////
469// Implementation of inline functions //
470
471template <typename TPoint>
472inline
473std::ostream&
474DGtal::operator<< ( std::ostream & out,
475 const PolygonalSurface<TPoint> & object )
476{
477 object.selfDisplay( out );
478 return out;
479}
480
481// //
482///////////////////////////////////////////////////////////////////////////////
483
484