125{
126 if ( argc <= 1 )
127 {
128 usage( argc, argv );
129 return 0;
130 }
132 using namespace DGtal;
140
141 std::string input = argv[ 1 ];
142 const double R = argc > 2 ? atof( argv[ 2 ] ) : 2.0;
143 const int m = argc > 3 ? atoi( argv[ 3 ] ) : 0;
144 const int M = argc > 4 ? atoi( argv[ 4 ] ) : 1;
145 const double Kmax = argc > 5 ? atof( argv[ 5 ] ) : 0.33;
146
148
149 auto params = SH::defaultParameters() | SHG::defaultParameters();
150 params( "thresholdMin", m )( "thresholdMax", M )( "closed", 1);
151 params( "t-ring", 3 )( "surfaceTraversal", "Default" );
152 auto bimage = SH::makeBinaryImage( input.c_str(), params );
153 if ( bimage == nullptr )
154 {
155 trace.
error() <<
"Unable to read file <" << input.c_str() <<
">" << std::endl;
156 return 1;
157 }
158 auto K = SH::getKSpace( bimage, params );
159 auto sembedder = SH::getSCellEmbedder(
K );
160 auto embedder = SH::getCellEmbedder(
K );
161 auto surface = SH::makeDigitalSurface( bimage,
K, params );
162 auto surfels = SH::getSurfelRange( surface, params );
163 trace.
info() <<
"- surface has " << surfels.size()<<
" surfels." << std::endl;
165
167 SM smesh;
168 std::vector< SM::Vertices > faces;
169 SH::Cell2Index c2i;
170 auto pointels = SH::getPointelRange( c2i, surface );
171 auto vertices = SH::RealPoints( pointels.size() );
172 std::transform( pointels.cbegin(), pointels.cend(),
vertices.begin(),
173 [&] (const SH::Cell& c) { return embedder( c ); } );
174 for ( auto&& surfel : *surface )
175 {
176 const auto primal_surfel_vtcs = SH::getPointelRange(
K, surfel );
177 SM::Vertices face;
178 for ( auto&& primal_vtx : primal_surfel_vtcs )
179 face.push_back( c2i[ primal_vtx ] );
180 faces.push_back( face );
181 }
183 faces.cbegin(), faces.cend() );
186
188
189 CNC cnc( smesh );
190
191 auto face_normals = SHG::getCTrivialNormalVectors( surface, surfels, params );
192 smesh.setFaceNormals( face_normals.cbegin(), face_normals.cend() );
193 if ( smesh.vertexNormals().empty() )
194 smesh.computeVertexNormalsFromFaceNormals();
195
196 auto mu0 = cnc.computeMu0();
197 auto muXY = cnc.computeMuXY();
199
201
202
203 std::vector< double > K1( smesh.nbFaces() );
204 std::vector< double >
K2( smesh.nbFaces() );
205 std::vector< RealVector > D1( smesh.nbFaces() );
206 std::vector< RealVector > D2( smesh.nbFaces() );
207 for ( auto f = 0; f < smesh.nbFaces(); ++f )
208 {
209 const auto b = smesh.faceCentroid( f );
210 const auto N = smesh.faceNormals()[ f ];
211 const auto area = mu0 .measure( b, R, f );
212 const auto M = muXY.measure( b, R, f );
213 std::tie( K1[ f ], K2[ f ], D1[ f ], D2[ f ] )
214 = cnc.principalCurvatures( area, M, N );
215 }
217
219 auto K1_min_max = std::minmax_element( K1.cbegin(), K1.cend() );
220 auto K2_min_max = std::minmax_element(
K2.cbegin(),
K2.cend() );
221 std::cout << "Computed k1 curvatures:"
222 << " min=" << *K1_min_max.first << " max=" << *K1_min_max.second
223 << std::endl;
224 std::cout << "Computed k2 curvatures:"
225 << " min=" << *K2_min_max.first << " max=" << *K2_min_max.second
226 << std::endl;
228
230
231 smesh.vertexNormals() = SH::RealVectors();
232 smesh.faceNormals() = SH::RealVectors();
236 auto colorsK1 = SMW::Colors( smesh.nbFaces() );
237 auto colorsK2 = SMW::Colors( smesh.nbFaces() );
238 for ( auto i = 0; i < smesh.nbFaces(); i++ )
239 {
240 colorsK1[ i ] = colormapK1( K1[ i ] );
241 colorsK2[ i ] = colormapK2( K2[ i ] );
242 }
243 SMW::writeOBJ( "example-cnc-K1", smesh, colorsK1 );
244 SMW::writeOBJ( "example-cnc-K2", smesh, colorsK2 );
245 const auto avg_e = smesh.averageEdgeLength();
246 SH::RealPoints positions( smesh.nbFaces() );
247 for ( auto f = 0; f < positions.size(); ++f )
248 {
249 D1[ f ] *= smesh.localWindow( f );
250 positions[ f ] = smesh.faceCentroid( f ) - 0.5 * D1[ f ];
251 }
252 SH::saveVectorFieldOBJ( positions, D1, 0.05 * avg_e, SH::Colors(),
253 "example-cnc-D1",
254 SH::Color::Black, SH::Color( 0, 128, 0 ) );
255 for ( auto f = 0; f < positions.size(); ++f )
256 {
257 D2[ f ] *= smesh.localWindow( f );
258 positions[ f ] = smesh.faceCentroid( f ) - 0.5 * D2[ f ];
259 }
260 SH::saveVectorFieldOBJ( positions, D2, 0.05 * avg_e, SH::Colors(),
261 "example-cnc-D2",
262 SH::Color::Black, SH::Color(128, 0,128 ) );
264 return 0;
265}
Aim: This class is used to simplify shape and surface creation. With it, you can create new shapes an...
Aim: This class is used to simplify shape and surface creation. With it, you can create new shapes an...
Z3i this namespace gathers the standard of types for 3D imagery.
DGtal is the top-level namespace which contains all DGtal functions and types.
QuantifiedColorMap< TColorMap > makeQuantifiedColorMap(TColorMap colormap, int nb=50)
std::pair< typename graph_traits< DGtal::DigitalSurface< TDigitalSurfaceContainer > >::vertex_iterator, typename graph_traits< DGtal::DigitalSurface< TDigitalSurfaceContainer > >::vertex_iterator > vertices(const DGtal::DigitalSurface< TDigitalSurfaceContainer > &digSurf)
Aim: Utility class to compute curvature measures induced by (1) a corrected normal current defined by...
Aim: An helper class for reading mesh files (Wavefront OBJ at this point) and creating a SurfaceMesh.
Aim: An helper class for writing mesh file formats (Waverfront OBJ at this point) and creating a Surf...
Aim: Represents an embedded mesh as faces and a list of vertices. Vertices may be shared among faces ...
DGtal::GradientColorMap< double > makeColorMap(double min_value, double max_value)
[curvature-measures-Includes]