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 ) const
273 typedef typename ArcRange::const_iterator ArcRangeConstIterator;
274 // std::cerr << " - facesAroundVertex(" << v << ")" << std::endl;
275 ArcRange arcs = outArcs( v );
277 std::back_insert_iterator<FaceRange> output_it = std::back_inserter( faces );
278 for ( ArcRangeConstIterator it = arcs.begin(), it_end = arcs.end();
281 // std::cerr << " + arc " << tail( *it )
282 // << " -> " << head( *it ) << std::endl;
283 FaceRange faces_of_arc = facesAroundArc( *it );
285 std::copy( faces_of_arc.begin(), faces_of_arc.end(), output_it );
289 //-----------------------------------------------------------------------------
290 template <typename TDigitalSurfaceContainer>
292 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::Vertex
293 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
294 head( const Arc & a ) const
297 myTracker->move( a.base );
298 uint8_t code = myTracker->adjacent( s, a.k, a.epsilon );
299 ASSERT( code != 0 ); boost::ignore_unused_variable_warning(code);
302 //-----------------------------------------------------------------------------
303 template <typename TDigitalSurfaceContainer>
305 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::Vertex
306 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
307 tail( const Arc & a ) const
311 //-----------------------------------------------------------------------------
312 template <typename TDigitalSurfaceContainer>
314 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::Arc
315 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
316 opposite( const Arc & a ) const
319 myTracker->move( a.base );
320 uint8_t code = myTracker->adjacent( s, a.k, a.epsilon );
322 if ( code == 2 ) return Arc( s, a.k, ! a.epsilon );
325 bool orientation = container().space().sDirect( a.base, a.k );
326 unsigned int i = myTracker->orthDir();
328 ( orientation == a.epsilon )
329 != container().space().sDirect( s, i ) );
332 //-----------------------------------------------------------------------------
333 template <typename TDigitalSurfaceContainer>
335 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::Arc
336 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
337 arc( const Vertex & t, const Vertex & h ) const
339 const KSpace & K = container().space();
340 Point p1 = K.sKCoords( t );
341 Point p2 = K.sKCoords( h );
343 for ( typename KSpace::DirIterator q = K.sDirs( h );
347 if ( p1[ i ] != 0 ) return Arc( t, i, p1[ i ] > 0 );
349 ASSERT( false && "DGtal::DigitalSurface<TDigitalSurfaceContainer>::arc( tail, head ): tail and head are not adjacent." );
350 return Arc( t, 0, true );
352 //-----------------------------------------------------------------------------
353 template <typename TDigitalSurfaceContainer>
355 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::FaceRange
356 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
357 facesAroundArc( const Arc & a ) const
360 UmbrellaState state( a.base, a.k, a.epsilon, 0 );
361 myUmbrellaComputer.setState( state );
362 SCell sep = myUmbrellaComputer.separator();
363 // Faces are to be found along direction spanned by the separator.
364 for ( typename KSpace::DirIterator q = container().space().sDirs( sep );
368 faces.push_back( computeFace( state ) );
373 //-----------------------------------------------------------------------------
374 template <typename TDigitalSurfaceContainer>
376 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::VertexRange
377 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
378 verticesAroundFace( const Face & f ) const
380 VertexRange vertices;
381 myUmbrellaComputer.setState( f.state );
382 for ( unsigned int i = 0; i < f.nbVertices; ++i )
384 vertices.push_back( myUmbrellaComputer.surfel() );
385 myUmbrellaComputer.previous();
389 //-----------------------------------------------------------------------------
390 template <typename TDigitalSurfaceContainer>
392 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::FaceSet
393 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
397 for ( ConstIterator it = begin(), it_end = end(); it != it_end; ++it )
399 FaceRange local_faces = facesAroundVertex( *it );
400 all_faces.insert( local_faces.begin(), local_faces.end() );
404 //-----------------------------------------------------------------------------
405 template <typename TDigitalSurfaceContainer>
407 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::FaceSet
408 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
409 allClosedFaces() const
412 for ( ConstIterator it = begin(), it_end = end(); it != it_end; ++it )
414 FaceRange local_faces = facesAroundVertex( *it );
415 for ( typename FaceRange::const_iterator lit = local_faces.begin(),
416 lit_end = local_faces.end(); lit != lit_end; ++lit )
417 if ( lit->isClosed() )
418 all_faces.insert( *lit );
422 //-----------------------------------------------------------------------------
423 template <typename TDigitalSurfaceContainer>
425 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::FaceSet
426 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
430 for ( ConstIterator it = begin(), it_end = end(); it != it_end; ++it )
432 FaceRange local_faces = facesAroundVertex( *it );
433 for ( typename FaceRange::const_iterator lit = local_faces.begin(),
434 lit_end = local_faces.end(); lit != lit_end; ++lit )
435 if ( ! lit->isClosed() )
436 all_faces.insert( *lit );
441 //-----------------------------------------------------------------------------
442 template <typename TDigitalSurfaceContainer>
444 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::Face
445 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
446 computeFace( UmbrellaState state ) const
448 myUmbrellaComputer.setState( state );
449 Surfel start = state.surfel;
454 // std::cerr << " + s/surf "
455 // << myUmbrellaComputer.state().surfel<< std::endl;
457 code = myUmbrellaComputer.previous();
458 if ( code == 0 ) break; // face is open
459 if ( myUmbrellaComputer.state() < state )
460 state = myUmbrellaComputer.state();
462 while ( myUmbrellaComputer.surfel() != start );
463 if ( code == 0 ) // open face
464 { // Going back to count the number of incident vertices.
468 // std::cerr << " + c/surf "
469 // << myUmbrellaComputer.state().surfel<< std::endl;
471 code = myUmbrellaComputer.next();
474 return Face( myUmbrellaComputer.state(), nb, false );
477 return Face( state, nb, true );
479 //-----------------------------------------------------------------------------
480 template <typename TDigitalSurfaceContainer>
482 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::SCell
483 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
484 separator( const Arc & a ) const
486 return container().space().sIncident( a.base, a.k, a.epsilon );
488 //-----------------------------------------------------------------------------
489 // template <typename TDigitalSurfaceContainer>
491 // typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::SCell
492 // DGtal::DigitalSurface<TDigitalSurfaceContainer>::
493 // separator( const Face & f ) const
495 // return container().space().sIncident( f.state.surfel, f.state.k,
496 // f.state.epsilon );
498 //-----------------------------------------------------------------------------
499 template <typename TDigitalSurfaceContainer>
501 typename DGtal::DigitalSurface<TDigitalSurfaceContainer>::SCell
502 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
503 pivot( const Face & f ) const
505 SCell sep = container().space().sIncident( f.state.surfel, f.state.k,
507 return container().space().sDirectIncident( sep, f.state.j );
512 ///////////////////////////////////////////////////////////////////////////////
513 // Interface - public :
516 * Writes/Displays the object on an output stream.
517 * @param out the output stream where the object is written.
519 template <typename TDigitalSurfaceContainer>
522 DGtal::DigitalSurface<TDigitalSurfaceContainer>::selfDisplay ( std::ostream & out ) const
524 out << "[DigitalSurface]";
528 * Checks the validity/consistency of the object.
529 * @return 'true' if the object is valid, 'false' otherwise.
531 template <typename TDigitalSurfaceContainer>
534 DGtal::DigitalSurface<TDigitalSurfaceContainer>::isValid() const
536 return myTracker != 0;
539 //-----------------------------------------------------------------------------
541 Writes/Displays the object on an output stream.
542 @param out the output stream where the object is written.
544 template <typename TDigitalSurfaceContainer>
546 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
547 exportSurfaceAs3DOFF ( std::ostream & out ) const
549 typedef DGtal::uint64_t Number;
550 // Numbers all vertices.
551 std::map<Vertex, Number> index;
553 for ( ConstIterator it = begin(), it_end = end();
555 index[ *it ] = nbv++;
557 // std::cerr << "- " << nbv << " vertices." << std::endl;
558 FaceSet faces = allClosedFaces();
559 // Compute the number of edges and faces.
562 for ( typename FaceSet::const_iterator
563 itf = faces.begin(), itf_end = faces.end();
564 itf != itf_end; ++itf )
566 if ( itf->isClosed() )
567 { nbe += itf->nbVertices; ++nbf; }
569 { nbe += itf->nbVertices - 1; }
571 // std::cerr << "- " << nbf << " faces." << std::endl;
572 // Outputs OFF header.
573 out << "OFF" << std::endl
574 << "# Generated by DGtal::DigitalSurface." << std::endl
575 << nbv << " " << nbf << " " << ( nbe / 2 ) << std::endl;
576 // Outputs vertex coordinates (the 3 first ones).
577 const KSpace & K = container().space();
578 for ( ConstIterator it = begin(), it_end = end();
581 Point p = K.sKCoords( *it );
582 out << p[ 0 ] << " " << p[ 1 ] << " " << p[ 2 ] << std::endl;
583 // double areaD = NumberTraits<Coordinate>::castToDouble(area)*2.0;
585 // Outputs closed faces.
586 for ( typename FaceSet::const_iterator
587 itf = faces.begin(), itf_end = faces.end();
588 itf != itf_end; ++itf )
590 if ( itf->isClosed() )
592 out << itf->nbVertices;
593 VertexRange vtcs = verticesAroundFace( *itf );
594 for ( typename VertexRange::const_iterator
595 itv = vtcs.begin(), itv_end = vtcs.end();
596 itv != itv_end; ++itv )
597 out << " " << index[ *itv ];
603 //-----------------------------------------------------------------------------
604 template <typename TDigitalSurfaceContainer>
605 template <typename CellEmbedder>
607 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
608 exportEmbeddedSurfaceAs3DOFF
609 ( std::ostream & out,
610 const CellEmbedder & cembedder ) const
612 BOOST_CONCEPT_ASSERT(( concepts::CCellEmbedder< CellEmbedder > ));
614 typedef DGtal::uint64_t Number;
615 // Numbers all vertices.
616 std::map<Vertex, Number> index;
618 for ( ConstIterator it = begin(), it_end = end();
620 index[ *it ] = nbv++;
622 // std::cerr << "- " << nbv << " vertices." << std::endl;
623 FaceSet faces = allClosedFaces();
624 // Compute the number of edges and faces.
627 for ( typename FaceSet::const_iterator
628 itf = faces.begin(), itf_end = faces.end();
629 itf != itf_end; ++itf )
631 if ( itf->isClosed() )
632 { nbe += itf->nbVertices; ++nbf; }
634 { nbe += itf->nbVertices - 1; }
636 // std::cerr << "- " << nbf << " faces." << std::endl;
637 // Outputs OFF header.
638 out << "OFF" << std::endl
639 << "# Generated by DGtal::DigitalSurface." << std::endl
640 << nbv << " " << nbf << " " << ( nbe / 2 ) << std::endl;
641 // Outputs vertex coordinates (the 3 first ones).
642 typedef typename CellEmbedder::RealPoint RealPoint;
643 const KSpace & K = container().space();
644 for ( ConstIterator it = begin(), it_end = end();
647 RealPoint p( cembedder( K.unsigns( *it ) ) );
648 out << p[ 0 ] << " " << p[ 1 ] << " " << p[ 2 ] << std::endl;
649 // double areaD = NumberTraits<Coordinate>::castToDouble(area)*2.0;
651 // Outputs closed faces.
652 for ( typename FaceSet::const_iterator
653 itf = faces.begin(), itf_end = faces.end();
654 itf != itf_end; ++itf )
656 if ( itf->isClosed() )
658 out << itf->nbVertices;
659 VertexRange vtcs = verticesAroundFace( *itf );
660 for ( typename VertexRange::const_iterator
661 itv = vtcs.begin(), itv_end = vtcs.end();
662 itv != itv_end; ++itv )
663 out << " " << index[ *itv ];
669 //-----------------------------------------------------------------------------
670 template <typename TDigitalSurfaceContainer>
671 template <typename CellEmbedder>
673 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
674 exportEmbeddedSurfaceAs3DNOFF
675 ( std::ostream & out,
676 const CellEmbedder & cembedder ) const
678 BOOST_CONCEPT_ASSERT(( concepts::CCellEmbedder< CellEmbedder > ));
679 BOOST_CONCEPT_ASSERT(( concepts::CWithGradientMap< CellEmbedder > ));
681 typedef typename CellEmbedder::GradientMap GradientMap;
682 typedef typename CellEmbedder::Cell MyCell;
683 typedef typename CellEmbedder::RealPoint RealPoint;
684 typedef typename CellEmbedder::RealVector RealVector;
685 typedef DGtal::uint64_t Number;
687 // Gets the gradient map.
688 GradientMap gradMap = cembedder.gradientMap();
689 // Numbers all vertices.
690 std::map<Vertex, Number> index;
692 for ( ConstIterator it = begin(), it_end = end();
694 index[ *it ] = nbv++;
696 // std::cerr << "- " << nbv << " vertices." << std::endl;
697 FaceSet faces = allClosedFaces();
698 // Compute the number of edges and faces.
701 for ( typename FaceSet::const_iterator
702 itf = faces.begin(), itf_end = faces.end();
703 itf != itf_end; ++itf )
705 if ( itf->isClosed() )
706 { nbe += itf->nbVertices; ++nbf; }
708 { nbe += itf->nbVertices - 1; }
710 // std::cerr << "- " << nbf << " faces." << std::endl;
711 // Outputs OFF header.
712 out << "NOFF" << std::endl
713 << "# Generated by DGtal::DigitalSurface." << std::endl
714 << nbv << " " << nbf << " " << ( nbe / 2 ) << std::endl;
715 // Outputs vertex coordinates (the 3 first ones).
716 const KSpace & K = container().space();
719 for ( ConstIterator it = begin(), it_end = end();
722 MyCell c = K.unsigns( *it );
725 //cembedder.embedSCell( *it, p, v );
726 double norm = v.norm();
727 if ( norm != 0.0 ) v /= norm;
728 out << p[ 0 ] << " " << p[ 1 ] << " " << p[ 2 ] << " "
729 << v[ 0 ] << " " << v[ 1 ] << " " << v[ 2 ] << std::endl;
730 // double areaD = NumberTraits<Coordinate>::castToDouble(area)*2.0;
732 // Outputs closed faces.
733 for ( typename FaceSet::const_iterator
734 itf = faces.begin(), itf_end = faces.end();
735 itf != itf_end; ++itf )
737 if ( itf->isClosed() )
739 out << itf->nbVertices;
740 VertexRange vtcs = verticesAroundFace( *itf );
741 for ( typename VertexRange::const_iterator
742 itv = vtcs.begin(), itv_end = vtcs.end();
743 itv != itv_end; ++itv )
744 out << " " << index[ *itv ];
750 //-----------------------------------------------------------------------------
751 template <typename TDigitalSurfaceContainer>
752 template <typename SCellEmbedderWithGradientMap>
754 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
756 ( std::ostream & out,
757 const SCellEmbedderWithGradientMap & scembedder ) const
759 BOOST_CONCEPT_ASSERT(( concepts::CSCellEmbedder< SCellEmbedderWithGradientMap > ));
760 BOOST_CONCEPT_ASSERT(( concepts::CWithGradientMap< SCellEmbedderWithGradientMap > ));
762 typedef typename SCellEmbedderWithGradientMap::GradientMap GradientMap;
763 typedef typename SCellEmbedderWithGradientMap::SCell MySCell;
764 typedef typename SCellEmbedderWithGradientMap::RealPoint RealPoint;
765 typedef typename SCellEmbedderWithGradientMap::RealVector RealVector;
766 typedef DGtal::uint64_t Number;
768 // Gets the gradient map.
769 GradientMap gradMap = scembedder.gradientMap();
770 // Numbers all vertices.
771 std::map<Vertex, Number> index;
773 for ( ConstIterator it = begin(), it_end = end();
775 index[ *it ] = nbv++;
777 // std::cerr << "- " << nbv << " vertices." << std::endl;
778 FaceSet faces = allClosedFaces();
779 // Compute the number of edges and faces.
782 for ( typename FaceSet::const_iterator
783 itf = faces.begin(), itf_end = faces.end();
784 itf != itf_end; ++itf )
786 if ( itf->isClosed() )
787 { nbe += itf->nbVertices; ++nbf; }
789 { nbe += itf->nbVertices - 1; }
791 // std::cerr << "- " << nbf << " faces." << std::endl;
792 // Outputs OFF header.
793 out << "NOFF" << std::endl
794 << "# Generated by DGtal::DigitalSurface." << std::endl
795 << nbv << " " << nbf << " " << ( nbe / 2 ) << std::endl;
796 // Outputs vertex coordinates (the 3 first ones).
799 for ( ConstIterator it = begin(), it_end = end();
805 //cembedder.embedSCell( *it, p, v );
806 double norm = v.norm();
807 if ( norm != 0.0 ) v /= norm;
808 out << p[ 0 ] << " " << p[ 1 ] << " " << p[ 2 ] << " "
809 << v[ 0 ] << " " << v[ 1 ] << " " << v[ 2 ] << std::endl;
810 // double areaD = NumberTraits<Coordinate>::castToDouble(area)*2.0;
812 // Outputs closed faces.
813 for ( typename FaceSet::const_iterator
814 itf = faces.begin(), itf_end = faces.end();
815 itf != itf_end; ++itf )
817 if ( itf->isClosed() )
819 out << itf->nbVertices;
820 VertexRange vtcs = verticesAroundFace( *itf );
821 for ( typename VertexRange::const_iterator
822 itv = vtcs.begin(), itv_end = vtcs.end();
823 itv != itv_end; ++itv )
824 out << " " << index[ *itv ];
830 //-----------------------------------------------------------------------------
831 template <typename TDigitalSurfaceContainer>
832 template <typename CellEmbedder>
834 DGtal::DigitalSurface<TDigitalSurfaceContainer>::
835 exportEmbeddedIteratedSurfaceAs3DNOFF
836 ( std::ostream & out,
837 const CellEmbedder & cembedder ) const
839 typedef DGtal::uint64_t Number;
840 // Numbers all vertices.
841 std::map<Vertex, Number> index;
843 for ( ConstIterator it = begin(), it_end = end();
845 index[ *it ] = nbv++;
847 // std::cerr << "- " << nbv << " vertices." << std::endl;
848 FaceSet faces = allClosedFaces();
849 // Compute the number of edges and faces.
852 for ( typename FaceSet::const_iterator
853 itf = faces.begin(), itf_end = faces.end();
854 itf != itf_end; ++itf )
856 if ( itf->isClosed() )
857 { nbe += itf->nbVertices; ++nbf; }
859 { nbe += itf->nbVertices - 1; }
861 // std::cerr << "- " << nbf << " faces." << std::endl;
862 // Outputs OFF header.
863 out << "NOFF" << std::endl
864 << "# Generated by DGtal::DigitalSurface." << std::endl
865 << nbv << " " << nbf << " " << ( nbe / 2 ) << std::endl;
866 // Outputs vertex coordinates (the 3 first ones).
867 typedef typename CellEmbedder::RealPoint RealPoint;
868 typedef typename CellEmbedder::RealVector RealVector;
869 const KSpace & K = container().space();
872 for ( ConstIterator it = begin(), it_end = end();
875 cembedder.embedSurfel( it, p, v );
876 double norm = v.norm();
877 if ( norm != 0.0 ) v /= norm;
878 out << p[ 0 ] << " " << p[ 1 ] << " " << p[ 2 ] << " "
879 << v[ 0 ] << " " << v[ 1 ] << " " << v[ 2 ] << std::endl;
880 // double areaD = NumberTraits<Coordinate>::castToDouble(area)*2.0;
882 // Outputs closed faces.
883 for ( typename FaceSet::const_iterator
884 itf = faces.begin(), itf_end = faces.end();
885 itf != itf_end; ++itf )
887 if ( itf->isClosed() )
889 out << itf->nbVertices;
890 VertexRange vtcs = verticesAroundFace( *itf );
891 for ( typename VertexRange::const_iterator
892 itv = vtcs.begin(), itv_end = vtcs.end();
893 itv != itv_end; ++itv )
894 out << " " << index[ *itv ];
903 ///////////////////////////////////////////////////////////////////////////////
904 // Implementation of inline functions //
906 template <typename TDigitalSurfaceContainer>
909 DGtal::operator<< ( std::ostream & out,
910 const DigitalSurface<TDigitalSurfaceContainer> & object )
912 object.selfDisplay( out );
917 ///////////////////////////////////////////////////////////////////////////////