Beispiel #1
0
int main( int argc, char** argv )
{
  if ( argc < 5 )
    {
      usage( argc, argv );
      return 1;
    }
  std::string inputFilename = argv[ 1 ];
  unsigned int minThreshold = atoi( argv[ 2 ] );
  unsigned int maxThreshold = atoi( argv[ 3 ] );
  bool intAdjacency = atoi( argv[ 4 ] ) == 0;

  //! [volMarchingCubes-readVol]
  trace.beginBlock( "Reading vol file into an image." );
  typedef ImageSelector < Domain, int>::Type Image;
  Image image = VolReader<Image>::importVol(inputFilename);
  DigitalSet set3d (image.domain());
  SetFromImage<DigitalSet>::append<Image>(set3d, image,
                                          minThreshold, maxThreshold);
  trace.endBlock();
  //! [volMarchingCubes-readVol]


  //! [volMarchingCubes-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();
  //! [volMarchingCubes-KSpace]

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

  //! [volMarchingCubes-ExtractingSurface]
  trace.beginBlock( "Extracting boundary by scanning the space. " );
  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() << "Digital surface has " << digSurf.size() << " surfels."
               << std::endl;
  trace.endBlock();
  //! [volMarchingCubes-ExtractingSurface]

  //! [volMarchingCubes-makingOFF]
  trace.beginBlock( "Making OFF surface <marching-cube.off>. " );
  typedef CanonicEmbedder< Space > MyEmbedder;
  typedef
    ImageLinearCellEmbedder< KSpace, Image, MyEmbedder > CellEmbedder;
  CellEmbedder cellEmbedder;
  MyEmbedder trivialEmbedder;
  // The +0.5 is to avoid isosurface going exactly through a voxel
  // center, especially for binary volumes.
  cellEmbedder.init( ks, image, trivialEmbedder, 
                     ( (double) minThreshold ) + 0.5 );
  ofstream out( "marching-cube.off" );
  if ( out.good() )
    digSurf.exportEmbeddedSurfaceAs3DOFF( out, cellEmbedder );
  out.close();
  trace.endBlock();
  //! [volMarchingCubes-makingOFF]
  return 0;
}
Beispiel #2
0
int main( int argc, char** argv )
{
  if ( argc < 5 )
    {
      usage( argc, argv );
      return 1;
    }
  std::string inputFilename = argv[ 1 ];
  unsigned int minThreshold = atoi( argv[ 2 ] );
  unsigned int maxThreshold = atoi( argv[ 3 ] );
  bool intAdjacency = atoi( argv[ 4 ] ) == 0;

  typedef ImageSelector < Domain, int>::Type Image;
      
  //! [viewMarchingCubes-readVol]
  trace.beginBlock( "Reading vol file into an image." );
  Image image = VolReader<Image>::importVol(inputFilename);
  DigitalSet set3d (image.domain());
  SetFromImage<DigitalSet>::append<Image>(set3d, image,
                                          minThreshold, maxThreshold);
  trace.endBlock();
  //! [viewMarchingCubes-readVol]


  //! [viewMarchingCubes-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();
  //! [viewMarchingCubes-KSpace]

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

  //! [viewMarchingCubes-ExtractingSurface]
  trace.beginBlock( "Extracting boundary by scanning the space. " );
  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() << "Digital surface has " << digSurf.size() << " surfels."
               << std::endl;
  trace.endBlock();
  //! [viewMarchingCubes-ExtractingSurface]

  //! [viewMarchingCubes-makingMesh]
  trace.beginBlock( "Making triangulated surface. " );
  typedef CanonicEmbedder< Space >                                  TrivialEmbedder;
  typedef ImageLinearCellEmbedder< KSpace, Image, TrivialEmbedder > CellEmbedder;
  typedef CellEmbedder::Value                                       RealPoint;
  typedef TriangulatedSurface< RealPoint >                          TriMesh;
  typedef Mesh< RealPoint >                                         ViewMesh;
  typedef std::map< MyDigitalSurface::Vertex, TriMesh::Index >      VertexMap;
  TriMesh         trimesh;
  ViewMesh        viewmesh;
  TrivialEmbedder trivialEmbedder;
  CellEmbedder    cellEmbedder;
  // The +0.5 is to avoid isosurface going exactly through a voxel
  // center, especially for binary volumes.
  cellEmbedder.init( ks, image, trivialEmbedder, 
                     ( (double) minThreshold ) + 0.5 );
  VertexMap vmap; // stores the map Vertex -> Index
  MeshHelpers::digitalSurface2DualTriangulatedSurface
    ( digSurf, cellEmbedder, trimesh, vmap );
  trace.info() << "Triangulated surface is " << trimesh << std::endl;
  MeshHelpers::triangulatedSurface2Mesh( trimesh, viewmesh );
  trace.info() << "Mesh has " << viewmesh.nbVertex()
               << " vertices and " << viewmesh.nbFaces() << " faces." << std::endl;
  trace.endBlock();
  //! [viewMarchingCubes-makingMesh]

  QApplication application(argc,argv);
  Viewer3D<> viewer;
  viewer.show();
  viewer.setLineColor(Color(150,0,0,254));
  viewer << viewmesh;
  viewer << Viewer3D<>::updateDisplay;
  application.exec();
  
}
int main( int argc, char** argv )
{
  //! [3dVolMarchingCubes-parseCommandLine]
  // 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>(), "the volume file (.vol)" )
    ("threshold,t",  po::value<unsigned int>()->default_value(1), "the value that defines the isosurface in the image (an integer between 0 and 255)." )
    ("adjacency,a",  po::value<unsigned int>()->default_value(0), "0: interior adjacency, 1: exterior adjacency")
    ("output,o",  po::value<std::string>()->default_value( "marching-cubes.off" ), "the output OFF file that represents the geometry of the isosurface") ;
  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.info()<< "Error checking program options: "<< ex.what()<< std::endl;
  }
  po::notify(vm);
  if ( !parseOK || vm.count("help") || ( argc <= 1 ) )
    {
      std::cout << "Usage: " << argv[0]
                << " [-i <fileName.vol>] [-t <threshold>] [-a <adjacency>] [-o <output.off>]" << std::endl
                << "Outputs the isosurface of value <threshold> of the volume <fileName.vol>  as an OFF file <output.off>. The <adjacency> (0/1) allows to choose between interior (6,18) and exterior (18,6) adjacency." << std::endl
                << general_opt << std::endl;
      return 0;
    }
  if ( ! vm.count("input") )
    {
      trace.error() << "The input file name was defined." << std::endl;
      return 1;
    }
  std::string inputFilename = vm["input"].as<std::string>();
  unsigned int threshold = vm["threshold"].as<unsigned int>();
  bool intAdjacency = ( vm["adjacency"].as<unsigned int>() == 0 );
  std::string outputFilename = vm["output"].as<std::string>();
  //! [3dVolMarchingCubes-parseCommandLine]

  //! [3dVolMarchingCubes-readVol]
  trace.beginBlock( "Reading vol file into an image." );
  typedef ImageSelector < Domain, int>::Type Image;
  Image image = VolReader<Image>::importVol(inputFilename);

  typedef functors::SimpleThresholdForegroundPredicate<Image> ThresholdedImage;
  ThresholdedImage thresholdedImage( image, threshold );
  // DigitalSet set3d (image.domain());
  // SetFromImage<DigitalSet>::append<Image>(set3d, image,
  //                                         threshold, 255 );
  trace.endBlock();
  //! [3dVolMarchingCubes-readVol]

  //! [3dVolMarchingCubes-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();
  //! [3dVolMarchingCubes-KSpace]

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

  //! [3dVolMarchingCubes-ExtractingSurface]
  trace.beginBlock( "Extracting boundary by scanning the space. " );
  typedef KSpace::SurfelSet SurfelSet;
  typedef SetOfSurfels< KSpace, SurfelSet > MySetOfSurfels;
  typedef DigitalSurface< MySetOfSurfels > MyDigitalSurface;
  MySetOfSurfels theSetOfSurfels( ks, surfAdj );
  Surfaces<KSpace>::sMakeBoundary( theSetOfSurfels.surfelSet(),
                                   ks, thresholdedImage,
                                   image.domain().lowerBound(),
                                   image.domain().upperBound() );
  MyDigitalSurface digSurf( theSetOfSurfels );
  trace.info() << "Digital surface has " << digSurf.size() << " surfels."
               << std::endl;
  trace.endBlock();
  //! [3dVolMarchingCubes-ExtractingSurface]

  //! [3dVolMarchingCubes-makingOFF]
  trace.beginBlock( "Making OFF surface. " );
  // Describes how voxels are embedded into Euclidean space.
  typedef CanonicEmbedder< Space > MyEmbedder; 
  // Describes how the centroid surface elements is placed in-between embedded voxels.
  typedef ImageLinearCellEmbedder< KSpace, Image, MyEmbedder > CellEmbedder;
  CellEmbedder cellEmbedder;
  MyEmbedder trivialEmbedder;
  cellEmbedder.init( ks, image, trivialEmbedder, threshold );
  std::ofstream out( outputFilename.c_str() );
  if ( out.good() )
    digSurf.exportEmbeddedSurfaceAs3DOFF( out, cellEmbedder );
  out.close();
  trace.endBlock();
  //! [3dVolMarchingCubes-makingOFF]
  return 0;
}