bool testRaySurface()
{
  typedef ImplicitBall<Z3i::Space> ImplicitShape;
  typedef GaussDigitizer<Z3i::Space, ImplicitShape> DigitalShape;
  typedef LightImplicitDigitalSurface<Z3i::KSpace,DigitalShape> Boundary;
  typedef DigitalSurface< Boundary > MyDigitalSurface;
  trace.beginBlock(" Ray shooting in digital surface");
  trace.beginBlock( "Shape initialisation ..." );
  ImplicitShape ishape( Z3i::RealPoint( 0, 0 ,0), 12 );
  DigitalShape dshape;
  dshape.attach( ishape );
  dshape.init( Z3i::RealPoint( -20.0, -20.0 ,-20.0 ), Z3i::RealPoint( 20.0, 20.0, 20.0  ), 1.0 );
  Z3i::KSpace K;
  if ( !K.init( dshape.getLowerBound(), dshape.getUpperBound(), true ) )
  {
    trace.error() << "Problem with Khalimsky space init" << std::endl;
    return false;
  }

  Z3i::KSpace::Surfel bel = Surfaces<Z3i::KSpace>::findABel( K, dshape, 10000 );
  Boundary boundary( K, dshape, SurfelAdjacency<Z3i::KSpace::dimension>( true ), bel );
  MyDigitalSurface surf ( boundary );
  trace.endBlock();


  trace.beginBlock(" Ray shooting the shape");
  
  RayIntersectionPredicate<Z3i::KSpace::Cell::Point> ray(Z3i::KSpace::Cell::Point(0,0,0),
                                                         Z3i::KSpace::Cell::Point(2,2,2));

  RayIntersectionPredicate<Z3i::KSpace::Cell::Point> ray2(Z3i::KSpace::Cell::Point(0,0,0),
                                                          Z3i::KSpace::Cell::Point(1,0,0));

  MyDigitalSurface::ConstIterator it = std::find_if(surf.begin(), surf.end(), ray); 
  trace.info() << "Ray shooting returns : "<< *it<<std::endl;

  MyDigitalSurface::ConstIterator it2 = std::find_if(surf.begin(), surf.end(), ray2); 
  trace.info() << "Ray shooting returns : "<< *it2<<std::endl;
  
  trace.endBlock();
  trace.endBlock();

  return true;
}
int main()
{
  const double h = 1;
  const double radiusBall = 12.0;
  
  trace.beginBlock( "Make parametric shape..." );
  
  typedef Ball3D< Z3i::Space > Shape;
  
  RealPoint center( 0.0, 0.0, 0.0 );
  Shape ball( center, radiusBall );
  RealPoint centerBis(18.0,0.0,0.0);
  Shape ballBis( centerBis, radiusBall);
  trace.endBlock();
  
  trace.beginBlock( "Make digital shape..." );
  typedef GaussDigitizer< Z3i::Space, Shape > DigitalShape;
  typedef DigitalShape::Domain Domain;
  
  DigitalShape digitalBall;
  digitalBall.attach( ball );
  digitalBall.init( ball.getLowerBound() - Z3i::RealPoint( 1.0, 1.0, 1.0 ),
                   ball.getUpperBound() + Z3i::RealPoint( 1.0, 1.0, 1.0 ),
                   h );
  DigitalShape digitalBallBis;
  digitalBallBis.attach( ballBis );
  digitalBallBis.init( ballBis.getLowerBound() - Z3i::RealPoint( 1.0, 1.0, 1.0 ),
                      ballBis.getUpperBound() + Z3i::RealPoint( 1.0, 1.0, 1.0 ),
                      h );
  
  Domain domain( digitalBall.getDomain().lowerBound().inf( digitalBallBis.getDomain().lowerBound() ),
                 digitalBall.getDomain().upperBound().sup( digitalBallBis.getDomain().upperBound() ));
  
  Z3i::KSpace kspace;
  kspace.init( domain.lowerBound(), domain.upperBound(), true );
  trace.info()<< domain <<std::endl;
  trace.endBlock();
  
  trace.beginBlock( "Make first digital surface..." );
  typedef LightImplicitDigitalSurface< Z3i::KSpace, DigitalShape > LightDigitalSurface;
  typedef DigitalSurface< LightDigitalSurface > DigitalSurface;
  typedef Z3i::KSpace::Surfel Surfel;
  
  Surfel bel = Surfaces< Z3i::KSpace >::findABel( kspace, digitalBall, 500 );
  SurfelAdjacency< Z3i::KSpace::dimension > surfelAdjacency( true );
  LightDigitalSurface lightDigitalSurface( kspace, digitalBall, surfelAdjacency, bel );
  DigitalSurface digitalSurface( lightDigitalSurface );

  bel = Surfaces< Z3i::KSpace >::findABel( kspace, digitalBallBis, 500 );
  LightDigitalSurface lightDigitalSurfaceBis( kspace, digitalBallBis, surfelAdjacency, bel );
  DigitalSurface digitalSurfaceBis( lightDigitalSurfaceBis );

  
  trace.endBlock();

  std::set<Surfel> storage;
  trace.beginBlock("Exporting the first ball");
  std::ofstream handle("output.csv");
  for(auto cell : digitalSurface)
  {
    const Point p = kspace.sKCoords(cell);
    
    if (p[0] < -7.5) continue;
    
    const KSpace::Sign sign = kspace.sSign(cell);
    for (int dim=0; dim<3; dim++)
      handle << p[dim] << " ";
    handle << ( sign == KSpace::POS ) << " ";
    for (int dim=0; dim<3; ++dim)
      handle << (p-center)[dim]<<" ";
    handle << std::endl;
    //std::cout << "exporting "<< cell<<std::endl;
    storage.insert( cell );
  }
  trace.endBlock();
  
  
  trace.beginBlock("Exporting the second ball");
  for(auto cell : digitalSurfaceBis)
  {
  
    if (storage.find(cell) != storage.end())
      continue;
    
    const Point p = kspace.sKCoords(cell);
    const KSpace::Sign sign = kspace.sSign(cell);
    // "2.0*" to map centerbis to Kspace
    const RealPoint normal = (p-2.0*centerBis).getNormalized();
    for (int dim=0; dim<3; dim++)
      handle << p[dim] << " ";
    handle << ( sign == KSpace::POS ) << " ";
    for (int dim=0; dim<3; ++dim)
      handle << normal[dim] <<" ";
    handle << std::endl;
    //std::cout << "exporting "<< cell<<std::endl;
  }
  trace.endBlock();
  
  
  handle.close();
  
  return 0;
}
Beispiel #3
0
int main( int argc, char** argv )
{
  trace.beginBlock ( "Example ctopo-2-3d" );
  // for 3D display with Viewer3D
  QApplication application(argc,argv);
  
  typedef ImageSelector < Z3i::Domain, int>::Type Image;
  std::string inputFilename = examplesPath + "samples/cat10.vol"; 
  Image image = VolReader<Image>::importVol(inputFilename);
  Z3i::DigitalSet set3d (image.domain());
  SetPredicate<Z3i::DigitalSet> set3dPredicate( set3d );
  SetFromImage<Z3i::DigitalSet>::append<Image>(set3d, image, 0,255);
  Viewer3D viewer;  
  viewer.show(); 
  
  
  // Construct the Khalimsky space from the image domain
  Z3i::KSpace ks;
  bool space_ok = ks.init( image.domain().lowerBound(), image.domain().upperBound(), true );
  
  ASSERT(space_ok);

  std::vector<Z3i::SCell> vectBdrySCell;
  std::vector<Z3i::SCell> vectBdrySCell2;
  std::set<Z3i::SCell> vectBdrySCellALL;
  SurfelAdjacency<3> SAdj( true );
  

  
  //Extract an initial boundary cell
  Z3i::SCell aCell = Surfaces<Z3i::KSpace>::findABel(ks, set3dPredicate);
  
  // Extracting all boundary surfels which are connected to the initial boundary Cell.
  Surfaces<Z3i::KSpace>::trackBoundary( vectBdrySCellALL,
          ks,SAdj, set3dPredicate, aCell );
    
  // Extract the bondary contour associated to the initial surfel in its first direction
  Surfaces<Z3i::KSpace>::track2DBoundary( vectBdrySCell,
             ks, *(ks.sDirs( aCell )), SAdj, 
            set3dPredicate, aCell );
  
  // Extract the bondary contour associated to the initial surfel in its second direction
  Surfaces<Z3i::KSpace>::track2DBoundary( vectBdrySCell2,
             ks, *(++(ks.sDirs( aCell ))), SAdj, 
            set3dPredicate, aCell );  
  
  
  // Displaying all the surfels in transparent mode
  viewer << SetMode3D((*(vectBdrySCellALL.begin())).styleName(), "Transparent");
  for( std::set<Z3i::SCell>::iterator it=vectBdrySCellALL.begin(); 
       it!= vectBdrySCellALL.end(); it++){
    viewer<< *it;
  } 
  
  // Displaying First surfels cut with gradient colors.;
  GradientColorMap<int> cmap_grad( 0, vectBdrySCell2.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((*(vectBdrySCell2.begin())).styleName(), "");
  viewer.setFillColor(Color(180, 200, 25, 255));
  
  int d=0;
  for( std::vector<Z3i::SCell>::iterator it=vectBdrySCell2.begin(); 
       it!= vectBdrySCell2.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, vectBdrySCell.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( std::vector<Z3i::SCell>::iterator it=vectBdrySCell.begin(); 
       it!= vectBdrySCell.end(); it++){
     Color col= cmap_grad2(d);
     viewer.setFillColor(Color(col.red(),col.green() ,col.blue(), 255));
     viewer<< *it;
    d++;
  }
  
  // On need once again to avoid superposition.
  viewer << Viewer3D::shiftSurfelVisu; 
  viewer.setFillColor(Color(18, 200, 25, 255));
  viewer << aCell ;
  viewer << Viewer3D::updateDisplay;
    
  return application.exec();
}
/**
 * Example of a test. To be completed.
 *
 */
bool testEstimatorCache(double h)
{
  unsigned int nbok = 0;
  unsigned int nb = 0;
    
  typedef ImplicitBall<Z3i::Space> ImplicitShape;
  typedef GaussDigitizer<Z3i::Space, ImplicitShape> DigitalShape;
  typedef LightImplicitDigitalSurface<Z3i::KSpace,DigitalShape> Boundary;
  typedef DigitalSurface< Boundary > MyDigitalSurface;
  typedef DepthFirstVisitor< MyDigitalSurface > Visitor;
  typedef GraphVisitorRange< Visitor > VisitorRange;
  typedef VisitorRange::ConstIterator VisitorConstIterator;

  typedef functors::IIGaussianCurvature3DFunctor<Z3i::Space> MyIICurvatureFunctor;
  typedef IntegralInvariantCovarianceEstimator< Z3i::KSpace, DigitalShape, MyIICurvatureFunctor > MyIICurvatureEstimator;
//  typedef MyIICurvatureFunctor::Value Value;

  double re = 5.0;
  double radius = 5.0;

  trace.beginBlock( "Shape initialisation ..." );

  ImplicitShape ishape( Z3i::RealPoint( 0, 0, 0 ), radius );
  DigitalShape dshape;
  dshape.attach( ishape );
  dshape.init( Z3i::RealPoint( -10.0, -10.0, -10.0 ), Z3i::RealPoint( 10.0, 10.0, 10.0 ), h );

  Z3i::KSpace K;
  if ( !K.init( dshape.getLowerBound(), dshape.getUpperBound(), true ) )
  {
    trace.error() << "Problem with Khalimsky space" << std::endl;
    return false;
  }

  Z3i::KSpace::Surfel bel = Surfaces<Z3i::KSpace>::findABel( K, dshape, 10000 );
  Boundary boundary( K, dshape, SurfelAdjacency<Z3i::KSpace::dimension>( true ), bel );
  MyDigitalSurface surf ( boundary );

  trace.endBlock();

  trace.beginBlock( "Curvature estimator computation ...");
  
  VisitorRange range( new Visitor( surf, *surf.begin() ));
  VisitorConstIterator ibegin = range.begin();
  VisitorConstIterator iend = range.end();

  MyIICurvatureFunctor curvatureFunctor;
  curvatureFunctor.init( h, re );

  MyIICurvatureEstimator curvatureEstimator( curvatureFunctor );
  curvatureEstimator.attach( K, dshape );
  curvatureEstimator.setParams( re/h );
  curvatureEstimator.init( h, ibegin, iend );

  std::vector<MyIICurvatureEstimator::Quantity> results;
  std::back_insert_iterator< std::vector<MyIICurvatureEstimator::Quantity> > itback(results);

  curvatureEstimator.eval(ibegin,iend,itback);
  trace.info() << "Number of values = "<< results.size()<<std::endl;
  trace.endBlock();

  trace.beginBlock( "Caching values ...");
  VisitorRange range2( new Visitor( surf, *surf.begin() ));
  VisitorConstIterator ibegin2 = range2.begin();
  VisitorConstIterator iend2 = range2.end();
  
  typedef EstimatorCache<MyIICurvatureEstimator> GaussianCache;

  BOOST_CONCEPT_ASSERT(( concepts::CSurfelLocalEstimator<GaussianCache> ));
    
  GaussianCache cache( curvatureEstimator );
  cache.init( h, ibegin2, iend2 );
  trace.info() << "Number of cached values = "<< cache.size()<<std::endl;

  trace.info() << "Value at begin="<< cache.eval(surf.begin())<<"  expected = "<< curvatureEstimator.eval(surf.begin())<<std::endl;
  trace.endBlock();


  trace.beginBlock( "Complete test ...");
  bool ok=true;
  for(MyDigitalSurface::ConstIterator it = surf.begin(), itend=surf.end(); it != itend; ++it)
    {
      if (  cache.eval(it) != curvatureEstimator.eval(it) )
        {
          ok=false;
          trace.error() << "Incorrect values at "<<*it<<" read " <<cache.eval(it)<< " and expecting "<<curvatureEstimator.eval(it)<<std::endl;
        }
    }
  trace.endBlock();

  trace.beginBlock( "Timing cache access ...");
  for(MyDigitalSurface::ConstIterator it = surf.begin(), itend=surf.end(); it != itend; ++it)
    {
      if (  cache.eval(it) == 12345678 ) //making sure to visit
                                             //all surfels
        {
          ok=false;
          trace.error() << "Incorrect values at "<<*it<<std::endl;
        }
    }
  trace.endBlock();

  trace.beginBlock( "Copy construction and timing cache access ...");
  GaussianCache cache2(cache);
  trace.info() << "Number of cached values = "<< cache.size()<<std::endl;
  trace.info() << "Value at begin="<< cache2.eval(surf.begin())<<"  expected = "<< curvatureEstimator.eval(surf.begin())<<std::endl;
  for(MyDigitalSurface::ConstIterator it = surf.begin(), itend=surf.end(); it != itend; ++it)
    {
      if (  cache.eval(it) == 12345678 ) //making sure to visit
                                         //all surfels
        {
          ok=false;
          trace.error() << "Incorrect values at "<<*it<<std::endl;
        }
    }
  trace.endBlock();


  
  nbok += ok ? 1 : 0; 
  nb++;
  trace.info() << "(" << nbok << "/" << nb << ") "
	       << "cache == eval" << std::endl;
  
  return nbok == nb;
}
int main( int argc, char** argv )
{
  // parse command line ----------------------------------------------
  po::options_description general_opt("Allowed options are");
  general_opt.add_options()
    ("help,h", "display this message")
    ("input,i", po::value< std::string >(), ".vol file")
    ("radius,r",  po::value< double >(), "Kernel radius for IntegralInvariant" )
    ("threshold,t",  po::value< unsigned int >()->default_value(8), "Min size of SCell boundary of an object" )
    ("minImageThreshold,l",  po::value<  int >()->default_value(0), "set the minimal image threshold to define the image object (object defined by the voxel with intensity belonging to ]minImageThreshold, maxImageThreshold ] )." )
    ("maxImageThreshold,u",  po::value<  int >()->default_value(255), "set the minimal image threshold to define the image object (object defined by the voxel with intensity belonging to ]minImageThreshold, maxImageThreshold] )." )
    ("mode,m", po::value< std::string >()->default_value("mean"), "type of output : mean, gaussian, k1, k2, prindir1, prindir2 or normal (default mean)")
    ("exportOBJ,o", po::value< std::string >(), "Export the scene to specified OBJ/MTL filename (extensions added)." )
    ("exportDAT,d", po::value<std::string>(), "Export resulting curvature (for mean, gaussian, k1 or k2 mode) in a simple data file each line representing a surfel. ")
    ("exportOnly", "Used to only export the result without the 3d Visualisation (usefull for scripts)." )
    ("imageScale,s", po::value<std::vector<double> >()->multitoken(), "scaleX, scaleY, scaleZ: re sample the source image according with a grid of size 1.0/scale (usefull to compute curvature on image defined on anisotropic grid). Set by default to 1.0 for the three axis.  ")
    ("normalization,n", "When exporting to OBJ, performs a normalization so that the geometry fits in [-1/2,1/2]^3") ;

  bool parseOK = true;
  po::variables_map vm;
  try
    {
      po::store( po::parse_command_line( argc, argv, general_opt ), vm );
    }
  catch( const std::exception & ex )
    {
      parseOK = false;
      trace.error() << " Error checking program options: " << ex.what() << std::endl;
    }
  bool neededArgsGiven=true;

  if (parseOK && !(vm.count("input"))){
    missingParam("--input");
    neededArgsGiven=false;
  }
  if (parseOK && !(vm.count("radius"))){
    missingParam("--radius");
    neededArgsGiven=false;
  }

  bool normalization = false;
  if (parseOK && vm.count("normalization"))
    normalization = true;

  std::string mode;
  if( parseOK )
    mode =  vm["mode"].as< std::string >();
  if ( parseOK && ( mode.compare("gaussian") != 0 ) && ( mode.compare("mean") != 0 ) &&
       ( mode.compare("k1") != 0 ) && ( mode.compare("k2") != 0 ) &&
       ( mode.compare("prindir1") != 0 ) && ( mode.compare("prindir2") != 0 ) && ( mode.compare("normal") != 0 ))
    {
      parseOK = false;
      trace.error() << " The selected mode ("<<mode << ") is not defined."<<std::endl;
    }

#ifndef WITH_VISU3D_QGLVIEWER
  bool enable_visu = false;
#else
  bool enable_visu = !vm.count("exportOnly"); ///<! Default QGLViewer viewer. Disabled if exportOnly is set.
#endif
  bool enable_obj = vm.count("exportOBJ"); ///<! Export to a .obj file.
  bool enable_dat = vm.count("exportDAT"); ///<! Export to a .dat file.

  if( !enable_visu && !enable_obj && !enable_dat )
    {
#ifndef WITH_VISU3D_QGLVIEWER
      trace.error() << "You should specify what you want to export with --export and/or --exportDat." << std::endl;
#else
      trace.error() << "You should specify what you want to export with --export and/or --exportDat, or remove --exportOnly." << std::endl;
#endif
      neededArgsGiven = false;
    }

  if(!neededArgsGiven || !parseOK || vm.count("help") || argc <= 1 )
    {
      trace.info()<< "Visualisation of 3d curvature from .vol file using curvature from Integral Invariant" <<std::endl
                  << general_opt << "\n"
                  << "Basic usage: "<<std::endl
                  << "\t3dCurvatureViewer -i file.vol --radius 5 --mode mean"<<std::endl
                  << std::endl
                  << "Below are the different available modes: " << std::endl
                  << "\t - \"mean\" for the mean curvature" << std::endl
                  << "\t - \"gaussian\" for the Gaussian curvature" << std::endl
                  << "\t - \"k1\" for the first principal curvature" << std::endl
                  << "\t - \"k2\" for the second principal curvature" << std::endl
                  << "\t - \"prindir1\" for the first principal curvature direction" << std::endl
                  << "\t - \"prindir2\" for the second principal curvature direction" << std::endl
                  << "\t - \"normal\" for the normal vector" << std::endl
                  << std::endl;
      return 0;
    }
  unsigned int threshold = vm["threshold"].as< unsigned int >();
  int minImageThreshold =  vm["minImageThreshold"].as<  int >();
  int maxImageThreshold =  vm["maxImageThreshold"].as<  int >();

  double h = 1.0;

  std::string export_obj_filename;
  std::string export_dat_filename;

  if( enable_obj )
    {
      export_obj_filename = vm["exportOBJ"].as< std::string >();
      if( export_obj_filename.find(".obj") == std::string::npos )
        {
          std::ostringstream oss;
          oss << export_obj_filename << ".obj" << std::endl;
          export_obj_filename = oss.str();
        }
    }


  if( enable_dat )
    {
      export_dat_filename = vm["exportDAT"].as<std::string>();
    }

  double re_convolution_kernel = vm["radius"].as< double >();


  std::vector<  double > aGridSizeReSample;
  if( vm.count( "imageScale" ))
    {
      std::vector< double> vectScale = vm["imageScale"].as<std::vector<double > >();
      if( vectScale.size() != 3 )
        {
          trace.error() << "The grid size should contains 3 elements" << std::endl;
          return 0;
        }
      else
        {
          aGridSizeReSample.push_back(1.0/vectScale.at(0));
          aGridSizeReSample.push_back(1.0/vectScale.at(1));
          aGridSizeReSample.push_back(1.0/vectScale.at(2));
        }
    }
  else
    {
      aGridSizeReSample.push_back(1.0);
      aGridSizeReSample.push_back(1.0);
      aGridSizeReSample.push_back(1.0);
    }



  // Construction of the shape from vol file
  typedef Z3i::Space::RealPoint RealPoint;
  typedef Z3i::Point Point;
  typedef ImageSelector< Z3i::Domain,  int>::Type Image;
  typedef DGtal::functors::BasicDomainSubSampler< HyperRectDomain<SpaceND<3, int> >,
                                                  DGtal::int32_t, double >   ReSampler;
  typedef DGtal::ConstImageAdapter<Image, Image::Domain, ReSampler,
                                   Image::Value,  DGtal::functors::Identity >  SamplerImageAdapter;
  typedef IntervalForegroundPredicate< SamplerImageAdapter > ImagePredicate;
  typedef BinaryPointPredicate<DomainPredicate<Image::Domain>, ImagePredicate, AndBoolFct2  > Predicate;
  typedef Z3i::KSpace KSpace;
  typedef KSpace::SCell SCell;
  typedef KSpace::Cell Cell;

  trace.beginBlock("Loading the file");
  std::string filename = vm["input"].as< std::string >();
  Image image = GenericReader<Image>::import( filename );

  PointVector<3,int> shiftVector3D( 0 ,0, 0 );
  DGtal::functors::BasicDomainSubSampler< HyperRectDomain< SpaceND< 3, int > >,
                                          DGtal::int32_t, double > reSampler(image.domain(),
                                                                             aGridSizeReSample,  shiftVector3D);
  const functors::Identity identityFunctor{};
  SamplerImageAdapter sampledImage ( image, reSampler.getSubSampledDomain(), reSampler, identityFunctor );
  ImagePredicate predicateIMG = ImagePredicate( sampledImage,  minImageThreshold, maxImageThreshold );
  DomainPredicate<Z3i::Domain> domainPredicate( sampledImage.domain() );
  AndBoolFct2 andF;
  Predicate predicate(domainPredicate, predicateIMG, andF  );


  Z3i::Domain domain =  sampledImage.domain();
  Z3i::KSpace K;
  bool space_ok = K.init( domain.lowerBound()-Z3i::Domain::Point::diagonal(),
                          domain.upperBound()+Z3i::Domain::Point::diagonal(), true );
  if (!space_ok)
    {
      trace.error() << "Error in the Khalimsky space construction."<<std::endl;
      return 2;
    }
  CanonicSCellEmbedder< KSpace > embedder( K );
  SurfelAdjacency< Z3i::KSpace::dimension > Sadj( true );
  trace.endBlock();
  // Viewer settings


  // Extraction of components
  typedef KSpace::SurfelSet SurfelSet;
  typedef SetOfSurfels< KSpace, SurfelSet > MySetOfSurfels;
  typedef DigitalSurface< MySetOfSurfels > MyDigitalSurface;

  trace.beginBlock("Extracting surfaces");
  std::vector< std::vector<SCell > > vectConnectedSCell;
  Surfaces<KSpace>::extractAllConnectedSCell(vectConnectedSCell,K, Sadj, predicate, false);
  std::ofstream outDat;
  if( enable_dat )
    {
      trace.info() << "Exporting curvature as dat file: "<< export_dat_filename <<std::endl;
      outDat.open( export_dat_filename.c_str() );
      outDat << "# data exported from 3dCurvatureViewer implementing the II curvature estimator (Coeurjolly, D.; Lachaud, J.O; Levallois, J., (2013). Integral based Curvature"
             << "  Estimators in Digital Geometry. DGCI 2013.) " << std::endl;
      outDat << "# format: surfel coordinates (in Khalimsky space) curvature: "<< mode <<  std::endl;
    }

  trace.info()<<"Number of components= "<<vectConnectedSCell.size()<<std::endl;
  trace.endBlock();

  if( vectConnectedSCell.size() == 0 )
    {
      trace.error()<< "No surface component exists. Please check the vol file threshold parameter.";
      trace.info()<<std::endl;
      exit(2);
    }

#ifdef WITH_VISU3D_QGLVIEWER
  QApplication application( argc, argv );
  typedef Viewer3D<Z3i::Space, Z3i::KSpace> Viewer;
#endif
  typedef Board3D<Z3i::Space, Z3i::KSpace> Board;

#ifdef WITH_VISU3D_QGLVIEWER
  Viewer viewer( K );
#endif
  Board board( K );

#ifdef WITH_VISU3D_QGLVIEWER
  if( enable_visu )
    {
      viewer.show();
    }
#endif

  for( unsigned int i = 0; i<vectConnectedSCell.size(); ++i )
    {
      if( vectConnectedSCell[i].size() <= threshold )
        {
          continue;
        }

      MySetOfSurfels  aSet(K, Sadj);

      for( std::vector<SCell>::const_iterator it = vectConnectedSCell.at(i).begin();
           it != vectConnectedSCell.at(i).end();
           ++it )
        {
          aSet.surfelSet().insert( *it);
        }

      MyDigitalSurface digSurf( aSet );


      typedef DepthFirstVisitor<MyDigitalSurface> Visitor;
      typedef GraphVisitorRange< Visitor > VisitorRange;
      typedef VisitorRange::ConstIterator SurfelConstIterator;
      VisitorRange range( new Visitor( digSurf, *digSurf.begin() ) );
      SurfelConstIterator abegin = range.begin();
      SurfelConstIterator aend = range.end();

      VisitorRange range2( new Visitor( digSurf, *digSurf.begin() ) );
      SurfelConstIterator abegin2 = range2.begin();

      trace.beginBlock("Curvature computation on a component");
      if( ( mode.compare("gaussian") == 0 ) || ( mode.compare("mean") == 0 )
          || ( mode.compare("k1") == 0 ) || ( mode.compare("k2") == 0 ))
        {
          typedef double Quantity;
          std::vector< Quantity > results;
          std::back_insert_iterator< std::vector< Quantity > > resultsIterator( results );
          if ( mode.compare("mean") == 0 )
            {
              typedef functors::IIMeanCurvature3DFunctor<Z3i::Space> MyIICurvatureFunctor;
              typedef IntegralInvariantVolumeEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator;

              MyIICurvatureFunctor functor;
              functor.init( h, re_convolution_kernel );

              MyIIEstimator estimator( functor );
              estimator.attach( K, predicate );
              estimator.setParams( re_convolution_kernel/h );
              estimator.init( h, abegin, aend );

              estimator.eval( abegin, aend, resultsIterator );
            }
          else if ( mode.compare("gaussian") == 0 )
            {
              typedef functors::IIGaussianCurvature3DFunctor<Z3i::Space> MyIICurvatureFunctor;
              typedef IntegralInvariantCovarianceEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator;

              MyIICurvatureFunctor functor;
              functor.init( h, re_convolution_kernel );

              MyIIEstimator estimator( functor ); estimator.attach( K,
                                                                    predicate ); estimator.setParams( re_convolution_kernel/h );
              estimator.init( h, abegin, aend );

              estimator.eval( abegin, aend, resultsIterator );
            }
          else if ( mode.compare("k1") == 0 )
            {
              typedef functors::IIFirstPrincipalCurvature3DFunctor<Z3i::Space> MyIICurvatureFunctor;
              typedef IntegralInvariantCovarianceEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator;

              MyIICurvatureFunctor functor;
              functor.init( h, re_convolution_kernel );

              MyIIEstimator estimator( functor );
              estimator.attach( K, predicate );
              estimator.setParams( re_convolution_kernel/h );
              estimator.init( h, abegin, aend );

              estimator.eval( abegin, aend, resultsIterator );
            }
          else if ( mode.compare("k2") == 0 )
            {
              typedef functors::IISecondPrincipalCurvature3DFunctor<Z3i::Space> MyIICurvatureFunctor;
              typedef IntegralInvariantCovarianceEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator;

              MyIICurvatureFunctor functor;
              functor.init( h, re_convolution_kernel );

              MyIIEstimator estimator( functor );
              estimator.attach( K, predicate );
              estimator.setParams( re_convolution_kernel/h );
              estimator.init( h, abegin, aend );

              estimator.eval( abegin, aend, resultsIterator );
            }
          trace.endBlock();


          // Drawing results
          trace.beginBlock("Visualisation");
          Quantity min = results[ 0 ];
          Quantity max = results[ 0 ];
          for ( unsigned int i = 1; i < results.size(); ++i )
            {
              if ( results[ i ] < min )
                {
                  min = results[ i ];
                }
              else if ( results[ i ] > max )
                {
                  max = results[ i ];
                }
            }
          trace.info() << "Max value= "<<max<<"  min value= "<<min<<std::endl;
          ASSERT( min <= max );
          typedef GradientColorMap< Quantity > Gradient;
          Gradient cmap_grad( min, (max==min)? max+1: max );
          cmap_grad.addColor( Color( 50, 50, 255 ) );
          cmap_grad.addColor( Color( 255, 0, 0 ) );
          cmap_grad.addColor( Color( 255, 255, 10 ) );

#ifdef WITH_VISU3D_QGLVIEWER
          if( enable_visu )
            {
              viewer << SetMode3D((*abegin2).className(), "Basic" );
            }
#endif
          if( enable_obj )
            {
              board << SetMode3D((K.unsigns(*abegin2)).className(), "Basic" );
            }


          for ( unsigned int i = 0; i < results.size(); ++i )
            {
#ifdef WITH_VISU3D_QGLVIEWER
              if( enable_visu )
                {
                  viewer << CustomColors3D( Color::Black, cmap_grad( results[ i ] ));
                  viewer << *abegin2;
                }
#endif

              if( enable_obj )
                {
                  board << CustomColors3D( Color::Black, cmap_grad( results[ i ] ));
                  board      << K.unsigns(*abegin2);
                }

              if( enable_dat )
                {
                  Point kCoords = K.uKCoords(K.unsigns(*abegin2));
                  outDat << kCoords[0] << " " << kCoords[1] << " " << kCoords[2] <<  " " <<  results[i] << std::endl;
                }

              ++abegin2;
            }
        }
      else
        {
          typedef Z3i::Space::RealVector Quantity;
          std::vector< Quantity > results;
          std::back_insert_iterator< std::vector< Quantity > > resultsIterator( results );

          if( mode.compare("prindir1") == 0 )
            {
              typedef functors::IIFirstPrincipalDirectionFunctor<Z3i::Space> MyIICurvatureFunctor;
              typedef IntegralInvariantCovarianceEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator;

              MyIICurvatureFunctor functor;
              functor.init( h, re_convolution_kernel );

              MyIIEstimator estimator( functor );
              estimator.attach( K, predicate );
              estimator.setParams( re_convolution_kernel/h );
              estimator.init( h, abegin, aend );

              estimator.eval( abegin, aend, resultsIterator );
            }
          else if( mode.compare("prindir2") == 0 )
            {
              typedef functors::IISecondPrincipalDirectionFunctor<Z3i::Space> MyIICurvatureFunctor;
              typedef IntegralInvariantCovarianceEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator;

              MyIICurvatureFunctor functor;
              functor.init( h, re_convolution_kernel );

              MyIIEstimator estimator( functor );
              estimator.attach( K, predicate );
              estimator.setParams( re_convolution_kernel/h );
              estimator.init( h, abegin, aend );

              estimator.eval( abegin, aend, resultsIterator );
            }
          else
            if( mode.compare("normal") == 0 )
              {
                typedef functors::IINormalDirectionFunctor<Z3i::Space> MyIICurvatureFunctor;
                typedef IntegralInvariantCovarianceEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator;

                MyIICurvatureFunctor functor;
                functor.init( h, re_convolution_kernel );

                MyIIEstimator estimator( functor );
                estimator.attach( K, predicate );
                estimator.setParams( re_convolution_kernel/h );
                estimator.init( h, abegin, aend );

                estimator.eval( abegin, aend, resultsIterator );
              }



          ///Visualizaton / export

#ifdef WITH_VISU3D_QGLVIEWER
          if( enable_visu )
            {
              viewer << SetMode3D(K.uCell( K.sKCoords(*abegin2) ).className(), "Basic" );
            }
#endif

          if( enable_obj )
            {
              board << SetMode3D(K.uCell( K.sKCoords(*abegin2) ).className(), "Basic" );
            }

          for ( unsigned int i = 0; i < results.size(); ++i )
            {
              DGtal::Dimension kDim = K.sOrthDir( *abegin2 );
              SCell outer = K.sIndirectIncident( *abegin2, kDim);
              if ( predicate(embedder(outer)) )
                {
                  outer = K.sDirectIncident( *abegin2, kDim);
                }

              Cell unsignedSurfel = K.uCell( K.sKCoords(*abegin2) );

#ifdef WITH_VISU3D_QGLVIEWER
              if( enable_visu )
                {
                  viewer << CustomColors3D( DGtal::Color(255,255,255,255),
                                            DGtal::Color(255,255,255,255))
                         << unsignedSurfel;
                }
#endif

              if( enable_obj )
                {
                  board << CustomColors3D( DGtal::Color(255,255,255,255),
                                           DGtal::Color(255,255,255,255))
                        << unsignedSurfel;
                }

              if( enable_dat )
                {
                  Point kCoords = K.uKCoords(K.unsigns(*abegin2));
                  outDat << kCoords[0] << " " << kCoords[1] << " " << kCoords[2] << " "
                         << results[i][0] << " " << results[i][1] << " " << results[i][2]
                         << std::endl;
                }

              RealPoint center = embedder( outer );

#ifdef WITH_VISU3D_QGLVIEWER
              if( enable_visu )
                {
                  if( mode.compare("prindir1") == 0 )
                    {
                      viewer.setLineColor( AXIS_COLOR_BLUE );
                    }
                  else if( mode.compare("prindir2") == 0 )
                    {
                      viewer.setLineColor( AXIS_COLOR_RED );
                    }
                  else if( mode.compare("normal") == 0 )
                    {
                      viewer.setLineColor( AXIS_COLOR_GREEN );
                    }


                  viewer.addLine (
                                  RealPoint(
                                            center[0] -  0.5 * results[i][0],
                                            center[1] -  0.5 * results[i][1],
                                            center[2] -  0.5 * results[i][2]
                                            ),
                                  RealPoint(
                                            center[0] +  0.5 * results[i][0],
                                            center[1] +  0.5 * results[i][1],
                                            center[2] +  0.5 * results[i][2]
                                            ),
                                  AXIS_LINESIZE );
                }
#endif

              if( enable_obj )
                {
                  if( mode.compare("prindir1") == 0 )
                    {
                      board.setFillColor( AXIS_COLOR_BLUE );
                    }
                  else if( mode.compare("prindir2") == 0 )
                    {
                      board.setFillColor( AXIS_COLOR_RED );
                    }
                  else if( mode.compare("normal") == 0 )
                    {
                      board.setFillColor( AXIS_COLOR_GREEN );
                    }

                  board.addCylinder (
                                     RealPoint(
                                               center[0] -  0.5 * results[i][0],
                                               center[1] -  0.5 * results[i][1],
                                               center[2] -  0.5 * results[i][2]),
                                     RealPoint(
                                               center[0] +  0.5 * results[i][0],
                                               center[1] +  0.5 * results[i][1],
                                               center[2] +  0.5 * results[i][2]),
                                     0.2 );
                }

              ++abegin2;
            }
        }
      trace.endBlock();
    }

#ifdef WITH_VISU3D_QGLVIEWER
  if( enable_visu )
    {
      viewer << Viewer3D<>::updateDisplay;
    }
#endif
  if( enable_obj )
    {
      trace.info()<< "Exporting object: " << export_obj_filename << " ...";
      board.saveOBJ(export_obj_filename,normalization);
      trace.info() << "[done]" << std::endl;
    }
  if( enable_dat )
    {
      outDat.close();
    }

#ifdef WITH_VISU3D_QGLVIEWER
  if( enable_visu )
    {
      return application.exec();
    }
#endif

  return 0;
}
int main( int argc, char** argv )
{
	const double h = 1;
	const double radiusBall = 12.0;
	const double radiusII = 6;
	const double trueAreaSurface = 4.0*M_PI*radiusBall*radiusBall;

	trace.beginBlock( "Make parametric shape..." );

	typedef Ball3D< Z3i::Space > Shape;

	Z3i::RealPoint center( 0.0, 0.0, 0.0 );
	Shape ball( center, radiusBall );

	trace.endBlock();

	trace.beginBlock( "Make digital shape..." );

	typedef GaussDigitizer< Z3i::Space, Shape > DigitalShape;
	typedef DigitalShape::Domain Domain;

	DigitalShape digitalBall;
	digitalBall.attach( ball );
	digitalBall.init( ball.getLowerBound() - Z3i::RealPoint( 1.0, 1.0, 1.0 ), 
					  ball.getUpperBound() + Z3i::RealPoint( 1.0, 1.0, 1.0 ),
					  h );
	Domain domain = digitalBall.getDomain();
	Z3i::KSpace kspace;
	kspace.init( domain.lowerBound(), domain.upperBound(), true );

	trace.endBlock();

	trace.beginBlock( "Make digital surface..." );

	typedef LightImplicitDigitalSurface< Z3i::KSpace, DigitalShape > LightDigitalSurface;
	typedef DigitalSurface< LightDigitalSurface > DigitalSurface;
	typedef DepthFirstVisitor< DigitalSurface > DepthFirstVisitor;
	typedef GraphVisitorRange< DepthFirstVisitor > GraphVisitorRange;
	typedef GraphVisitorRange::ConstIterator SurfelConstIterator;
	typedef Z3i::KSpace::Surfel Surfel;

	Surfel bel = Surfaces< Z3i::KSpace >::findABel( kspace, digitalBall, 500 );
	SurfelAdjacency< Z3i::KSpace::dimension > surfelAdjacency( true );
	LightDigitalSurface lightDigitalSurface( kspace, digitalBall, surfelAdjacency, bel );
	DigitalSurface digitalSurface( lightDigitalSurface );

	GraphVisitorRange graphVisitorRange( new DepthFirstVisitor( digitalSurface, *digitalSurface.begin() ) );
	SurfelConstIterator sbegin = graphVisitorRange.begin();
    SurfelConstIterator send = graphVisitorRange.end();
    std::vector< Surfel > v_border;
    while( sbegin != send )
    {
    	v_border.push_back( *sbegin );
    	++sbegin;
    }

	trace.endBlock();

	trace.beginBlock( "Computation with normal estimation ..." );

	typedef IIGeometricFunctors::IINormalDirectionFunctor< Z3i::Space > NormalFunctor;
	typedef IntegralInvariantCovarianceEstimator< Z3i::KSpace, DigitalShape, NormalFunctor > IINormalEstimator;

	NormalFunctor normalFunctor;
	IINormalEstimator normalEstimator( normalFunctor );
	normalEstimator.attach( kspace, digitalBall );
	normalEstimator.setParams( radiusII / h );
	normalEstimator.init( h, v_border.begin(), v_border.end() );

	double areaSurfaceEstimated = 0.0;

	for( unsigned int i_position = 0; i_position < v_border.size(); ++i_position )
	{
		Z3i::RealPoint normalEstimated = normalEstimator.eval( &(v_border[i_position]) );
		Z3i::RealPoint normalSurfel = kspace.sKCoords( kspace.sDirectIncident( v_border[i_position], kspace.sOrthDir( v_border[i_position] ))) - kspace.sKCoords( v_border[i_position] ); 
		normalEstimated = normalEstimated.getNormalized();
		areaSurfaceEstimated += std::abs( normalEstimated.dot( normalSurfel )) * h * h;
	}

	trace.endBlock();

	trace.info() << "Area Surface estimated : " << areaSurfaceEstimated << std::endl;
	trace.info() << "True areaSurface : " << trueAreaSurface << std::endl;
	trace.info() << "Ratio : " << areaSurfaceEstimated / trueAreaSurface << std::endl;

	return 0;
}
Beispiel #7
0
int main( int narg, char **argv )
{
	trace.beginBlock("Identifying the domain.");
	Z3i::Domain domain = scene_dimensions( argv[1] ) ;
	if ( domain.lowerBound() == domain.upperBound() ) {
		trace.error()<<"Invalid domain ("<<__FILE__<<")"<<std::endl;
		return -1 ;
	}
	trace.endBlock() ;
	trace.beginBlock("Reading slices.");
	Z3i::DigitalSet set3d( domain ) ;
	
	SetPredicate<Z3i::DigitalSet> set3dPredicate( set3d ) ;
	for ( uint depth = 0 ; depth < domain.upperBound().at(2) ; depth++ )
		process_slice( argv[1], depth, set3d ) ;
	trace.endBlock() ;

	if ( 0) {
		try {
			Gray3DImage aImage( domain );
			for ( Z3i::Domain::ConstIterator pt = domain.begin() ; pt != domain.end() ; pt++ )
				aImage.setValue( (*pt), 255 ) ;
			boost::filesystem::path pathvolname = argv[1] ;
			pathvolname /= "obj.vol" ;
			if ( ! DGtal::VolWriter< Gray3DImage, GrayColorMap >::exportVol ( pathvolname.string(), aImage, 0, 255 ) )
			{
				trace.error() <<"Can not export data (generated 3D object)"<<std::endl;
				return -4 ;
			} else {
				trace.info()<<"export data to "<<pathvolname.string()<<std::endl;
			}
			pathvolname = argv[1] ;
			pathvolname /= "obj.pgm3d" ;
			if ( ! PNMWriter<Gray3DImage, GrayColorMap >::exportPGM3D( pathvolname.string(), aImage, 0, 255 ) )
			{
				trace.error() <<"Can not export data (generated 3D object)"<<std::endl;
				return -4 ;
			} else {
				trace.info()<<"export data to "<<pathvolname.string()<<std::endl;
			}
			
		} catch ( std::exception &e ) {
			trace.error() <<"Can not export data (generated 3D object) "<<e.what()<<std::endl;
			return -8 ;
		}
	}

	trace.beginBlock( "Decompose the object into connected components." );
	{
		DGtal::Z3i::Object6_18 scene( DGtal::Z3i::dt6_18, set3d ) ;
		std::vector< Z3i::Object6_18 > v_obj ;
		back_insert_iterator< std::vector< Z3i::Object6_18 > > it( v_obj ) ;
		scene.writeComponents( it ) ;
		boost::filesystem::path scenefilename = argv[1] ;
		scenefilename /= "scene.pgm3d" ;
		IOPgm3d::write( v_obj, scenefilename.string().c_str() ) ;
	}
	trace.endBlock( );

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

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

	trace.beginBlock( "Extracting boundary by tracking from an initial bel." );
	Z3i::KSpace::SCellSet boundary;
	Z3i::SCell bel = Surfaces<Z3i::KSpace>::findABel( ks, set3dPredicate, 100000 );
	Surfaces<Z3i::KSpace>::trackBoundary( boundary, ks, surfAdj, set3dPredicate, bel );
	trace.endBlock();

	trace.beginBlock( "Displaying surface in Viewer3D." );
	QApplication application(narg,argv);
	Viewer3D viewer;
	viewer.show();
	viewer 	<< SetMode3D( boundary.begin()->className(), "") ; //CustomColors3D(Color(250, 0, 0 ), Color( 128, 128, 128 ) );
	unsigned long nbSurfels = 0;
	for ( Z3i::KSpace::SCellSet::const_iterator it = boundary.begin(), it_end = boundary.end(); it != it_end; ++it, ++nbSurfels )
	
			viewer << ks.uCell( Z3i::Point( (*it).myCoordinates.at(0), (*it).myCoordinates.at(1), (*it).myCoordinates.at(2) ) ) ;
	
	/**
	for ( Z3i::KSpace::SCellSet::const_iterator it = boundary.begin(), it_end = boundary.end(); it != it_end; ++it, ++nbSurfels )
		viewer << (*it) ;
	*/
	trace.info() << *boundary.begin()<<std::endl;
	viewer << Viewer3D::updateDisplay;
	trace.info() << "nb surfels = " << nbSurfels << std::endl;
	trace.endBlock();
	return application.exec();
}
int main( int argc, char** argv )
{
    if ( argc != 4 )
    {
        trace.error() << "Usage: " << argv[0]
                               << " <fileName.vol> <threshold> <re_convolution_kernel>" << std::endl;
        trace.error() << "Example : "<< argv[0] << " Al.150.vol 0 7.39247665" << std::endl;
        return 0;
    }

    trace.beginBlock ( "Example IntegralInvariantCurvature3D" );
    trace.info() << "Args:";
    for ( int i = 0; i < argc; ++i )
        trace.info() << " " << argv[ i ];
    trace.info() << endl;

    double h = 1.0;
    unsigned int threshold = atoi( argv[ 2 ] );

    /// Construction of the shape from vol file
    typedef ImageSelector< Z3i::Domain, unsigned int >::Type Image;
    typedef SimpleThresholdForegroundPredicate< Image > ImagePredicate;
    typedef Z3i::KSpace::Surfel Surfel;
    typedef LightImplicitDigitalSurface< Z3i::KSpace, ImagePredicate > MyLightImplicitDigitalSurface;
    typedef DigitalSurface< MyLightImplicitDigitalSurface > MyDigitalSurface;

    std::string filename = argv[1];
    Image image = VolReader<Image>::importVol( filename );
    ImagePredicate predicate = ImagePredicate( image, threshold );

    Z3i::Domain domain = image.domain();

    Z3i::KSpace KSpaceShape;

    bool space_ok = KSpaceShape.init( domain.lowerBound(), domain.upperBound(), true );
    if (!space_ok)
    {
      trace.error() << "Error in the Khalimsky space construction."<<std::endl;
      return 2;
    }

    SurfelAdjacency< Z3i::KSpace::dimension > SAdj( true );
    Surfel bel = Surfaces< Z3i::KSpace >::findABel( KSpaceShape, predicate, 100000 );
    MyLightImplicitDigitalSurface LightImplDigSurf( KSpaceShape, predicate, SAdj, bel );
    MyDigitalSurface digSurf( LightImplDigSurf );

    typedef DepthFirstVisitor< MyDigitalSurface > Visitor;
    typedef GraphVisitorRange< Visitor > VisitorRange;
    typedef VisitorRange::ConstIterator SurfelConstIterator;

    VisitorRange range( new Visitor( digSurf, *digSurf.begin() ) );
    SurfelConstIterator abegin = range.begin();
    SurfelConstIterator aend = range.end();

    typedef ImageToConstantFunctor< Image, ImagePredicate > MyPointFunctor;
    MyPointFunctor pointFunctor( &image, &predicate, 1 );

    /// Integral Invariant stuff
    //! [IntegralInvariantUsage]
    double re_convolution_kernel = atof(argv[3]);

    typedef FunctorOnCells< MyPointFunctor, Z3i::KSpace > MyCellFunctor;
    typedef IntegralInvariantGaussianCurvatureEstimator< Z3i::KSpace, MyCellFunctor > MyCurvatureEstimator; // Gaussian curvature estimator

    MyCellFunctor functor ( pointFunctor, KSpaceShape ); // Creation of a functor on Cells, returning true if the cell is inside the shape
    MyCurvatureEstimator estimator ( KSpaceShape, functor );
    estimator.init( h, re_convolution_kernel ); // Initialisation for a given Euclidean radius of convolution kernel
    std::vector< double > results;
    back_insert_iterator< std::vector< double > > resultsIterator( results ); // output iterator for results of Integral Invariante curvature computation
    estimator.eval ( abegin, aend, resultsIterator ); // Computation
    //! [IntegralInvariantUsage]

    /// Drawing results
    typedef MyCurvatureEstimator::Quantity Quantity;
    Quantity min = numeric_limits < Quantity >::max();
    Quantity max = numeric_limits < Quantity >::min();
    for ( unsigned int i = 0; i < results.size(); ++i )
    {
        if ( results[ i ] < min )
        {
            min = results[ i ];
        }
        else if ( results[ i ] > max )
        {
            max = results[ i ];
        }
    }

    QApplication application( argc, argv );
    Viewer3D<> viewer;
    viewer.show();

    typedef GradientColorMap< Quantity > Gradient;
    Gradient cmap_grad( min, max );
    cmap_grad.addColor( Color( 50, 50, 255 ) );
    cmap_grad.addColor( Color( 255, 0, 0 ) );
    cmap_grad.addColor( Color( 255, 255, 10 ) );

    VisitorRange range2( new Visitor( digSurf, *digSurf.begin() ) );
    abegin = range2.begin();

    for ( unsigned int i = 0; i < results.size(); ++i )
    {
        viewer << CustomColors3D( Color::Black, cmap_grad( results[ i ] ))
               << *abegin;
        ++abegin;
    }

    viewer << Viewer3D<>::updateDisplay;

    trace.endBlock();
    return application.exec();
}
int main( int argc, char** argv )
{

  typedef PointVector<4, double> Point4D;
  typedef PointVector<1, int> Point1D;
    
  // parse command line ----------------------------------------------
  po::options_description general_opt("Allowed options are: ");
  general_opt.add_options()
    ("help,h", "display this message")
    ("input,i", po::value<std::string>(), "input file: sdp (sequence of discrete points with attribute)" )
    ("noWindows,n", "Don't display Viewer windows." )
    ("doSnapShotAndExit,d", po::value<std::string>(), "save display snapshot into file." )
    ("fixMaxColorValue", po::value<double>(), "fix the maximal color value for the scale error display (else the scale is set from the maximal value)" )
    ("fixMinColorValue", po::value<double>(), "fix the minimal color value for the scale error display (else the scale is set from the minimal value)" )
    ("labelIndex", po::value<unsigned int>(), "set the index of the label (by default set to 3)  " ) 
    ("SDPindex", po::value<std::vector <unsigned int> >()->multitoken(), "specify the sdp index (by default 0,1,2).");


  bool parseOK=true;
  bool cannotStart= false;
  po::variables_map vm;


  try{
    po::store(po::parse_command_line(argc, argv, general_opt), vm);  
  }catch(const std::exception& ex){
    parseOK=false;
    trace.error()<< "Error checking program options: "<< ex.what()<< endl;
  }
  po::notify(vm);    
  if(parseOK && ! vm.count("input"))
    {
      trace.error() << " The input file name was not defined" << endl;      
      cannotStart = true;
    }
   
  
  if( !parseOK || cannotStart ||  vm.count("help")||argc<=1)
    {
      trace.info() << "Usage: " << argv[0] << " [input]\n"
		<< "Display surfel data from SDP file with color attributes given as scalar interpreted as color."
		<< general_opt << "\n";
      return 0;
    }
  Z3i::KSpace K;
  string inputFilename = vm["input"].as<std::string>();

  
  std::vector<Point4D> surfelAndScalarInput;
  

  
  if(vm.count("SDPindex")) {
    std::vector<unsigned int > vectIndex = vm["SDPindex"].as<std::vector<unsigned int > >();
    if(vectIndex.size()!=4){
      trace.error() << "you need to specify the three indexes of vertex." << std::endl; 
      return 0;
    }
    surfelAndScalarInput = PointListReader<Point4D>::getPointsFromFile(inputFilename, vectIndex);
  }else{
    surfelAndScalarInput = PointListReader<Point4D>::getPointsFromFile(inputFilename);
  }  
  
  
  Point4D ptLower = surfelAndScalarInput.at(0);
  Point4D ptUpper = surfelAndScalarInput.at(0);
  getBoundingUpperAndLowerPoint(surfelAndScalarInput,  ptLower, ptUpper);
  
  
  K.init(Z3i::Point(2*ptLower[0]+1, 2*ptLower[1]+1, 2*ptLower[2]+1),
         Z3i::Point(2*ptUpper[0]+1, 2*ptUpper[1]+1, 2*ptUpper[2]+1), true);
  
  
  std::vector<Cell> vectSurfelsInput; 
  
  // Construction of the set of surfels
  for(unsigned int i =0; i<surfelAndScalarInput.size(); i++){
    Point4D pt4d = surfelAndScalarInput.at(i);
    Cell c = K.uCell(Z3i::Point(pt4d[0], pt4d[1], pt4d[2])); 
    vectSurfelsInput.push_back(c);
  }
  
    
  CanonicCellEmbedder<KSpace> embeder(K);
  std::vector<unsigned int> vectIndexMinToReference;
  
  
  //-------------------------
  // Displaying input with color given from scalar values
  
  QApplication application(argc,argv);
  typedef ViewerSnap<> Viewer;
   
  Viewer viewer(K, vm.count("doSnapShotAndExit"));
  if(vm.count("doSnapShotAndExit")){
    viewer.setSnapshotFileName(QString(vm["doSnapShotAndExit"].as<std::string>().c_str()));
  }
  viewer.setWindowTitle("3dCompSurfel Viewer");
  viewer.show();
  viewer.restoreStateFromFile();
    
  double minScalarVal=surfelAndScalarInput.at(0)[3];
  double maxScalarVal=surfelAndScalarInput.at(0)[3];

  for(unsigned int i=1; i <surfelAndScalarInput.size(); i++){
    double scalVal = surfelAndScalarInput.at(i)[3];
    if(scalVal < minScalarVal){
      minScalarVal = scalVal;
    }
    if(scalVal > maxScalarVal){
      maxScalarVal = scalVal;
    }
  }
  if(vm.count("fixMaxColorValue")){
    maxScalarVal = vm["fixMaxColorValue"].as<double>();
  }
  if(vm.count("fixMinColorValue")){
    minScalarVal = vm["fixMinColorValue"].as<double>();
  }  
  
  GradientColorMap<double> gradientColorMap( minScalarVal, maxScalarVal );
  gradientColorMap.addColor( Color(255,0,0,100 ) );
  gradientColorMap.addColor( Color(0,255,0,100 ) );
  gradientColorMap.addColor( Color(0,0,255,100 ) );

  bool useGrad = minScalarVal!=maxScalarVal;

  viewer << SetMode3D(vectSurfelsInput.at(0).className(), "Basic");
  for(unsigned int i=0; i <surfelAndScalarInput.size(); i++){
    double valInput = surfelAndScalarInput.at(i)[3];
    if(useGrad){
      viewer.setFillColor(gradientColorMap(valInput));
    }else{
      viewer.setFillColor(Color::White);
    }
    viewer << vectSurfelsInput.at(i);     
  }
  
  
  
  viewer << Viewer::updateDisplay;
  if(vm.count("doSnapShotAndExit")){
    // Appy cleaning just save the last snap
    std::string name = vm["doSnapShotAndExit"].as<std::string>();
    std::string extension = name.substr(name.find_last_of(".") + 1);
    std::string basename = name.substr(0, name.find_last_of("."));
    for(int i=0; i< viewer.snapshotCounter()-1; i++){
      std::stringstream s; 
      s << basename << "-"<< setfill('0') << setw(4)<<  i << "." << extension; 
      trace.info() << "erase temp file: " << s.str() << std::endl;
      remove(s.str().c_str());
    }
    std::stringstream s; 
    s << basename << "-"<< setfill('0') << setw(4)<<  viewer.snapshotCounter()-1 << "." << extension;
    rename(s.str().c_str(), name.c_str()); 
    return 0;
  }
  
  if(vm.count("noWindows")){
    return 0;
  }else{
    return application.exec();
  }
}
int main(int argc, char** argv)
{


  QApplication application(argc,argv);


  Point ptL(-1, -1, -1);
  Point ptU(3, 3, 1);
  Domain d (ptL, ptU);    
    
  Point pt0(0,0, 0);
  Point pt1(1,0,0 );
  Point pt2(0,1,0 );
  Point pt3(2,1,0);
  Point pt4(1,2,0);
  Point pt5(2,2,0);
  

  DigitalSet aSet( d );
  aSet.insert(pt0);
  aSet.insert(pt1);
  aSet.insert(pt2);
  aSet.insert(pt3);
  aSet.insert(pt4);



  std::set<SCell> bdry;
  Z3i::KSpace ks;  
  ks.init( ptL, ptU, true );
 

  SCell v0 = ks.sSpel(pt0, KSpace::POS);
  SCell v1 = ks.sSpel(pt1, KSpace::POS);
  SCell v2 = ks.sSpel(pt2, KSpace::POS);
  SCell v3 = ks.sSpel(pt3, KSpace::POS);
  SCell v4 = ks.sSpel(pt4, KSpace::POS);



  Viewer3D viewerAdjSRC;
  viewerAdjSRC.show();
  viewerAdjSRC << d;
  viewerAdjSRC << SetMode3D( v0.className(), "Illustration" );
  viewerAdjSRC << pt0 << pt1 << pt2 << pt3 << pt4;



  Viewer3D viewerAdj;
  viewerAdj.show();

  viewerAdj << SetMode3D( v0.className(), "Illustration" );
  viewerAdj << v0 << v1 << v2 << v3 << v4;

  Viewer3D viewerAdj2;
  viewerAdj2.show();



  
  // Extracting the surface boundary of the shape
  Surfaces<Z3i::KSpace>::sMakeBoundary( bdry, ks, aSet, ks.lowerBound(), ks.upperBound() );

  SurfelAdjacency<Z3i::KSpace::dimension>  sAdjInt( true );
  SurfelAdjacency<Z3i::KSpace::dimension>  sAdjExt( false );
  
  viewerAdj << SetMode3D( v0.className(), "Illustration" );
  viewerAdj << v0 << v1 << v2 << v3 << v4;

  //Displaying the boundary bels
  std::set<SCell>::iterator itBoundary;
  int i=0;


  for(itBoundary= bdry.begin(); itBoundary!= bdry.end(); itBoundary++){
    viewerAdj << *itBoundary;
  }
  
  viewerAdj2 << SetMode3D( v0.className(), "Illustration" );
  viewerAdj2 << v0 << v1 << v2 << v3 << v4;

  itBoundary = bdry.begin();
  for (int i =0; i<17; i++) itBoundary++;
  SCell surfel = *itBoundary;
  
  // Defining surfel Neighborhood given an surfel Adjacency
  SurfelNeighborhood<KSpace> sNeighInt;
  sNeighInt.init( &ks, &sAdjInt, surfel );
  
  SurfelNeighborhood<KSpace> sNeighExt;
  sNeighExt.init( &ks, &sAdjExt, surfel );
  
  
  SCell surfelFollowerInt;
  SCell surfelFollowerExt;

  sNeighInt.getAdjacentOnDigitalSet ( surfelFollowerInt, aSet, *(ks.sDirs(surfel)), true);
  sNeighExt.getAdjacentOnDigitalSet ( surfelFollowerExt, aSet, *(ks.sDirs(surfel)), true);

  viewerAdj2 <<  CustomColors3D(Color(220, 220,255),Color(220, 220,255));
  viewerAdj2 << surfel;
  
  viewerAdj2 <<  CustomColors3D(Color(250, 0,0),Color(250, 0,0));

  viewerAdj2 << surfelFollowerInt;
  viewerAdj2 <<  CustomColors3D(Color(0, 250,0),Color(0, 250,0));
  viewerAdj2 << surfelFollowerExt;
  


  // Extraction of contour
  std::set<SCell> aContour1;
  Surfaces<Z3i::KSpace>::trackBoundary( aContour1, ks, 
  					sAdjExt,
  					aSet, surfel ); 


  Viewer3D viewerContour1;
  viewerContour1.show();

  viewerContour1 << SetMode3D( v0.className(), "Illustration" );
  viewerContour1 << v0 << v1 << v2 << v3 << v4;
	    

  std::set<SCell>::iterator iterOnContour;
  for( iterOnContour= aContour1.begin(); iterOnContour != aContour1.end(); iterOnContour++){
    if(*iterOnContour != surfel){
      viewerContour1 <<  CustomColors3D(Color(0, 250,0),Color(0, 250,0));
      viewerContour1<< *iterOnContour;
    }else{
				 
      viewerContour1 <<  CustomColors3D(Color(220, 220,255),Color(220, 220,255));
      viewerContour1<< *iterOnContour;
    }
  }
  



  // Extraction of contour
  std::set<SCell> aContour2;
  Surfaces<Z3i::KSpace>::trackBoundary( aContour2, ks, 
  					sAdjInt,
  					aSet, surfel ); 

  Viewer3D viewerContour2;


  viewerContour2.show();
  viewerContour2 << SetMode3D( v0.className(), "Illustration" );
  viewerContour2 << v0 << v1 << v2 << v3 << v4;


  std::set<SCell>::iterator iterOnContour2;
  for( iterOnContour2= aContour2.begin(); iterOnContour2 != aContour2.end(); iterOnContour2++){
    if(*iterOnContour2 != surfel){
      viewerContour2 <<  CustomColors3D(Color(250, 0,0),Color(250, 0,0));
      viewerContour2<< *iterOnContour2;
    }else{
      
      viewerContour2 <<  CustomColors3D(Color(220, 220,255),Color(220, 220,255));
      viewerContour2<< *iterOnContour2;
    }
  }
  
  viewerAdjSRC << Viewer3D:: updateDisplay;  
  viewerAdj<< Viewer3D::updateDisplay;
  viewerAdj2<< Viewer3D::updateDisplay;
  viewerContour1 << Viewer3D::updateDisplay;
  viewerContour2 << Viewer3D::updateDisplay;

 
  return application.exec();


  return 0;
}