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; }
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; }
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 }
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] }
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(); }