示例#1
0
int
LiNode::subdivide() {

    Vec3 size = (_max - _min) * 0.5;

    if(size.length() < 0.00000001) {
        printf("SIZE: %d\n", _surfelCount);
        for(int i = 0; i < _surfelCount; i++) {
            Surfel surf = *_surfelData[i];
            printf("\t%s\n", surf.position().str());
        }
        printf("ERROR\n\tMIN: %s\n\tMAX: %s\n", _min.str(), _max.str());
        exit(1);
    }
    assert(size.length() > 0.00000001);
    Vec3 min, max;
    int x,y,z;

    // Loop over children
    for(int i = 0; i < 8; i++) {
        // Find out which child this is (in terms of what quadrant)
        x = i%2;
        y = (i/2)%2;
        z = (i/4);

        // Define minimum by which quadrant it is in
        min = Vec3(_min.x() + (size.x() * x),
                     _min.y() + (size.y() * y),
                     _min.z() + (size.z() * z));

        // Max is always the minimum plus the size of the node
        max = min + size;

        
        m_children[i] = new LiNode(min, max);
    }

    int surfCount = _surfelCount;

    //_surfelCount = 0;

    // Iterate over all existing surfel data
    for(int i = 0; i < surfCount; i++) {
        //printf("Re-Adding %s!\n", _surfelData[i]->position().str());
        // Re-add the surfel, allowing it to recurse into the children
        add(_surfelData[i]);
    }
    // Clear all surfel data in this node
    return 0;
}
示例#2
0
	void TangencialError(const Surfel& surfel)
	{

        Real dis_max = 0.0;
        Real dist = 0.0;
        Real result = 9999999.0;
        Real A = 0.0;
        Real B = 0.0;
        Real BA = 0.0;
        Real Aline = 0.0;
        Point3  q;
        Vector3 r,s;

        ListPoint3 l = surfel.BoundariesSamples(8,1.0);

        for(ListPoint3Iterator p = l.begin(); p != l.end();++p)
        {

        	for(SurfelListIterator itEllipse = mEllipses.begin(); itEllipse != mEllipses.end(); ++itEllipse)
        	{
			   q =  (*p) - ((( (*p) - itEllipse->Center() ) * itEllipse->Normal()) * itEllipse->Normal()); //(*p) - ( ( ( (*p) - itEllipse->Center() ) * itEllipse->Normal()  ) * itEllipse->Normal());
               r =  q - itEllipse->Center();
               s =  (*p) - q;
               A = (r * itEllipse->MajorAxis().second)/(itEllipse->MajorAxis().first);
               B = (r * itEllipse->MinorAxis().second)/(itEllipse->MinorAxis().first);
               if ((A*A + B*B) > 1)
               {
                    BA = B/A;
                    Aline = std::sqrt(1.0/(1.0+(BA*BA)));
                    dist = (1-(Aline/std::fabs(A))) * std::sqrt(r*r)  + std::sqrt(s*s);
               }
               else
               {
            	   dist = sqrt(s*s);
               }

               if (result > dist)
			   {
            	   result = dist;
			   }

        	}
        	if (result > dis_max)
            {
         	   dis_max = result;
            }
        }
        mNewTangencialError = dis_max;
	}
示例#3
0
	Surfel NewSurfel(Splat type)
	{
		if (type == ELLIPTICAL)
		{
			Surfel s = Surfel(mNewCenter,mNewNormal,mNewMinorAxis,mNewMajorAxis,1);
			s.SetPerpendicularError(mNewPerpendicularError);
			s.SetTangencialError(mNewTangencialError);
			s.SetMinError(mNewTangencialError+mNewPerpendicularError);
			return ( s );
		}
		if (type == CIRCULAR)
		{
			Surfel s =  Surfel(mNewCenter,mNewNormal,std::make_pair(mNewMajorAxis.first,mNewMinorAxis.second),mNewMajorAxis,1);
			s.SetPerpendicularError(mNewPerpendicularError);
			s.SetTangencialError(mNewTangencialError);
			s.SetMinError(mNewTangencialError+mNewPerpendicularError);
			return (s);
		}

	}
  static int LoadMesh (
		       const char * filename,
		       std::vector<Surfel<Real> >& pSurfel,vcg::CallBackPos *cb = 0)
  {
    MyMesh mesh;

    int mask = 0;

    mesh.Clear();

    if (cb != NULL) 	(*cb)(0, "Loading Model...");


    vcg::tri::io::PlyInfo info;
    info.cb = cb;

    vcg::tri::io::ImporterPLY<MyMesh>::LoadMask(filename, mask,info);
    vcg::tri::io::ImporterPLY<MyMesh>::Open(mesh,filename,info);


    bool normal_per_vertex = false;
    if (mask & vcg::tri::io::Mask::IOM_VERTNORMAL)
      normal_per_vertex = true;

    bool color_per_vertex = false;
    if (mask & vcg::tri::io::Mask::IOM_VERTCOLOR)
      color_per_vertex = true;

    bool quality_per_vertex = false;
    if (mask & vcg::tri::io::Mask::IOM_VERTQUALITY)
      quality_per_vertex = true;

    bool radius_per_vertex = false;
    if (mask & vcg::tri::io::Mask::IOM_VERTRADIUS)
      radius_per_vertex = true;


    unsigned int pos = 0;
    Surfel<Real> s;

    for (MyMesh::VertexIterator vit = mesh.vert.begin(); vit != mesh.vert.end(); ++vit)
      {
	Point3f v = (*vit).P();
	Point3f n = (*vit).N();

	Color4b c (0.2, 0.2, 0.2, 1.0);
	if (color_per_vertex) {
	  c = Color4b ((GLubyte)(*vit).C()[0], (GLubyte)(*vit).C()[1], (GLubyte)(*vit).C()[2], 1.0);
	}

	Real radius = 0.25;
	if (radius_per_vertex)
	  {
	    radius = static_cast<Real> (((*vit).R()));
	  }

	Real quality = 1.0;
	if (quality_per_vertex)
	  quality = static_cast<Real> ((*vit).Q());


	s = Surfel<Real> (v, n, c, radius, pos);

	s.SetRadius(radius);

	pSurfel.push_back (s);

	++pos;

      }
    std::cout << "Surfel " << pSurfel.size() << std::endl;
    if (cb != NULL)	(*cb)(99, "Done");
    mesh.Clear();
    return 0;
  }
void computeEstimation
( const po::variables_map& vm,     //< command-line parameters
  const KSpace& K,                 //< cellular grid space
  const ImplicitShape& shape,      //< implicit shape "ground truth"
  const Surface& surface,          //< digital surface approximating shape
  TrueEstimator& true_estimator,   //< "ground truth" estimator
  Estimator& estimator )           //< an initialized estimator
{
  typedef typename Surface::ConstIterator ConstIterator;
  typedef typename Surface::Surfel Surfel;
  typedef typename Estimator::Quantity Quantity;
  typedef double Scalar;
  typedef DepthFirstVisitor< Surface > Visitor;
  typedef GraphVisitorRange< Visitor > VisitorRange;
  typedef typename VisitorRange::ConstIterator VisitorConstIterator;
  
  std::string fname = vm[ "output" ].as<std::string>();
  string nameEstimator = vm[ "estimator" ].as<string>();
  trace.beginBlock( "Computing " + nameEstimator + "estimations." );
  CountedPtr<VisitorRange> range( new VisitorRange( new Visitor( surface, *(surface.begin()) )) );
  std::vector<Quantity> n_estimations;
  estimator.eval( range->begin(), range->end(), std::back_inserter( n_estimations ) );
  trace.info() << "- nb estimations  = " << n_estimations.size() << std::endl;
  trace.endBlock();

  trace.beginBlock( "Computing ground truth." );
  range = CountedPtr<VisitorRange>( new VisitorRange( new Visitor( surface, *(surface.begin()) )) );
  std::vector<Quantity> n_true_estimations;
  true_estimator.eval( range->begin(), range->end(), std::back_inserter( n_true_estimations ) );
  trace.info() << "- nb estimations  = " << n_true_estimations.size() << std::endl;
  trace.endBlock();

  trace.beginBlock( "Correcting orientations." );
  ASSERT( n_estimations.size() == n_true_estimations.size() );
  for ( unsigned int i = 0; i < n_estimations.size(); ++i )
    if ( n_estimations[ i ].dot( n_true_estimations[ i ] ) < 0 )
      n_estimations[ i ] = -n_estimations[ i ];
  trace.endBlock();

  DGtal::GradientColorMap<double> grad( 0.0, 40.0 );
  // 0 metallic blue, 5 light cyan, 10 light green, 15 light
  // yellow, 20 yellow, 25 orange, 30 red, 35, dark red, 40- grey
  grad.addColor( DGtal::Color( 128, 128, 255 ) ); // 0
  grad.addColor( DGtal::Color( 128, 255, 255 ) ); // 5
  grad.addColor( DGtal::Color( 128, 255, 128 ) ); // 10
  grad.addColor( DGtal::Color( 255, 255, 128 ) ); // 15
  grad.addColor( DGtal::Color( 255, 255, 0   ) ); // 20
  grad.addColor( DGtal::Color( 255, 128, 0   ) ); // 25
  grad.addColor( DGtal::Color( 255,   0, 0   ) ); // 30
  grad.addColor( DGtal::Color( 128,   0, 0   ) ); // 35
  grad.addColor( DGtal::Color( 128, 128, 128 ) ); // 40

  if ( vm.count( "angle-deviation-stats" ) )
    {
      trace.beginBlock( "Computing angle deviation error stats." );
      std::ostringstream adev_sstr;
      adev_sstr << fname << "-" << nameEstimator << "-angle-deviation-" 
                << estimator.h() << ".txt"; 
      DGtal::Statistic<Scalar> adev_stat;
      unsigned int i = 0;
      range = CountedPtr<VisitorRange>( new VisitorRange( new Visitor( surface, *(surface.begin()) )) );
      for ( VisitorConstIterator it = range->begin(), itE = range->end(); it != itE; ++it, ++i )
        {
          Quantity n_est = n_estimations[ i ];
          Quantity n_true_est = n_true_estimations[ i ];
          Scalar angle_error = acos( n_est.dot( n_true_est ) );
          adev_stat.addValue( angle_error );
        }
      adev_stat.terminate();
      std::ofstream adev_output( adev_sstr.str().c_str() );
      adev_output << "# Average error X of the absolute angle between two vector estimations." << std::endl;
      adev_output << "# h L1 L2 Loo E[X] Var[X] Min[X] Max[X] Nb[X]" << std::endl;
      adev_output << estimator.h() 
                  << " " << adev_stat.mean() // L1
                  << " " << sqrt( adev_stat.unbiasedVariance()
                                  + adev_stat.mean()*adev_stat.mean() ) // L2
                  << " " << adev_stat.max() // Loo
                  << " " << adev_stat.mean() // E[X] (=L1)
                  << " " << adev_stat.unbiasedVariance() // Var[X]
                  << " " << adev_stat.min() // Min[X]
                  << " " << adev_stat.max() // Max[X]
                  << " " << adev_stat.samples() // Nb[X]
                  << std::endl;
      adev_output.close();
      trace.endBlock();
    }
  if ( vm[ "export" ].as<string>() != "None" )
    {
      trace.beginBlock( "Exporting cell geometry." );
      std::ostringstream export_sstr;
      export_sstr << fname << "-" << nameEstimator << "-cells-" 
                  << estimator.h() << ".txt"; 
      std::ofstream export_output( export_sstr.str().c_str() );
      export_output << "# ImaGene viewer (viewSetOfSurfels) file format for displaying cells." << std::endl;
      bool adev =  vm[ "export" ].as<string>() == "AngleDeviation";
      unsigned int i = 0;
      range = CountedPtr<VisitorRange>( new VisitorRange( new Visitor( surface, *(surface.begin()) )) );
      for ( VisitorConstIterator it = range->begin(), itE = range->end(); it != itE; ++it, ++i )
        {
          Quantity n_est = n_estimations[ i ];
          Quantity n_true_est = n_true_estimations[ i ];
          Scalar angle_error = acos( n_est.dot( n_true_est ) )*180.0 / 3.14159625;
          Surfel s = *it;
          export_output
            << "CellN" 
            << " " << min( 1023, max( 512+K.sKCoord( s, 0 ), 0 ) )
            << " " << min( 1023, max( 512+K.sKCoord( s, 1 ), 0 ) )
            << " " << min( 1023, max( 512+K.sKCoord( s, 2 ), 0 ) )
            << " " << K.sSign( s );
          Color c = grad( 0 );
          if ( adev ) c = grad( max( 0.0, min( angle_error, 40.0 ) ) );
          export_output << " " << ((double) c.red() / 255.0 )
                        << " " << ((double) c.green() / 255.0 )
                        << " " << ((double) c.blue() / 255.0 );
          export_output << " " << n_est[ 0 ] << " " << n_est[ 1 ] 
                        << " " << n_est[ 2 ] << std::endl;
        }
      export_output.close();
      trace.endBlock();
    }
  if ( vm.count( "normals" ) )
    {
      trace.beginBlock( "Exporting cells normals." );
      std::ostringstream export_sstr;
      export_sstr << fname << "-" << nameEstimator << "-normals-" 
                  << estimator.h() << ".txt"; 
      std::ofstream export_output( export_sstr.str().c_str() );
      export_output << "# kx ky kz sign n_est[0] n_est[1] n_est[2] n_true[0] n_true[1] n_true[2]" << std::endl;
      unsigned int i = 0;
      range = CountedPtr<VisitorRange>( new VisitorRange( new Visitor( surface, *(surface.begin()) )) );
      for ( VisitorConstIterator it = range->begin(), itE = range->end(); it != itE; ++it, ++i )
        {
          Quantity n_est = n_estimations[ i ];
          Quantity n_true_est = n_true_estimations[ i ];
          Surfel s = *it;
          export_output
            << K.sKCoord( s, 0 ) << " " << K.sKCoord( s, 1 ) << " " << K.sKCoord( s, 2 ) 
            << " " << K.sSign( s )
            << " " << n_est[ 0 ] << " " << n_est[ 1 ] << " " << n_est[ 2 ]
            << " " << n_true_est[ 0 ] << " " << n_true_est[ 1 ] << " " << n_true_est[ 2 ]
            << std::endl;
        }
      export_output.close();
      trace.endBlock();
    }
  if ( vm.count( "noff" ) )
    {
      trace.beginBlock( "Exporting NOFF file." );
      std::ostringstream export_sstr;
      export_sstr << fname << "-" << nameEstimator << "-noff-" 
                  << estimator.h() << ".off"; 
      std::ofstream export_output( export_sstr.str().c_str() );
      std::map<Surfel,Quantity> normals;
      unsigned int i = 0;
      range = CountedPtr<VisitorRange>( new VisitorRange( new Visitor( surface, *(surface.begin()) )) );
      for ( VisitorConstIterator it = range->begin(), itE = range->end(); it != itE; ++it, ++i )
        {
          Quantity n_est = n_estimations[ i ];
          normals[ *it ] = n_est;
        }
      CanonicSCellEmbedder<KSpace> surfelEmbedder( K );
      typedef SCellEmbedderWithNormal< CanonicSCellEmbedder<KSpace> > Embedder;
      Embedder embedder( surfelEmbedder, normals );
      surface.exportAs3DNOFF( export_output, embedder );
      export_output.close();
      trace.endBlock();
    }
#ifdef WITH_VISU3D_QGLVIEWER
  if ( vm[ "view" ].as<string>() != "None" )
    {
      typedef typename KSpace::Space Space;
      typedef Viewer3D<Space,KSpace> MyViewever3D;
      typedef Display3DFactory<Space,KSpace> MyDisplay3DFactory;
      int argc = 1;
      char name[] = "Viewer";
      char* argv[ 1 ];
      argv[ 0 ] = name;
      Surfel s;
      QApplication application( argc, argv );
      MyViewever3D viewer( K );
      viewer.show();
      viewer << SetMode3D( s.className(), "Basic" );
      trace.beginBlock( "Viewing surface." );
      bool adev =  vm[ "view" ].as<string>() == "AngleDeviation";

      unsigned int i = 0;
      range = CountedPtr<VisitorRange>( new VisitorRange( new Visitor( surface, *(surface.begin()) )) );
      for ( VisitorConstIterator it = range->begin(), itE = range->end(); it != itE; ++it, ++i )
        {
          Quantity n_est = n_estimations[ i ];
          Quantity n_true_est = n_true_estimations[ i ];
          Scalar angle_error = acos( n_est.dot( n_true_est ) )*180.0 / 3.14159625;
          s = *it;
          Color c = grad( 0 );
          if ( adev ) c = grad( max( 0.0, min( angle_error, 40.0 ) ) );
          viewer.setFillColor( c );
          MyDisplay3DFactory::drawOrientedSurfelWithNormal( viewer, s, n_est, false );
        }
      trace.endBlock();
      viewer << MyViewever3D::updateDisplay;
      application.exec();
    }
#endif

}
示例#6
0
int main( int argc, char** argv )
{
  // for 3D display with Viewer3D
  QApplication application(argc,argv);
  
  //! [digitalSurfaceSlice-readVol]
  trace.beginBlock( "Reading vol file into an image." );
  typedef ImageSelector < Domain, int>::Type Image;
  std::string inputFilename = examplesPath + "samples/Al.100.vol"; 
  Image image = VolReader<Image>::importVol(inputFilename);
  DigitalSet set3d (image.domain());
  SetPredicate<DigitalSet> set3dPredicate( set3d );
  SetFromImage<DigitalSet>::append<Image>(set3d, image, 
                                          0, 1 );
  Viewer3D viewer;  
  viewer.show(); 
  trace.endBlock();
  //! [digitalSurfaceSlice-readVol]
  
  //! [digitalSurfaceSlice-KSpace]
  trace.beginBlock( "Construct the Khalimsky space from the image domain." );
  KSpace ks;
  bool space_ok = ks.init( image.domain().lowerBound(), 
                           image.domain().upperBound(), true );
  if (!space_ok)
    {
      trace.error() << "Error in the Khamisky space construction."<<std::endl;
      return 2;
    }
  trace.endBlock();
  //! [digitalSurfaceSlice-KSpace]

  //! [digitalSurfaceSlice-SurfelAdjacency]
  typedef SurfelAdjacency<KSpace::dimension> MySurfelAdjacency;
  MySurfelAdjacency surfAdj( true ); // interior in all directions.
  //! [digitalSurfaceSlice-SurfelAdjacency]

  //! [digitalSurfaceSlice-ExtractingSurface]
  trace.beginBlock( "Extracting boundary by scanning the space. " );
  typedef KSpace::Surfel Surfel;
  typedef KSpace::SurfelSet SurfelSet;
  typedef SetOfSurfels< KSpace, SurfelSet > MySetOfSurfels;
  typedef DigitalSurface< MySetOfSurfels > MyDigitalSurface;
  MySetOfSurfels theSetOfSurfels( ks, surfAdj );
  Surfaces<KSpace>::sMakeBoundary( theSetOfSurfels.surfelSet(),
                                   ks, set3dPredicate,
                                   image.domain().lowerBound(), 
                                   image.domain().upperBound() );
  MyDigitalSurface digSurf( theSetOfSurfels );
  trace.info() << "Digital surface has " << digSurf.size() << " surfels."
               << std::endl;
  trace.endBlock();
  //! [digitalSurfaceSlice-ExtractingSurface]
  
  //! [digitalSurfaceSlice-ExtractingSlice]
  trace.beginBlock( "Extract slices." );
  typedef MyDigitalSurface::DigitalSurfaceTracker MyTracker;
  typedef DigitalSurface2DSlice< MyTracker > My2DSlice;
  //Extract an initial boundary cell
  Surfel surf = *digSurf.begin();
  MyTracker* tracker1 = digSurf.container().newTracker( surf );
  MyTracker* tracker2 = digSurf.container().newTracker( surf );
  // Extract the bondary contour associated to the initial surfel in
  // its first direction
  My2DSlice slice1( tracker1, *(ks.sDirs( surf )) ); 
  // Extract the bondary contour associated to the initial surfel in
  // its second direction
  My2DSlice slice2( tracker2, *++(ks.sDirs( surf )) ); 
  delete tracker1;
  delete tracker2;
  trace.endBlock();
  //! [digitalSurfaceSlice-ExtractingSlice]

  ASSERT( slice1.start() == slice1.begin() );
  ASSERT( slice1.cstart() == slice1.c() );
  ASSERT( *slice1.begin() == surf );
  ASSERT( *slice1.c() == surf );
  ASSERT( *slice1.start() == surf );
  ASSERT( *slice1.cstart() == surf );
  ASSERT( *slice1.rcstart() == surf );
  ASSERT( slice1.rcstart() == slice1.rc() );
  ASSERT( *slice1.rc() == surf );
  ASSERT( *(slice1.c()+1) == *(slice1.begin()+1) );
  ASSERT( *(slice1.rc()+1) == *(slice1.rbegin()) );

  //! [digitalSurfaceSlice-displayingAll]
  trace.beginBlock( "Display all with QGLViewer." );
  // Displaying all the surfels in transparent mode
  viewer << SetMode3D( surf.className(), "Transparent");
  for( MyDigitalSurface::ConstIterator it = theSetOfSurfels.begin(),
         it_end = theSetOfSurfels.end(); it != it_end; ++it )
    viewer<< *it;
  
  // Displaying First surfels cut with gradient colors.;
  GradientColorMap<int> cmap_grad( 0, slice1.size() );
  cmap_grad.addColor( Color( 50, 50, 255 ) );
  cmap_grad.addColor( Color( 255, 0, 0 ) );
  cmap_grad.addColor( Color( 255, 255, 10 ) );
  
  // Need to avoid surfel superposition (the surfel size in increased)
  viewer << Viewer3D::shiftSurfelVisu; 
  viewer << SetMode3D( surf.className(), "");
  viewer.setFillColor(Color(180, 200, 25, 255));
  
  int d=0;
  for ( My2DSlice::ConstIterator it = slice1.begin(),
          it_end = slice1.end(); it != it_end; ++it )
    {        
      Color col= cmap_grad(d);
      viewer.setFillColor(Color(col.red(),col.green() ,col.blue(), 255));
      viewer<< *it;
      d++;
    }
  
  GradientColorMap<int> cmap_grad2( 0, slice2.size() );
  cmap_grad2.addColor( Color( 50, 50, 255 ) );
  cmap_grad2.addColor( Color( 255, 0, 0 ) );
  cmap_grad2.addColor( Color( 255, 255, 10 ) );
  
  d=0;
  for ( My2DSlice::ConstIterator it = slice2.begin(),
          it_end = slice2.end(); it != it_end; ++it )
    {        
      Color col= cmap_grad2(d);
      viewer.setFillColor(Color(col.red(),col.green() ,col.blue(), 255));
      viewer<< *it;
      d++;
    }
  
  // One need once again to avoid superposition.
  viewer << Viewer3D::shiftSurfelVisu; 
  viewer.setFillColor(Color(18, 200, 25, 255));
  viewer << surf ;
  viewer << Viewer3D::updateDisplay;
  trace.endBlock();
    
  return application.exec();
  //! [digitalSurfaceSlice-displayingAll]
}
示例#7
0
int main( int argc, char** argv )
{
  trace.info() <<  "exampleGridCurve3d: the type can be changed in example source code with  <gridcurve>, <inner>, <outer>, <incident> " << std::endl;

  string type = "gridcurve";

  //vol reading and digital set construction
  trace.beginBlock( "Reading vol file into an image." );
  typedef ImageSelector < Domain, int>::Type Image;
  std::string inputFilename = examplesPath + "samples/cat10.vol";
  Image image = VolReader<Image>::importVol(inputFilename);
  DigitalSet set3d (image.domain());
  setFromImage( image, DigitalSetInserter<DigitalSet>(set3d), 1);
  trace.info() << set3d.size() << " voxels." << std::endl;
  trace.endBlock();

  //Khalimsky space construction
  trace.beginBlock( "Construct the Khalimsky space from the image domain." );
  KSpace ks;
/*  bool space_ok = ks.init( image.domain().lowerBound(),
                           image.domain().upperBound(), true );
  if (!space_ok)
    {
      trace.error() << "Error in the Khamisky space construction."<<std::endl;
      return 2;
    }*/
  trace.endBlock();

  //digital surface construction
  typedef SurfelAdjacency<KSpace::dimension> MySurfelAdjacency;
  MySurfelAdjacency surfAdj( true ); // interior in all directions.

  trace.beginBlock( "Extracting boundary by scanning the space. " );
  typedef KSpace::Surfel Surfel;
  typedef KSpace::SurfelSet SurfelSet;
  typedef SetOfSurfels< KSpace, SurfelSet > MySetOfSurfels;
  typedef DigitalSurface< MySetOfSurfels > MyDigitalSurface;
  MySetOfSurfels theSetOfSurfels( ks, surfAdj );
  Surfaces<KSpace>::sMakeBoundary( theSetOfSurfels.surfelSet(),
                                   ks, set3d,
                                   image.domain().lowerBound(),
                                   image.domain().upperBound() );
  MyDigitalSurface digSurf( theSetOfSurfels );
  trace.info() << digSurf.size() << " surfels." << std::endl;
  trace.endBlock();

  //slice retrieving
  trace.beginBlock( "Extracting slice and constructing a grid curve. " );
  typedef MyDigitalSurface::DigitalSurfaceTracker MyTracker;
  typedef DigitalSurface2DSlice< MyTracker > My2DSlice;

  //Extract an initial boundary cell
  Surfel surf = *digSurf.begin();
  MyTracker* tracker = digSurf.container().newTracker( surf );

  // Extract the bondary contour associated to the initial surfel in
  // its first direction
  My2DSlice slice( tracker, *(ks.sDirs( surf )) );
  delete tracker;

  //! [exampleGridCurve3d-Construction]
  GridCurve<KSpace> gc(ks);
  gc.initFromSCellsRange( slice.begin(), slice.end() );
  //! [exampleGridCurve3d-Construction]

  trace.endBlock();


  // for 3D display with Viewer3D
  QApplication application(argc,argv);
  trace.beginBlock( "Display all with QGLViewer." );
  Viewer3D<> viewer;
  viewer.show();
  // Displaying all the surfels in transparent mode
  viewer << SetMode3D( surf.className(), "Transparent");
  for( MyDigitalSurface::ConstIterator it = theSetOfSurfels.begin(),
         it_end = theSetOfSurfels.end(); it != it_end; ++it )
    viewer<< *it;


  // Displaying slice
  viewer << Viewer3D<>::shiftSurfelVisu;
  viewer << SetMode3D( surf.className(), "");
  viewer.setFillColor( Color( 50, 50, 255 ) );

  if (type == "gridcurve")
    {
      viewer  << gc;
    }
  else if (type == "inner")
    {
      viewer << gc.getInnerPointsRange();
    }
  else if (type == "outer")
    {
      viewer << gc.getOuterPointsRange();
    }
  else if (type == "incident")
    {
      viewer << gc.getIncidentPointsRange();
    }
  else
    {
      trace.info() << "Display type not known. Use option -h" << std::endl;
    }

  viewer << Viewer3D<>::updateDisplay;
  trace.endBlock();

  return application.exec();
}