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 SurfaceMesh.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 SurfaceMesh.h
26 * This file is part of the DGtal library.
30 //////////////////////////////////////////////////////////////////////////////
33 //////////////////////////////////////////////////////////////////////////////
35 ///////////////////////////////////////////////////////////////////////////////
36 // IMPLEMENTATION of inline methods.
37 ///////////////////////////////////////////////////////////////////////////////
39 ///////////////////////////////////////////////////////////////////////////////
40 // ----------------------- Standard services ------------------------------
42 //-----------------------------------------------------------------------------
43 template <typename TRealPoint, typename TRealVector>
44 template <typename RealPointIterator, typename VerticesIterator>
45 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
46 SurfaceMesh( RealPointIterator itPos, RealPointIterator itPosEnd,
47 VerticesIterator itVertices, VerticesIterator itVerticesEnd )
49 bool ok = init( itPos, itPosEnd, itVertices, itVerticesEnd );
53 //-----------------------------------------------------------------------------
54 template <typename TRealPoint, typename TRealVector>
55 template <typename RealPointIterator, typename VerticesIterator>
57 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
58 init( RealPointIterator itPos, RealPointIterator itPosEnd,
59 VerticesIterator itVertices, VerticesIterator itVerticesEnd )
62 myPositions = std::vector< RealPoint >( itPos, itPosEnd );
63 myIncidentFaces.resize( myPositions.size() );
64 Index f = 0; // current face index
66 for ( ; itVertices != itVerticesEnd; ++itVertices, ++f )
69 for ( auto it = itVertices->begin(), itE = itVertices->end(); it != itE; ++it )
72 if ( vtx >= nbVertices() )
74 trace.warning() << "[SurfaceMesh::init] Invalid vtx "
75 << vtx << " at face " << f
76 << " since #V=" << nbVertices()
77 << ". Ignoring vertex." << std::endl;
82 myIncidentFaces[ vtx ].push_back( f );
83 f_vtcs.push_back( vtx );
86 myIncidentVertices.push_back( f_vtcs );
93 //-----------------------------------------------------------------------------
94 template <typename TRealPoint, typename TRealVector>
96 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
99 myIncidentVertices.clear();
100 myIncidentFaces.clear();
102 myVertexNormals.clear();
103 myFaceNormals.clear();
104 myNeighborFaces.clear();
105 myNeighborVertices.clear();
106 myEdgeVertices.clear();
108 myEdgeRightFaces.clear();
109 myEdgeLeftFaces.clear();
112 //-----------------------------------------------------------------------------
113 template <typename TRealPoint, typename TRealVector>
114 template <typename RealVectorIterator>
116 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
117 setVertexNormals( RealVectorIterator itN, RealVectorIterator itNEnd )
119 myVertexNormals = std::vector< RealVector >( itN, itNEnd );
120 return myVertexNormals.size() == myPositions.size();
123 //-----------------------------------------------------------------------------
124 template <typename TRealPoint, typename TRealVector>
125 template <typename RealVectorIterator>
127 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
128 setFaceNormals( RealVectorIterator itN, RealVectorIterator itNEnd )
130 myFaceNormals = std::vector< RealVector >( itN, itNEnd );
131 return myFaceNormals.size() == myIncidentVertices.size();
134 //-----------------------------------------------------------------------------
135 template <typename TRealPoint, typename TRealVector>
137 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
138 computeFaceNormalsFromPositions()
140 myFaceNormals.resize( myIncidentVertices.size() );
142 for ( auto face : myIncidentVertices )
144 RealPoint p; // barycenter
145 RealVector n; // normal
146 // compute barycenter
147 for ( auto idx : face ) p += myPositions[ idx ];
149 // compute normal as sum of triangle normal vectors.
150 for ( Index i = 0; i < face.size(); ++i )
152 const Index j = face[ i ];
153 const Index nj = face[ (i+1) % face.size() ];
154 n += ( myPositions[ j ] - p ).crossProduct( myPositions[ nj ] - p );
156 auto n_norm = n.norm();
157 myFaceNormals[ f ] = n_norm != 0.0 ? n / n_norm : n;
162 //-----------------------------------------------------------------------------
163 template <typename TRealPoint, typename TRealVector>
165 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
166 computeFaceNormalsFromVertexNormals()
168 if ( myVertexNormals.empty() ) return;
169 myFaceNormals.resize( myIncidentVertices.size() );
171 for ( auto face : myIncidentVertices )
173 RealVector n; // normal
174 for ( auto idx : face ) n += myVertexNormals[ idx ];
175 auto n_norm = n.norm();
176 myFaceNormals[ f ] = n_norm != 0.0 ? n / n_norm : n;
180 //-----------------------------------------------------------------------------
181 template <typename TRealPoint, typename TRealVector>
183 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
184 computeVertexNormalsFromFaceNormals()
186 if ( myFaceNormals.empty() ) return;
187 myVertexNormals.resize( myIncidentFaces.size() );
189 for ( auto vertex : myIncidentFaces )
191 RealVector n; // normal
192 for ( auto idx : vertex ) n += myFaceNormals[ idx ];
193 auto n_norm = n.norm();
194 myVertexNormals[ v ] = n_norm != 0.0 ? n / n_norm : n;
198 //-----------------------------------------------------------------------------
199 template <typename TRealPoint, typename TRealVector>
201 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
202 computeVertexNormalsFromFaceNormalsWithMaxWeights()
204 if ( myFaceNormals.empty() ) return;
205 myVertexNormals.resize( myIncidentFaces.size() );
207 for ( auto incident_faces : myIncidentFaces )
209 RealVector n; // normal
210 const auto weights = getMaxWeights( v );
212 for ( auto idx_f : incident_faces ) n += weights[ i++ ] * myFaceNormals[ idx_f ];
213 auto n_norm = n.norm();
214 myVertexNormals[ v ] = n_norm != 0.0 ? n / n_norm : n;
219 //-----------------------------------------------------------------------------
220 template <typename TRealPoint, typename TRealVector>
221 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Scalars
222 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
223 getMaxWeights( Index v ) const
226 const auto & neighbors = myNeighborVertices[ v ];
227 const RealPoint x = myPositions[ v ];
228 for ( auto idx_f : myIncidentFaces[ v ] )
230 // Find adjacent vertices to v
231 std::vector< Index > adj_vertices;
232 for ( auto idx_v : myIncidentVertices[ idx_f ] )
234 auto it = std::find( neighbors.cbegin(), neighbors.cend(), idx_v );
235 if ( it != neighbors.cend() ) adj_vertices.push_back( *it );
237 if ( adj_vertices.size() != 2 )
239 trace.warning() << "[SurfaceMesh::getMaxWeights] "
240 << adj_vertices.size() << " adjacent vertices to vertex "
241 << v << " on face" << idx_f << "." << std::endl;
242 for ( auto a : adj_vertices ) std::cerr << " " << a;
243 std::cerr << std::endl;
245 if (adj_vertices.size() >= 2 )
247 const Scalar area = faceArea( idx_f );
248 const Scalar l1 = ( myPositions[ adj_vertices[ 0 ] ] - x ).squaredNorm();
249 const Scalar l2 = ( myPositions[ adj_vertices[ 1 ] ] - x ).squaredNorm();
250 const Scalar l1l2 = l1 * l2;
251 weights.push_back( l1l2 != 0 ? fabs( area ) / l1l2 : 0.0 );
253 else weights.push_back( 0.0 );
258 //-----------------------------------------------------------------------------
259 template <typename TRealPoint, typename TRealVector>
260 template <typename AnyRing>
262 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
263 computeFaceValuesFromVertexValues( const std::vector<AnyRing>& vvalues ) const
265 ASSERT( vvalues.size() == nbVertices() );
266 std::vector<AnyRing> fvalues( nbFaces() );
268 for ( auto face : myIncidentVertices )
270 AnyRing n = NumberTraits<AnyRing>::ZERO;
271 for ( auto idx : face ) n += vvalues[ idx ];
272 fvalues[ f++ ] = n / face.size();
277 template <typename TRealPoint, typename TRealVector>
278 template <typename AnyRing>
280 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
281 computeVertexValuesFromFaceValues( const std::vector<AnyRing>& fvalues ) const
283 ASSERT( fvalues.size() == nbFaces() );
284 std::vector<AnyRing> vvalues( nbVertices() );
286 for ( auto vertex : myIncidentFaces )
288 AnyRing n = NumberTraits<AnyRing>::ZERO;
289 for ( auto idx : vertex ) n += fvalues[ idx ];
290 vvalues[ v++ ] = n / vertex.size();
295 //-----------------------------------------------------------------------------
296 template <typename TRealPoint, typename TRealVector>
297 std::vector<TRealVector>
298 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
299 computeFaceUnitVectorsFromVertexUnitVectors
300 ( const std::vector<RealVector>& vuvectors ) const
302 ASSERT( vuvectors.size() == nbVertices() );
303 std::vector<RealVector> fuvectors( nbFaces() );
305 for ( auto face : myIncidentVertices )
308 for ( auto idx : face ) n += vuvectors[ idx ];
309 const auto n_norm = n.norm();
310 fuvectors[ f++ ] = n_norm != 0.0 ? n / n_norm : n;
315 //-----------------------------------------------------------------------------
316 template <typename TRealPoint, typename TRealVector>
317 std::vector<TRealVector>
318 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
319 computeVertexUnitVectorsFromFaceUnitVectors
320 ( const std::vector<RealVector>& fuvectors ) const
322 ASSERT( fuvectors.size() == nbFaces() );
323 std::vector<RealVector> vuvectors( nbVertices() );
325 for ( auto vertex : myIncidentFaces )
328 for ( auto idx : vertex ) n += fuvectors[ idx ];
329 const auto n_norm = n.norm();
330 vuvectors[ v++ ] = n_norm != 0.0 ? n / n_norm : n;
336 //-----------------------------------------------------------------------------
337 template <typename TRealPoint, typename TRealVector>
338 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Edge
339 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
340 makeEdge( Vertex i, Vertex j ) const
342 VertexPair vp = i < j ? std::make_pair( i,j ) : std::make_pair( j,i );
343 auto it = std::lower_bound( myEdgeVertices.cbegin(), myEdgeVertices.cend(), vp );
344 if ( it == myEdgeVertices.cend() || *it != vp ) return nbEdges();
345 return it - myEdgeVertices.cbegin();
348 //-----------------------------------------------------------------------------
349 template <typename TRealPoint, typename TRealVector>
350 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Scalar
351 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
352 averageEdgeLength() const
354 double lengths = 0.0;
355 for ( Edge e = 0; e < nbEdges(); ++e )
357 auto vtcs = edgeVertices( e );
358 const RealPoint p = myPositions[ vtcs.first ];
359 const RealVector pq = myPositions[ vtcs.second ] - p;
360 lengths += pq.norm();
362 lengths /= nbEdges();
366 //-----------------------------------------------------------------------------
367 template <typename TRealPoint, typename TRealVector>
368 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Scalar
369 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
370 localWindow( Face f ) const
372 const RealPoint x = faceCentroid( f );
373 Scalar local_length = 0.0;
374 for ( auto v : incidentVertices( f ) )
375 local_length += ( myPositions[ v ] - x ).norm();
376 return local_length / incidentVertices( f ).size();
379 //-----------------------------------------------------------------------------
380 template <typename TRealPoint, typename TRealVector>
382 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
383 perturbateWithUniformRandomNoise( Scalar p )
385 for ( auto& x : myPositions )
387 RealVector d( rand01()*2.0 - 1.0, rand01()*2.0 - 1.0, rand01()*2.0 - 1.0 );
388 d = d.getNormalized();
389 Scalar l = rand01() * p;
394 //-----------------------------------------------------------------------------
395 template <typename TRealPoint, typename TRealVector>
397 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
398 perturbateWithAdaptiveUniformRandomNoise( Scalar p )
400 Scalars local_average_lengths( nbVertices() );
401 for ( Index v = 0; v < nbVertices(); ++v )
403 const RealPoint x = myPositions[ v ];
404 Scalar local_length = 0.0;
405 for ( auto nv : myNeighborVertices[ v ] )
406 local_length += ( myPositions[ nv ] - x ).norm();
407 local_average_lengths[ v ] = local_length / myNeighborVertices[ v ].size();
409 for ( Index v = 0; v < nbVertices(); ++v )
411 RealVector d( rand01()*2.0 - 1.0, rand01()*2.0 - 1.0, rand01()*2.0 - 1.0 );
412 d = d.getNormalized();
413 Scalar l = rand01() * p * local_average_lengths[ v ];
414 myPositions[ v ] += l * d;
418 //-----------------------------------------------------------------------------
419 template <typename TRealPoint, typename TRealVector>
420 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::RealPoint
421 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
422 faceCentroid( Index f ) const
425 for ( auto v : myIncidentVertices[ f ] )
426 c += myPositions[ v ];
427 return c / myIncidentVertices[ f ].size();
430 //-----------------------------------------------------------------------------
431 template <typename TRealPoint, typename TRealVector>
432 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::RealPoint
433 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
434 edgeCentroid( Index e ) const
436 const auto& vtcs = myEdgeVertices[ e ];
437 RealPoint c = myPositions[ vtcs.first ] + myPositions[ vtcs.second ];
441 //-----------------------------------------------------------------------------
442 template <typename TRealPoint, typename TRealVector>
443 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Scalar
444 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
445 faceArea( Index f ) const
448 const auto & inc_vtcs = myIncidentVertices[ f ];
449 RealPoint p = myPositions[ inc_vtcs.back() ];
450 const Index m = inc_vtcs.size() - 2;
451 for ( Index i = 0; i < m; ++i )
452 area += ( myPositions[ inc_vtcs[ i ] ] - p )
453 .crossProduct( myPositions[ inc_vtcs[ i+1 ] ] - p ).norm();
457 //-----------------------------------------------------------------------------
458 template <typename TRealPoint, typename TRealVector>
459 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::WeightedFaces
460 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
461 computeFacesInclusionsInBall( Scalar r, Index f ) const
463 WeightedFaces result;
466 result.push_back( std::make_pair( f, 0.000001 ) );
469 RealPoint p = faceCentroid( f );
470 std::unordered_set< Index > marked;
471 std::queue< Index > active;
474 while ( ! active.empty() )
476 Index current = active.front();
478 Scalar weight = faceInclusionRatio( p, r, current );
481 result.push_back( std::make_pair( current, weight ) );
482 auto neighbors = myNeighborFaces[ current ];
483 for ( auto n : neighbors )
484 if ( marked.find( n ) == marked.end() )
494 //-----------------------------------------------------------------------------
495 template <typename TRealPoint, typename TRealVector>
497 < typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Vertices,
498 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::WeightedEdges,
499 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::WeightedFaces >
500 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
501 computeCellsInclusionsInBall( Scalar r, Index f ) const
504 std::set<Vertex> set_v;
505 WeightedEdges result_e;
506 WeightedFaces result_f;
509 result_f.push_back( std::make_pair( f, 0.000001 ) );
510 return std::make_tuple( result_v, result_e, result_f );
512 RealPoint p = faceCentroid( f );
513 std::set< Index > marked;
514 std::queue< Index > active;
517 while ( ! active.empty() )
519 Index current = active.front();
521 Scalar fweight = faceInclusionRatio( p, r, current );
524 result_f.push_back( std::make_pair( current, fweight ) );
525 // Taking care of faces, and the breadth-first traversal
526 const auto& neighbors = myNeighborFaces[ current ];
527 for ( auto n : neighbors )
528 if ( marked.find( n ) == marked.end() )
533 // Taking care of edges and vertices
534 const auto& inc_v = myIncidentVertices[ current ];
535 for ( Size i = 0; i < inc_v.size(); ++i )
537 const Vertex vi = inc_v[ i ];
538 const Vertex vn = inc_v[ (i+1) % inc_v.size() ];
539 if ( vertexInclusionRatio( p, r, vi ) > 0.0 )
541 const Edge e_ij = makeEdge( vi, vn );
542 if ( e_ij >= nbEdges() ) {
543 trace.error() << "bad edge " << vi << " " << vn << std::endl;
546 Scalar eweight = edgeInclusionRatio( p, r, e_ij );
548 result_e.push_back( std::make_pair( e_ij, eweight ) );
552 result_v = Vertices( set_v.cbegin(), set_v.cend() );
553 return std::make_tuple( result_v, result_e, result_f );
556 //-----------------------------------------------------------------------------
557 template <typename TRealPoint, typename TRealVector>
558 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Scalar
559 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
560 faceInclusionRatio( RealPoint p, Scalar r, Index f ) const
562 const auto vertices = myIncidentVertices[ f ];
563 const RealPoint b = faceCentroid( f );
564 Scalar d_min = ( b - p ).norm();
565 Scalar d_max = d_min;
566 for ( auto v : vertices )
568 Scalar d = ( myPositions[ v ] - p ).norm();
569 d_max = std::max( d_max, d );
570 d_min = std::min( d_min, d );
572 if ( d_max <= r ) return 1.0;
573 else if ( r <= d_min ) return 0.0;
574 return ( r - d_min ) / ( d_max - d_min );
577 //-----------------------------------------------------------------------------
578 template <typename TRealPoint, typename TRealVector>
579 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Scalar
580 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
581 edgeInclusionRatio( RealPoint p, Scalar r, Index e ) const
583 const auto vertices = myEdgeVertices[ e ];
584 const RealPoint b = edgeCentroid( e );
585 const Scalar d0 = ( myPositions[ vertices.first ] - p ).norm();
586 const Scalar d1 = ( myPositions[ vertices.second ] - p ).norm();
587 Scalar d_min = ( b - p ).norm();
588 Scalar d_max = d_min;
589 d_max = std::max( d_max, std::max( d0, d1 ) );
590 d_min = std::min( d_min, std::min( d0, d1 ) );
591 if ( d_max <= r ) return 1.0;
592 else if ( r <= d_min ) return 0.0;
593 return ( r - d_min ) / ( d_max - d_min );
596 //-----------------------------------------------------------------------------
597 template <typename TRealPoint, typename TRealVector>
598 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Scalar
599 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
600 vertexInclusionRatio( RealPoint p, Scalar r, Index v ) const
602 const RealPoint b = myPositions[ v ];
603 return ( ( b - p ).norm() <= r ) ? 1.0 : 0.0;
607 ///////////////////////////////////////////////////////////////////////////////
608 // Interface - public :
610 //-----------------------------------------------------------------------------
611 template <typename TRealPoint, typename TRealVector>
613 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
614 selfDisplay ( std::ostream & out ) const
616 out << "[SurfaceMesh" << ( isValid() ? " (OK)" : " (KO)" )
617 << " #V=" << myPositions.size()
618 << " #VN=" << myVertexNormals.size()
619 << " #E=" << myEdgeVertices.size()
620 << " #F=" << myIncidentVertices.size()
621 << " #FN=" << myFaceNormals.size();
625 for ( auto nf : myNeighborFaces ) nb_nf += nf.size();
626 for ( auto nv : myNeighborVertices ) nb_nv += nv.size();
627 for ( auto nfe : myEdgeFaces ) nb_nfe += nfe.size();
629 nb_nv /= nbVertices();
631 out << " E[IF]=" << nb_nf << " E[IV]=" << nb_nv << " E[IFE]=" << nb_nfe;
635 //-----------------------------------------------------------------------------
636 template <typename TRealPoint, typename TRealVector>
638 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
641 return myPositions.size() == myIncidentFaces.size()
642 && ( myVertexNormals.size() == 0
643 || ( myVertexNormals.size() == myPositions.size() ) )
644 && ( myFaceNormals.size() == 0
645 || ( myFaceNormals.size() == myIncidentVertices.size() ) );
649 //-----------------------------------------------------------------------------
650 template <typename TRealPoint, typename TRealVector>
652 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
655 myNeighborFaces .resize( nbFaces() );
656 myNeighborVertices.resize( nbVertices() );
657 std::vector< std::set< Index > > tmp( nbVertices() );
658 // For each vertex, computes its neighboring vertices
659 for ( auto incident_vertices : allIncidentVertices() )
661 const Size nb_iv = incident_vertices.size();
662 for ( Size k = 0; k < nb_iv; ++k )
664 tmp[ incident_vertices[ k ] ].insert( incident_vertices[ (k+1)%nb_iv ] );
665 tmp[ incident_vertices[ (k+1)%nb_iv ] ].insert( incident_vertices[ k ] );
668 // For each vertex, computes its neighboring vertices
669 for ( Index idx_v = 0; idx_v < nbVertices(); ++idx_v )
670 myNeighborVertices[ idx_v ] = Vertices( tmp[ idx_v ].cbegin(), tmp[ idx_v ].cend() );
672 // For each face, computes its neighboring faces
674 for ( auto incident_vertices : allIncidentVertices() )
676 std::set< Index > neighbor_faces_set;
677 std::sort( incident_vertices.begin(), incident_vertices.end() );
678 for ( auto idx_v : incident_vertices )
680 const auto & incident_faces = incidentFaces( idx_v );
681 for ( auto inc_f : incident_faces )
683 // Keep only faces incident to two vertices of f.
684 auto incident_vertices2 = incidentVertices( inc_f );
685 std::sort( incident_vertices2.begin(), incident_vertices2.end() );
687 std::set_intersection( incident_vertices.cbegin(), incident_vertices.cend(),
688 incident_vertices2.cbegin(), incident_vertices2.cend(),
689 std::back_inserter( common ) );
690 if ( common.size() == 2 )
691 neighbor_faces_set.insert( inc_f );
694 neighbor_faces_set.erase( idx_f );
695 Faces neighbor_faces( neighbor_faces_set.begin(), neighbor_faces_set.end() );
696 myNeighborFaces[ idx_f++ ] = neighbor_faces;
700 //-----------------------------------------------------------------------------
701 template <typename TRealPoint, typename TRealVector>
703 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
706 std::map< VertexPair, std::vector<Face> > edge2face_right;
707 std::map< VertexPair, std::vector<Face> > edge2face_left;
708 std::set< VertexPair > edges;
710 for ( auto incident_vertices : allIncidentVertices() )
712 const Size n = incident_vertices.size();
713 for ( Size i = 0; i < n; i++ )
715 VertexPair e = std::make_pair( incident_vertices[ i ],
716 incident_vertices[ (i+1) % n ] );
717 if ( e.first < e.second ) {
718 edge2face_left[ e ].push_back( idx_f );
720 std::swap( e.first, e.second );
721 edge2face_right[ e ].push_back( idx_f );
727 const Size nbe = edges.size();
728 myEdgeVertices.resize ( nbe );
729 myEdgeFaces.resize ( nbe );
730 myEdgeRightFaces.resize( nbe );
731 myEdgeLeftFaces.resize ( nbe );
733 for ( auto e : edges )
735 myEdgeVertices [ idx_e ] = e;
736 myEdgeLeftFaces [ idx_e ] = edge2face_left [ e ];
737 myEdgeRightFaces[ idx_e ] = edge2face_right[ e ];
738 myEdgeFaces [ idx_e ] = myEdgeRightFaces[ idx_e ];
739 myEdgeFaces [ idx_e ].insert( myEdgeFaces[ idx_e ].end(),
740 myEdgeLeftFaces[ idx_e ].cbegin(),
741 myEdgeLeftFaces[ idx_e ].cend() );
746 //-----------------------------------------------------------------------------
747 template <typename TRealPoint, typename TRealVector>
748 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Edges
749 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
750 computeManifoldBoundaryEdges() const
753 for ( Index e = 0; e < myEdgeFaces.size(); ++e )
755 if ( myEdgeFaces[ e ].size() == 1 )
756 edges.push_back( e );
761 //-----------------------------------------------------------------------------
762 template <typename TRealPoint, typename TRealVector>
763 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Edges
764 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
765 computeManifoldInnerEdges() const
768 for ( Index e = 0; e < myEdgeFaces.size(); ++e )
770 if ( myEdgeFaces[ e ].size() == 2 )
771 edges.push_back( e );
776 //-----------------------------------------------------------------------------
777 template <typename TRealPoint, typename TRealVector>
778 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Edges
779 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
780 computeManifoldInnerConsistentEdges() const
783 for ( Index e = 0; e < myEdgeFaces.size(); ++e )
785 if ( ( myEdgeRightFaces[ e ].size() == 1 )
786 && ( myEdgeLeftFaces[ e ].size() == 1 ) )
787 edges.push_back( e );
792 //-----------------------------------------------------------------------------
793 template <typename TRealPoint, typename TRealVector>
794 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Edges
795 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
796 computeManifoldInnerUnconsistentEdges() const
799 for ( Index e = 0; e < myEdgeFaces.size(); ++e )
801 if ( ( myEdgeRightFaces[ e ].size() == 2 )
802 || ( myEdgeLeftFaces[ e ].size() == 2 ) )
803 edges.push_back( e );
808 //-----------------------------------------------------------------------------
809 template <typename TRealPoint, typename TRealVector>
810 typename DGtal::SurfaceMesh<TRealPoint, TRealVector>::Edges
811 DGtal::SurfaceMesh<TRealPoint, TRealVector>::
812 computeNonManifoldEdges() const
815 for ( Index e = 0; e < myEdgeFaces.size(); ++e )
817 if ( myEdgeFaces[ e ].size() >= 3 )
818 edges.push_back( e );
823 ///////////////////////////////////////////////////////////////////////////////
824 // Implementation of inline functions //
826 //-----------------------------------------------------------------------------
827 template <typename TRealPoint, typename TRealVector>
829 DGtal::operator<< ( std::ostream & out,
830 const SurfaceMesh<TRealPoint, TRealVector> & object )
832 object.selfDisplay( out );
837 ///////////////////////////////////////////////////////////////////////////////
838 ///////////////////////////////////////////////////////////////////////////////