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 DigitalSurface.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 DigitalSurface.h
26 * This file is part of the DGtal library.
30 //////////////////////////////////////////////////////////////////////////////
33 #include "DGtal/graph/CVertexPredicate.h"
34 //////////////////////////////////////////////////////////////////////////////
36 ///////////////////////////////////////////////////////////////////////////////
37 // IMPLEMENTATION of inline methods.
38 ///////////////////////////////////////////////////////////////////////////////
40 ///////////////////////////////////////////////////////////////////////////////
41 // ----------------------- Standard services ------------------------------
43 //-----------------------------------------------------------------------------
44 template <typename TDigitalSurfaceContainer>
46 DGtal::DigitalSurface<TDigitalSurfaceContainer>::~DigitalSurface()
48 if ( myTracker != 0 ) delete myTracker;
50 //-----------------------------------------------------------------------------
51 template <typename TDigitalSurfaceContainer>
53 DGtal::DigitalSurface<TDigitalSurfaceContainer>::DigitalSurface
54 ( const DigitalSurface & other )
55 : myContainer( other.myContainer ),
56 myTracker( new DigitalSurfaceTracker( *other.myTracker ) ),
57 myUmbrellaComputer( other.myUmbrellaComputer )
60 //-----------------------------------------------------------------------------
61 template <typename TDigitalSurfaceContainer>
63 DGtal::DigitalSurface<TDigitalSurfaceContainer>::DigitalSurface
64 ( const TDigitalSurfaceContainer & aContainer )
65 : myContainer( new DigitalSurfaceContainer( aContainer ) )
67 if ( ! myContainer->empty() )
69 Surfel s = *( myContainer->begin() );
70 myTracker = myContainer->newTracker( s );
71 myUmbrellaComputer.init( *myTracker, 0, false, 1 );
76 //-----------------------------------------------------------------------------
77 template <typename TDigitalSurfaceContainer>
79 DGtal::DigitalSurface<TDigitalSurfaceContainer>::DigitalSurface
80 ( TDigitalSurfaceContainer* containerPtr )
81 : myContainer( containerPtr )
83 if ( ! myContainer->empty() )
85 Surfel s = *( myContainer->begin() );
86 myTracker = myContainer->newTracker( s );
87 myUmbrellaComputer.init( *myTracker, 0, false, 1 );
92 //-----------------------------------------------------------------------------
93 template <typename TDigitalSurfaceContainer>
95 DGtal::DigitalSurface<TDigitalSurfaceContainer> &
96 DGtal::DigitalSurface<TDigitalSurfaceContainer>::operator=
97 ( const DigitalSurface & other )
101 myContainer = other.myContainer;
102 if ( myTracker != 0 ) delete myTracker;
103 myTracker = new DigitalSurfaceTracker( *other.myTracker );
104 myUmbrellaComputer = other.myUmbrellaComputer;
108 //-----------------------------------------------------------------------------
109 template <typename TDigitalSurfaceContainer>
111 const TDigitalSurfaceContainer &
112 DGtal::DigitalSurface<TDigitalSurfaceContainer>::container() const
116 //-----------------------------------------------------------------------------
117 template <typename TDigitalSurfaceContainer>
119 TDigitalSurfaceContainer &
120 DGtal::DigitalSurface<TDigitalSurfaceContainer>::container()
124 //-----------------------------------------------------------------------------
125 template <typename TDigitalSurfaceContainer>
127 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::ConstIterator
128 DGtal::DigitalSurface<TDigitalSurfaceContainer>::begin() const
130 return myContainer->begin();
132 //-----------------------------------------------------------------------------
133 template <typename TDigitalSurfaceContainer>
135 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::ConstIterator
136 DGtal::DigitalSurface<TDigitalSurfaceContainer>::end() const
138 return myContainer->end();
140 //-----------------------------------------------------------------------------
141 template <typename TDigitalSurfaceContainer>
143 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::Size
144 DGtal::DigitalSurface<TDigitalSurfaceContainer>::size() const
146 return myContainer->nbSurfels();
148 //-----------------------------------------------------------------------------
149 template <typename TDigitalSurfaceContainer>
151 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::Size
152 DGtal::DigitalSurface<TDigitalSurfaceContainer>::bestCapacity() const
154 return KSpace::dimension*2 - 2;
156 //-----------------------------------------------------------------------------
157 template <typename TDigitalSurfaceContainer>
159 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::Size
160 DGtal::DigitalSurface<TDigitalSurfaceContainer>::degree
161 ( const Vertex & v ) const
165 myTracker->move( v );
166 for ( typename KSpace::DirIterator q = container().space().sDirs( v );
169 if ( myTracker->adjacent( s, *q, true ) )
171 if ( myTracker->adjacent( s, *q, false ) )
176 //-----------------------------------------------------------------------------
177 template <typename TDigitalSurfaceContainer>
178 template <typename OutputIterator>
181 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
182 writeNeighbors( OutputIterator & it,
183 const Vertex & v ) const
186 myTracker->move( v );
187 for ( typename KSpace::DirIterator q = container().space().sDirs( v );
190 if ( myTracker->adjacent( s, *q, true ) )
192 if ( myTracker->adjacent( s, *q, false ) )
196 //-----------------------------------------------------------------------------
197 template <typename TDigitalSurfaceContainer>
198 template <typename OutputIterator, typename VertexPredicate>
201 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
202 writeNeighbors( OutputIterator & it,
204 const VertexPredicate & pred ) const
206 BOOST_CONCEPT_ASSERT(( concepts::CVertexPredicate< VertexPredicate > ));
208 myTracker->move( v );
209 for ( typename KSpace::DirIterator q = container().space().sDirs( v );
212 if ( myTracker->adjacent( s, *q, true ) )
214 if ( pred( s ) ) *it++ = s;
216 if ( myTracker->adjacent( s, *q, false ) )
218 if ( pred( s ) ) *it++ = s;
223 //-----------------------------------------------------------------------------
224 template <typename TDigitalSurfaceContainer>
226 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::ArcRange
227 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
228 outArcs( const Vertex & v ) const
232 myTracker->move( v );
233 for ( typename KSpace::DirIterator q = container().space().sDirs( v );
237 if ( myTracker->adjacent( s, i, true ) )
238 arcs.push_back( Arc( v, i, true ) );
239 if ( myTracker->adjacent( s, i, false ) )
240 arcs.push_back( Arc( v, i, false ) );
244 //-----------------------------------------------------------------------------
245 template <typename TDigitalSurfaceContainer>
247 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::ArcRange
248 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
249 inArcs( const Vertex & v ) const
253 myTracker->move( v );
254 for ( typename KSpace::DirIterator q = container().space().sDirs( v );
258 if ( myTracker->adjacent( s, i, true ) )
259 arcs.push_back( opposite( Arc( v, i, true ) ) );
260 if ( myTracker->adjacent( s, i, false ) )
261 arcs.push_back( opposite( Arc( v, i, false ) ) );
266 //-----------------------------------------------------------------------------
267 template <typename TDigitalSurfaceContainer>
269 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::FaceRange
270 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
271 facesAroundVertex( const Vertex & v, bool order_ccw_in_3d ) const
273 typedef typename ArcRange::const_iterator ArcRangeConstIterator;
274 // std::cerr << " - facesAroundVertex(" << v << ")" << std::endl;
275 ArcRange arcs = outArcs( v );
276 if ( order_ccw_in_3d && ( arcs.size() == 4 ) )
277 { // 3D method to order faces/pointels CCW around vertices/surfels
279 faces.push_back( facesAroundArc( arcs[ 0 ] )[ 0 ] );
280 faces.push_back( facesAroundArc( arcs[ 2 ] )[ 0 ] );
281 faces.push_back( facesAroundArc( arcs[ 1 ] )[ 0 ] ); // < to change order.
282 faces.push_back( facesAroundArc( arcs[ 3 ] )[ 0 ] ); // < to change order.
283 const KSpace& K = container().space();
284 auto orth_dir = K.sOrthDir( v );
285 auto direct = K.sDirect( v, orth_dir ); // true: ccw, false: ! ccw
286 Point vtcs[] = { K.sCoords( pivot( faces[ 0 ] ) ),
287 K.sCoords( pivot( faces[ 1 ] ) ),
288 K.sCoords( pivot( faces[ 2 ] ) ) };
289 Vector s0s1 = vtcs[ 1 ] - vtcs[ 0 ];
290 Vector s0s2 = vtcs[ 2 ] - vtcs[ 0 ];
291 Vector t = s0s1.crossProduct( s0s2 );
292 if ( ( ( t[ orth_dir ] > 0 ) && direct )
293 || ( ( t[ orth_dir ] < 0 ) && ! direct ) )
294 std::reverse( faces.begin(), faces.end() );
300 std::back_insert_iterator<FaceRange> output_it = std::back_inserter( faces );
301 for ( ArcRangeConstIterator it = arcs.begin(), it_end = arcs.end();
304 FaceRange faces_of_arc = facesAroundArc( *it );
306 std::copy( faces_of_arc.begin(), faces_of_arc.end(), output_it );
311 //-----------------------------------------------------------------------------
312 template <typename TDigitalSurfaceContainer>
314 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::Vertex
315 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
316 head( const Arc & a ) const
319 myTracker->move( a.base );
320 uint8_t code = myTracker->adjacent( s, a.k, a.epsilon );
321 ASSERT( code != 0 ); boost::ignore_unused_variable_warning(code);
324 //-----------------------------------------------------------------------------
325 template <typename TDigitalSurfaceContainer>
327 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::Vertex
328 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
329 tail( const Arc & a ) const
333 //-----------------------------------------------------------------------------
334 template <typename TDigitalSurfaceContainer>
336 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::Arc
337 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
338 opposite( const Arc & a ) const
341 myTracker->move( a.base );
342 uint8_t code = myTracker->adjacent( s, a.k, a.epsilon );
344 if ( code == 2 ) return Arc( s, a.k, ! a.epsilon );
347 bool orientation = container().space().sDirect( a.base, a.k );
348 unsigned int i = myTracker->orthDir();
350 ( orientation == a.epsilon )
351 != container().space().sDirect( s, i ) );
354 //-----------------------------------------------------------------------------
355 template <typename TDigitalSurfaceContainer>
357 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::Arc
358 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
359 arc( const Vertex & t, const Vertex & h ) const
361 const KSpace & K = container().space();
362 Point p1 = K.sKCoords( t );
363 Point p2 = K.sKCoords( h );
365 for ( typename KSpace::DirIterator q = K.sDirs( t );
369 if ( p2[ i ] != 0 ) return Arc( t, i, p2[ i ] > 0 );
371 ASSERT( false && "DGtal::DigitalSurface<TDigitalSurfaceContainer>::arc( tail, head ): tail and head are not adjacent." );
372 return Arc( t, 0, true );
373 // // JOL 2017/07/4: bad test.
374 // for ( typename KSpace::DirIterator q = K.sDirs( h );
378 // if ( p1[ i ] != 0 ) return Arc( t, i, p1[ i ] > 0 );
380 // ASSERT( false && "DGtal::DigitalSurface<TDigitalSurfaceContainer>::arc( tail, head ): tail and head are not adjacent." );
381 // return Arc( t, 0, true );
383 //-----------------------------------------------------------------------------
384 template <typename TDigitalSurfaceContainer>
386 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::FaceRange
387 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
388 facesAroundArc( const Arc & a ) const
391 UmbrellaState state( a.base, a.k, a.epsilon, 0 );
392 myUmbrellaComputer.setState( state );
393 SCell sep = myUmbrellaComputer.separator();
394 // Faces are to be found along direction spanned by the separator.
395 for ( typename KSpace::DirIterator q = container().space().sDirs( sep );
399 faces.push_back( computeFace( state ) );
404 //-----------------------------------------------------------------------------
405 template <typename TDigitalSurfaceContainer>
407 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::VertexRange
408 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
409 verticesAroundFace( const Face & f ) const
411 VertexRange vertices;
412 myUmbrellaComputer.setState( f.state );
413 for ( unsigned int i = 0; i < f.nbVertices; ++i )
415 vertices.push_back( myUmbrellaComputer.surfel() );
416 myUmbrellaComputer.previous();
420 //-----------------------------------------------------------------------------
421 template <typename TDigitalSurfaceContainer>
423 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::FaceSet
424 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
428 for ( ConstIterator it = begin(), it_end = end(); it != it_end; ++it )
430 FaceRange local_faces = facesAroundVertex( *it );
431 all_faces.insert( local_faces.begin(), local_faces.end() );
435 //-----------------------------------------------------------------------------
436 template <typename TDigitalSurfaceContainer>
438 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::FaceSet
439 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
440 allClosedFaces() const
443 for ( ConstIterator it = begin(), it_end = end(); it != it_end; ++it )
445 FaceRange local_faces = facesAroundVertex( *it );
446 for ( typename FaceRange::const_iterator lit = local_faces.begin(),
447 lit_end = local_faces.end(); lit != lit_end; ++lit )
448 if ( lit->isClosed() )
449 all_faces.insert( *lit );
453 //-----------------------------------------------------------------------------
454 template <typename TDigitalSurfaceContainer>
456 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::FaceSet
457 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
461 for ( ConstIterator it = begin(), it_end = end(); it != it_end; ++it )
463 FaceRange local_faces = facesAroundVertex( *it );
464 for ( typename FaceRange::const_iterator lit = local_faces.begin(),
465 lit_end = local_faces.end(); lit != lit_end; ++lit )
466 if ( ! lit->isClosed() )
467 all_faces.insert( *lit );
472 //-----------------------------------------------------------------------------
473 template <typename TDigitalSurfaceContainer>
475 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::Face
476 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
477 computeFace( UmbrellaState state ) const
479 myUmbrellaComputer.setState( state );
480 Surfel start = state.surfel;
485 // std::cerr << " + s/surf "
486 // << myUmbrellaComputer.state().surfel<< std::endl;
488 code = myUmbrellaComputer.previous();
489 if ( code == 0 ) break; // face is open
490 if ( myUmbrellaComputer.state() < state )
491 state = myUmbrellaComputer.state();
493 while ( myUmbrellaComputer.surfel() != start );
494 if ( code == 0 ) // open face
495 { // Going back to count the number of incident vertices.
499 // std::cerr << " + c/surf "
500 // << myUmbrellaComputer.state().surfel<< std::endl;
502 code = myUmbrellaComputer.next();
505 return Face( myUmbrellaComputer.state(), nb, false );
508 return Face( state, nb, true );
510 //-----------------------------------------------------------------------------
511 template <typename TDigitalSurfaceContainer>
513 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::SCell
514 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
515 separator( const Arc & a ) const
517 return container().space().sIncident( a.base, a.k, a.epsilon );
519 //-----------------------------------------------------------------------------
520 // template <typename TDigitalSurfaceContainer>
522 // typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::SCell
523 // DGtal::DigitalSurface<TDigitalSurfaceContainer>::
524 // separator( const Face & f ) const
526 // return container().space().sIncident( f.state.surfel, f.state.k,
527 // f.state.epsilon );
529 //-----------------------------------------------------------------------------
530 template <typename TDigitalSurfaceContainer>
532 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::SCell
533 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
534 pivot( const Face & f ) const
536 SCell sep = container().space().sIncident( f.state.surfel, f.state.k,
538 return container().space().sDirectIncident( sep, f.state.j );
543 ///////////////////////////////////////////////////////////////////////////////
544 // Interface - public :
547 * Writes/Displays the object on an output stream.
548 * @param out the output stream where the object is written.
550 template <typename TDigitalSurfaceContainer>
553 DGtal::DigitalSurface<TDigitalSurfaceContainer>::selfDisplay ( std::ostream & out ) const
555 out << "[DigitalSurface]";
559 * Checks the validity/consistency of the object.
560 * @return 'true' if the object is valid, 'false' otherwise.
562 template <typename TDigitalSurfaceContainer>
565 DGtal::DigitalSurface<TDigitalSurfaceContainer>::isValid() const
567 return myTracker != 0;
570 //-----------------------------------------------------------------------------
572 Writes/Displays the object on an output stream.
573 @param out the output stream where the object is written.
575 template <typename TDigitalSurfaceContainer>
577 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
578 exportSurfaceAs3DOFF ( std::ostream & out ) const
580 typedef DGtal::uint64_t Number;
581 // Numbers all vertices.
582 std::map<Vertex, Number> index;
584 for ( ConstIterator it = begin(), it_end = end();
586 index[ *it ] = nbv++;
588 // std::cerr << "- " << nbv << " vertices." << std::endl;
589 FaceSet faces = allClosedFaces();
590 // Compute the number of edges and faces.
593 for ( typename FaceSet::const_iterator
594 itf = faces.begin(), itf_end = faces.end();
595 itf != itf_end; ++itf )
597 if ( itf->isClosed() )
598 { nbe += itf->nbVertices; ++nbf; }
600 { nbe += itf->nbVertices - 1; }
602 // std::cerr << "- " << nbf << " faces." << std::endl;
603 // Outputs OFF header.
604 out << "OFF" << std::endl
605 << "# Generated by DGtal::DigitalSurface." << std::endl
606 << nbv << " " << nbf << " " << ( nbe / 2 ) << std::endl;
607 // Outputs vertex coordinates (the 3 first ones).
608 const KSpace & K = container().space();
609 for ( ConstIterator it = begin(), it_end = end();
612 Point p = K.sKCoords( *it );
613 out << p[ 0 ] << " " << p[ 1 ] << " " << p[ 2 ] << std::endl;
614 // double areaD = NumberTraits<Coordinate>::castToDouble(area)*2.0;
616 // Outputs closed faces.
617 for ( typename FaceSet::const_iterator
618 itf = faces.begin(), itf_end = faces.end();
619 itf != itf_end; ++itf )
621 if ( itf->isClosed() )
623 out << itf->nbVertices;
624 VertexRange vtcs = verticesAroundFace( *itf );
625 for ( typename VertexRange::const_iterator
626 itv = vtcs.begin(), itv_end = vtcs.end();
627 itv != itv_end; ++itv )
628 out << " " << index[ *itv ];
634 //-----------------------------------------------------------------------------
635 template <typename TDigitalSurfaceContainer>
636 template <typename CellEmbedder>
638 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
639 exportEmbeddedSurfaceAs3DOFF
640 ( std::ostream & out,
641 const CellEmbedder & cembedder ) const
643 BOOST_CONCEPT_ASSERT(( concepts::CCellEmbedder< CellEmbedder > ));
645 typedef DGtal::uint64_t Number;
646 // Numbers all vertices.
647 std::map<Vertex, Number> index;
649 for ( ConstIterator it = begin(), it_end = end();
651 index[ *it ] = nbv++;
653 // std::cerr << "- " << nbv << " vertices." << std::endl;
654 FaceSet faces = allClosedFaces();
655 // Compute the number of edges and faces.
658 for ( typename FaceSet::const_iterator
659 itf = faces.begin(), itf_end = faces.end();
660 itf != itf_end; ++itf )
662 if ( itf->isClosed() )
663 { nbe += itf->nbVertices; ++nbf; }
665 { nbe += itf->nbVertices - 1; }
667 // std::cerr << "- " << nbf << " faces." << std::endl;
668 // Outputs OFF header.
669 out << "OFF" << std::endl
670 << "# Generated by DGtal::DigitalSurface." << std::endl
671 << nbv << " " << nbf << " " << ( nbe / 2 ) << std::endl;
672 // Outputs vertex coordinates (the 3 first ones).
673 typedef typename CellEmbedder::RealPoint RealPoint;
674 const KSpace & K = container().space();
675 for ( ConstIterator it = begin(), it_end = end();
678 RealPoint p( cembedder( K.unsigns( *it ) ) );
679 out << p[ 0 ] << " " << p[ 1 ] << " " << p[ 2 ] << std::endl;
680 // double areaD = NumberTraits<Coordinate>::castToDouble(area)*2.0;
682 // Outputs closed faces.
683 for ( typename FaceSet::const_iterator
684 itf = faces.begin(), itf_end = faces.end();
685 itf != itf_end; ++itf )
687 if ( itf->isClosed() )
689 out << itf->nbVertices;
690 VertexRange vtcs = verticesAroundFace( *itf );
691 for ( typename VertexRange::const_iterator
692 itv = vtcs.begin(), itv_end = vtcs.end();
693 itv != itv_end; ++itv )
694 out << " " << index[ *itv ];
700 //-----------------------------------------------------------------------------
701 template <typename TDigitalSurfaceContainer>
702 template <typename CellEmbedder>
704 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
705 exportEmbeddedSurfaceAs3DNOFF
706 ( std::ostream & out,
707 const CellEmbedder & cembedder ) const
709 BOOST_CONCEPT_ASSERT(( concepts::CCellEmbedder< CellEmbedder > ));
710 BOOST_CONCEPT_ASSERT(( concepts::CWithGradientMap< CellEmbedder > ));
712 typedef typename CellEmbedder::GradientMap GradientMap;
713 typedef typename CellEmbedder::Cell MyCell;
714 typedef typename CellEmbedder::RealPoint RealPoint;
715 typedef typename CellEmbedder::RealVector RealVector;
716 typedef DGtal::uint64_t Number;
718 // Gets the gradient map.
719 GradientMap gradMap = cembedder.gradientMap();
720 // Numbers all vertices.
721 std::map<Vertex, Number> index;
723 for ( ConstIterator it = begin(), it_end = end();
725 index[ *it ] = nbv++;
727 // std::cerr << "- " << nbv << " vertices." << std::endl;
728 FaceSet faces = allClosedFaces();
729 // Compute the number of edges and faces.
732 for ( typename FaceSet::const_iterator
733 itf = faces.begin(), itf_end = faces.end();
734 itf != itf_end; ++itf )
736 if ( itf->isClosed() )
737 { nbe += itf->nbVertices; ++nbf; }
739 { nbe += itf->nbVertices - 1; }
741 // std::cerr << "- " << nbf << " faces." << std::endl;
742 // Outputs OFF header.
743 out << "NOFF" << std::endl
744 << "# Generated by DGtal::DigitalSurface." << std::endl
745 << nbv << " " << nbf << " " << ( nbe / 2 ) << std::endl;
746 // Outputs vertex coordinates (the 3 first ones).
747 const KSpace & K = container().space();
750 for ( ConstIterator it = begin(), it_end = end();
753 MyCell c = K.unsigns( *it );
756 //cembedder.embedSCell( *it, p, v );
757 double norm = v.norm();
758 if ( norm != 0.0 ) v /= norm;
759 out << p[ 0 ] << " " << p[ 1 ] << " " << p[ 2 ] << " "
760 << v[ 0 ] << " " << v[ 1 ] << " " << v[ 2 ] << std::endl;
761 // double areaD = NumberTraits<Coordinate>::castToDouble(area)*2.0;
763 // Outputs closed faces.
764 for ( typename FaceSet::const_iterator
765 itf = faces.begin(), itf_end = faces.end();
766 itf != itf_end; ++itf )
768 if ( itf->isClosed() )
770 out << itf->nbVertices;
771 VertexRange vtcs = verticesAroundFace( *itf );
772 for ( typename VertexRange::const_iterator
773 itv = vtcs.begin(), itv_end = vtcs.end();
774 itv != itv_end; ++itv )
775 out << " " << index[ *itv ];
781 //-----------------------------------------------------------------------------
782 template <typename TDigitalSurfaceContainer>
783 template <typename SCellEmbedderWithGradientMap>
785 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
787 ( std::ostream & out,
788 const SCellEmbedderWithGradientMap & scembedder ) const
790 BOOST_CONCEPT_ASSERT(( concepts::CSCellEmbedder< SCellEmbedderWithGradientMap > ));
791 BOOST_CONCEPT_ASSERT(( concepts::CWithGradientMap< SCellEmbedderWithGradientMap > ));
793 typedef typename SCellEmbedderWithGradientMap::GradientMap GradientMap;
794 typedef typename SCellEmbedderWithGradientMap::SCell MySCell;
795 typedef typename SCellEmbedderWithGradientMap::RealPoint RealPoint;
796 typedef typename SCellEmbedderWithGradientMap::RealVector RealVector;
797 typedef DGtal::uint64_t Number;
799 // Gets the gradient map.
800 GradientMap gradMap = scembedder.gradientMap();
801 // Numbers all vertices.
802 std::map<Vertex, Number> index;
804 for ( ConstIterator it = begin(), it_end = end();
806 index[ *it ] = nbv++;
808 // std::cerr << "- " << nbv << " vertices." << std::endl;
809 FaceSet faces = allClosedFaces();
810 // Compute the number of edges and faces.
813 for ( typename FaceSet::const_iterator
814 itf = faces.begin(), itf_end = faces.end();
815 itf != itf_end; ++itf )
817 if ( itf->isClosed() )
818 { nbe += itf->nbVertices; ++nbf; }
820 { nbe += itf->nbVertices - 1; }
822 // std::cerr << "- " << nbf << " faces." << std::endl;
823 // Outputs OFF header.
824 out << "NOFF" << std::endl
825 << "# Generated by DGtal::DigitalSurface." << std::endl
826 << nbv << " " << nbf << " " << ( nbe / 2 ) << std::endl;
827 // Outputs vertex coordinates (the 3 first ones).
830 for ( ConstIterator it = begin(), it_end = end();
836 //cembedder.embedSCell( *it, p, v );
837 double norm = v.norm();
838 if ( norm != 0.0 ) v /= norm;
839 out << p[ 0 ] << " " << p[ 1 ] << " " << p[ 2 ] << " "
840 << v[ 0 ] << " " << v[ 1 ] << " " << v[ 2 ] << std::endl;
841 // double areaD = NumberTraits<Coordinate>::castToDouble(area)*2.0;
843 // Outputs closed faces.
844 for ( typename FaceSet::const_iterator
845 itf = faces.begin(), itf_end = faces.end();
846 itf != itf_end; ++itf )
848 if ( itf->isClosed() )
850 out << itf->nbVertices;
851 VertexRange vtcs = verticesAroundFace( *itf );
852 for ( typename VertexRange::const_iterator
853 itv = vtcs.begin(), itv_end = vtcs.end();
854 itv != itv_end; ++itv )
855 out << " " << index[ *itv ];
861 //-----------------------------------------------------------------------------
862 template <typename TDigitalSurfaceContainer>
863 template <typename CellEmbedder>
865 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
866 exportEmbeddedIteratedSurfaceAs3DNOFF
867 ( std::ostream & out,
868 const CellEmbedder & cembedder ) const
870 typedef DGtal::uint64_t Number;
871 // Numbers all vertices.
872 std::map<Vertex, Number> index;
874 for ( ConstIterator it = begin(), it_end = end();
876 index[ *it ] = nbv++;
878 // std::cerr << "- " << nbv << " vertices." << std::endl;
879 FaceSet faces = allClosedFaces();
880 // Compute the number of edges and faces.
883 for ( typename FaceSet::const_iterator
884 itf = faces.begin(), itf_end = faces.end();
885 itf != itf_end; ++itf )
887 if ( itf->isClosed() )
888 { nbe += itf->nbVertices; ++nbf; }
890 { nbe += itf->nbVertices - 1; }
892 // std::cerr << "- " << nbf << " faces." << std::endl;
893 // Outputs OFF header.
894 out << "NOFF" << std::endl
895 << "# Generated by DGtal::DigitalSurface." << std::endl
896 << nbv << " " << nbf << " " << ( nbe / 2 ) << std::endl;
897 // Outputs vertex coordinates (the 3 first ones).
898 typedef typename CellEmbedder::RealPoint RealPoint;
899 typedef typename CellEmbedder::RealVector RealVector;
900 const KSpace & K = container().space();
903 for ( ConstIterator it = begin(), it_end = end();
906 cembedder.embedSurfel( it, p, v );
907 double norm = v.norm();
908 if ( norm != 0.0 ) v /= norm;
909 out << p[ 0 ] << " " << p[ 1 ] << " " << p[ 2 ] << " "
910 << v[ 0 ] << " " << v[ 1 ] << " " << v[ 2 ] << std::endl;
911 // double areaD = NumberTraits<Coordinate>::castToDouble(area)*2.0;
913 // Outputs closed faces.
914 for ( typename FaceSet::const_iterator
915 itf = faces.begin(), itf_end = faces.end();
916 itf != itf_end; ++itf )
918 if ( itf->isClosed() )
920 out << itf->nbVertices;
921 VertexRange vtcs = verticesAroundFace( *itf );
922 for ( typename VertexRange::const_iterator
923 itv = vtcs.begin(), itv_end = vtcs.end();
924 itv != itv_end; ++itv )
925 out << " " << index[ *itv ];
934 ///////////////////////////////////////////////////////////////////////////////
935 // Implementation of inline functions //
937 template <typename TDigitalSurfaceContainer>
940 DGtal::operator<< ( std::ostream & out,
941 const DigitalSurface<TDigitalSurfaceContainer> & object )
943 object.selfDisplay( out );
948 ///////////////////////////////////////////////////////////////////////////////