DGtal 1.3.0
Loading...
Searching...
No Matches
tangency-explorer.cpp
1
25#include <iostream>
26#include <string>
27#include <DGtal/base/Common.h>
28#include <DGtal/helpers/StdDefs.h>
29#include <DGtal/helpers/Shortcuts.h>
30#include <DGtal/helpers/ShortcutsGeometry.h>
31#include <DGtal/shapes/SurfaceMesh.h>
32#include "DGtal/geometry/volumes/TangencyComputer.h"
33#include "DGtal/geometry/tools/QuickHull.h"
34#include "DGtal/geometry/surfaces/estimation/PlaneProbingTetrahedronEstimator.h"
35#include "SymmetricConvexExpander.h"
36
37#include "polyscope/pick.h"
38#include <polyscope/polyscope.h>
39#include <polyscope/surface_mesh.h>
40#include <polyscope/point_cloud.h>
41
42#include "ConfigExamples.h"
43
44#include <Eigen/Dense>
45#include <Eigen/Sparse>
46
47using namespace DGtal;
48using namespace Z3i;
49
50// Using standard 3D digital space.
53// The following typedefs are useful
55typedef SurfMesh::Face Face;
59
60//Polyscope global
61polyscope::SurfaceMesh *psMesh;
62polyscope::SurfaceMesh *psDualMesh;
63polyscope::SurfaceMesh *psTriangle;
64polyscope::PointCloud* psCloud;
65polyscope::PointCloud* psCloudCvx;
66SurfMesh surfmesh;
67SurfMesh dual_surfmesh;
68float gridstep = 1.0;
69int vertex_idx = -1;
70int face_idx = -1;
71int edge_idx = -1;
72float Time = 0.0;
73bool is_selected = false;
74Point selected_kpoint; // valid if selection == true
75bool PSym = false;
76bool enforceFC = true;
77std::vector< Point > digital_points;
78KSpace K;
83typedef std::vector< Index > Indices;
84typedef double Scalar;
85typedef std::vector< Scalar > Scalars;
86
87struct UnorderedPointSetPredicate
88{
90 const std::unordered_set< Point >* myS;
91 explicit UnorderedPointSetPredicate( const std::unordered_set< Point >& S )
92 : myS( &S ) {}
93 bool operator()( const Point& p ) const
94 { return myS->count( p ) != 0; }
95};
96
97std::unordered_set< Point > unorderedSet;
98
99// ----------------------------------------------------------------------
100// utilities pointel
101Point pointelRealPoint2Point( RealPoint p )
102{
103 RealPoint sp = RealPoint( round( p[ 0 ] / gridstep + 0.5 ),
104 round( p[ 1 ] / gridstep + 0.5 ),
105 round( p[ 2 ] / gridstep + 0.5 ) );
106 return Point( sp[ 0 ], sp[ 1 ], sp[ 2 ] );
107}
108RealPoint pointelPoint2RealPoint( Point q )
109{
110 return RealPoint( gridstep * ( q[ 0 ] - 0.5 ),
111 gridstep * ( q[ 1 ] - 0.5 ),
112 gridstep * ( q[ 2 ] - 0.5 ) );
113}
114void embedPointels( const std::vector< Point >& vq, std::vector< RealPoint >& vp )
115{
116 vp.resize( vq.size() );
117 for ( auto i = 0; i < vp.size(); ++i )
118 vp[ i ] = pointelPoint2RealPoint( vq[ i ] );
119}
120void digitizePointels( const std::vector< RealPoint >& vp, std::vector< Point >& vq )
121{
122 vq.resize( vp.size() );
123 for ( auto i = 0; i < vq.size(); ++i )
124 vq[ i ] = pointelRealPoint2Point( vp[ i ] );
125}
126
127// ----------------------------------------------------------------------
128// utilities voxel
129Point voxelRealPoint2Point( RealPoint p )
130{
131 RealPoint sp = RealPoint( round( p[ 0 ] / gridstep ),
132 round( p[ 1 ] / gridstep ),
133 round( p[ 2 ] / gridstep ) );
134 return Point( sp[ 0 ], sp[ 1 ], sp[ 2 ] );
135}
136RealPoint voxelPoint2RealPoint( Point q )
137{
138 return RealPoint( gridstep * ( q[ 0 ] ),
139 gridstep * ( q[ 1 ] ),
140 gridstep * ( q[ 2 ] ) );
141}
142void embedVoxels( const std::vector< Point >& vq, std::vector< RealPoint >& vp )
143{
144 vp.resize( vq.size() );
145 for ( auto i = 0; i < vp.size(); ++i )
146 vp[ i ] = voxelPoint2RealPoint( vq[ i ] );
147}
148void digitizeVoxels( const std::vector< RealPoint >& vp, std::vector< Point >& vq )
149{
150 vq.resize( vp.size() );
151 for ( auto i = 0; i < vq.size(); ++i )
152 vq[ i ] = voxelRealPoint2Point( vp[ i ] );
153}
154
155// @return the indices of all the points of X different from p that are cotangent to p.
156Indices tangentCone( const Point& p )
157{
158 return TC.getCotangentPoints( p );
159}
160
161Scalars distances( const Point& p, const Indices& idx )
162{
163 Scalars D( idx.size() );
164 for ( Index i = 0; i < idx.size(); i++ )
165 D[ i ] = ( TC.point( i ) - p ).norm();
166 return D;
167}
168
170std::vector< Point >
171findCorners( const std::unordered_set< Point >& S,
172 const std::vector< Vector >& In,
173 const std::vector< Vector >& Out )
174{
175 std::vector< Point > C;
176 for ( auto&& p : S )
177 {
178 bool corner = true;
179 for ( auto&& n : In )
180 if ( ! S.count( p+n ) ) { corner = false; break; }
181 if ( ! corner ) continue;
182 for ( auto&& n : Out )
183 if ( S.count( p+n ) ) { corner = false; break; }
184 if ( corner ) C.push_back( p );
185 }
186 return C;
187}
188
189void computeQuadrant( int q,
190 std::vector< Vector >& In,
191 std::vector< Vector >& Out )
192{
193 In.clear();
194 Out.clear();
195 In.push_back( Vector( q & 0x1 ? 1 : -1, 0, 0 ) );
196 In.push_back( Vector( 0, q & 0x2 ? 1 : -1, 0 ) );
197 In.push_back( Vector( 0, 0, q & 0x4 ? 1 : -1 ) );
198 Out.push_back( Vector( q & 0x1 ? 1 : -1, q & 0x2 ? 1 : -1, q & 0x4 ? 1 : -1 ) );
199 Vector D = ( In[ 1 ] - In[ 0 ] ).crossProduct( In[ 2 ] - In[ 0 ] );
200 if ( D.dot( Out[ 0 ] ) < 0.0 ) std::swap( In[ 1 ], In[ 2 ] );
201 In.push_back( In[ 0 ]+In[ 1 ] );
202 In.push_back( In[ 0 ]+In[ 2 ] );
203 In.push_back( In[ 1 ]+In[ 2 ] );
204}
205
206
207void computePlanes()
208{
209 // - mode specifies the candidate set, it is one of { ProbingMode::H, ProbingMode::R, ProbingMode::R1 }.
210 using Estimator
211 = DGtal::PlaneProbingTetrahedronEstimator< UnorderedPointSetPredicate,
212 ProbingMode::R >;
213 trace.beginBlock( "Compute planes" );
214 std::vector< RealPoint > positions;
215 std::vector< Point > vertices;
216 std::vector< std::vector<SH3::SurfaceMesh::Vertex> > faces;
217 std::vector< Vector > In;
218 std::vector< Vector > Out;
219 std::unordered_set< Point > S( digital_points.cbegin(), digital_points.cend() );
220 UnorderedPointSetPredicate predS( S );
221 Index i = 0;
222 for ( int q = 0; q < 8; q++ ) // for each quadrant
223 {
224 computeQuadrant( q, In, Out );
225 std::vector< Point > corners = findCorners( S, In, Out );
226 std::cout << "Found " << corners.size() << " in Q" << q << std::endl;
227 std::array<Point, 3> m = { In[ 0 ], In[ 1 ], In[ 2 ] };
228 for ( auto&& p : corners )
229 {
230 Estimator estimator( p, m, predS );
231 // if ( estimator.hexagonState()
232 // != Estimator::Neighborhood::HexagonState::Planar)
233 // continue;
234 std::vector<SH3::SurfaceMesh::Vertex> triangle { i, i+1, i+2 };
235 auto v = estimator.vertices();
236 faces.push_back( triangle );
237 vertices.push_back( v[ 0 ] );
238 vertices.push_back( v[ 1 ] );
239 vertices.push_back( v[ 2 ] );
240 while (estimator.advance().first) {
241 auto state = estimator.hexagonState();
242 if (state == Estimator::Neighborhood::HexagonState::Planar) {
243 auto v = estimator.vertices();
244 if ( S.count( v[ 0 ] ) && S.count( v[ 1 ] ) && S.count( v[ 2 ] ) )
245 {
246 std::vector< Point > X { v[ 0 ], v[ 1 ], v[ 2 ] };
247 auto P = dconv.makePolytope( X );
248 if ( dconv.isFullySubconvex( P, LS ) )
249 // // && TC.arePointsCotangent( v[ 0 ], v[ 1 ], v[ 2 ] ) )
250 {
251 vertices[ i ] = v[ 0 ];
252 vertices[ i+1 ] = v[ 1 ];
253 vertices[ i+2 ] = v[ 2 ];
254 }
255 }
256 }
257 }
258 i += 3;
259 // }
260 }
261 }
262 Time = trace.endBlock();
263 embedPointels( vertices, positions );
264 psTriangle = polyscope::registerSurfaceMesh("Triangle", positions, faces);
265}
266
268void computeTangentCone()
269{
270 if ( digital_points.empty() ) return;
271 if ( vertex_idx < 0 || vertex_idx >= digital_points.size() ) return;
272 const auto p = digital_points[ vertex_idx ];
273 trace.beginBlock( "Compute tangent cone" );
274 auto local_X_idx = TC.getCotangentPoints( p );
275 std::cout << "#cone=" << local_X_idx.size() << std::endl;
276 local_X_idx.push_back( vertex_idx );
277 std::vector< Point > local_X;
278 std::vector< RealPoint > emb_local_X;
279 for ( auto idx : local_X_idx )
280 local_X.push_back( TC.point( idx ) );
281 std::vector< double > values( local_X.size(), 0.0 );
282 values.back() = 1.0;
283 embedPointels( local_X, emb_local_X );
284 psCloud = polyscope::registerPointCloud( "Tangent cone", emb_local_X );
285 psCloud->setPointRadius( gridstep / 100.0 );
286 psCloud->addScalarQuantity( "Classification", values );
287 QuickHull3D hull;
288 hull.setInput( local_X, false );
289 hull.computeConvexHull();
290 std::vector< Point > positions;
291 std::vector< RealPoint > emb_positions;
292 hull.getVertexPositions( positions );
293 Time = trace.endBlock();
294 embedPointels( positions, emb_positions );
295 psCloudCvx = polyscope::registerPointCloud( "Tangent cone vertices", emb_positions );
296 psCloudCvx->setPointRadius( gridstep / 50.0 );
297}
298
300void computeSymmetricConvexSet()
301{
302 if ( digital_points.empty() ) return;
303 if ( ! is_selected ) return;
304 trace.beginBlock( "Compute symmetric convex set" );
305 Point lo = Point::diagonal(-10000);
306 Point up = Point::diagonal( 10000);
307 UnorderedPointSetPredicate predS( unorderedSet );
308 SymmetricConvexExpander< KSpace, UnorderedPointSetPredicate > SCE
309 ( predS, selected_kpoint, lo, up );
310 while ( SCE.advance( enforceFC ) )
311 if ( PSym && ! SCE.myPerfectSymmetry
312 && SCE.current().second >= SCE.myPerfectSymmetryRadius )
313 break;
314 std::cout << "#symcvx=" << SCE.myPoints.size() << std::endl;
315 Time = trace.endBlock();
316 std::vector< Point > positions( SCE.myPoints.cbegin(), SCE.myPoints.cend() );
317 std::vector< RealPoint > emb_positions;
318 embedPointels( positions, emb_positions );
319 psCloud = polyscope::registerPointCloud( "Symmetric convex set", emb_positions );
320 psCloud->setPointRadius( gridstep / 100.0 );
321}
322
323struct TriangleContext
324{
325 Point p;
326 Indices cone_P; // the vector of indices of points in the tangent cone to p.
327 Scalars d_P; // the associated vector of distance to point p.
328 Scalar max_d; // the maximum of d_P
329 Scalar min_d; // the minimum distance between all pair of points in {P,A,B,C}
330 Scalar best; // the current best D=d_P(A)+d_P(B)+d_P(C)+d_A(B)+d_A(C)+d_B(C)
331 Scalar cur_qA;
332 Scalar cur_qAB;
333};
334
335Scalar bestTriangleAB( TriangleContext& ctx,
336 const Index A, const Index B, Index& C )
337{
338 if ( ( ctx.best - ctx.cur_qAB ) > 4.0 * ctx.max_d ) return 0.0;
339 Index cur_C;
340 Scalar q = 0.0;
341 const Point a = TC.point( ctx.cone_P[ A ] );
342 const Point b = TC.point( ctx.cone_P[ B ] );
343 for ( cur_C = B + 1; cur_C < ctx.cone_P.size(); cur_C++ )
344 {
345 const Scalar d_PC = ctx.d_P[ cur_C ];
346 if ( d_PC < ctx.min_d ) continue;
347 const Point c = TC.point( ctx.cone_P[ cur_C ] );
348 const Scalar d_AC = ( c - a ).norm();
349 if ( d_AC < ctx.min_d ) continue;
350 const Scalar d_BC = ( c - b ).norm();
351 if ( d_BC < ctx.min_d ) continue;
352 const Scalar cur_q = ctx.cur_qAB + d_PC + d_AC + d_BC
353 + sqrt( ( ( b - a ).crossProduct( c - a ) ).norm() );
354 if ( cur_q > q )
355 {
356 if ( ! TC.arePointsCotangent( a, c ) ) continue;
357 if ( ! TC.arePointsCotangent( b, c ) ) continue;
358 C = cur_C; q = cur_q;
359 }
360 }
361 return q;
362}
363
364Scalar bestTriangleA( TriangleContext& ctx,
365 const Index A,
366 Index& B, Index& C )
367{
368 Index cur_B, cur_C;
369 Scalar q = 0.0;
370 const Point a = TC.point( ctx.cone_P[ A ] );
371 for ( cur_B = A + 1; cur_B < ctx.cone_P.size(); cur_B++ )
372 {
373 const Scalar d_PB = ctx.d_P[ cur_B ];
374 if ( d_PB < ctx.min_d ) continue;
375 const Point b = TC.point( ctx.cone_P[ cur_B ] );
376 const Scalar d_AB = ( b - a ).norm();
377 if ( d_AB < ctx.min_d ) continue;
378 if ( ! TC.arePointsCotangent( a, b ) ) continue;
379 ctx.cur_qAB = ctx.cur_qA + d_PB + d_AB;
380 const Scalar result = bestTriangleAB( ctx, A, cur_B, cur_C );
381 if ( result > q )
382 {
383 B = cur_B; C = cur_C; q = result;
384 }
385 }
386 return q;
387}
388
389Scalar bestTriangle( TriangleContext& ctx,
390 Index& A, Index& B, Index& C )
391{
392 Index cur_A, cur_B, cur_C;
393 for ( cur_A = 0; cur_A < ctx.cone_P.size(); cur_A++ )
394 {
395 std::cout << " " << cur_A;
396 std::cout.flush();
397 const Scalar d_PA = ctx.d_P[ cur_A ];
398 if ( d_PA < ctx.min_d ) continue;
399 ctx.cur_qA = d_PA;
400 const Scalar result = bestTriangleA( ctx, cur_A, cur_B, cur_C );
401 if ( result > ctx.best )
402 {
403 A = cur_A; B = cur_B; C = cur_C;
404 ctx.best = result;
405 }
406 }
407 return ctx.best;
408}
409
410void computeGreatTriangle()
411{
412 if ( digital_points.empty() ) return;
413 if ( vertex_idx < 0 || vertex_idx >= digital_points.size() ) return;
414 trace.beginBlock( "Compute best triangle" );
415 TriangleContext ctx;
416 ctx.p = digital_points[ vertex_idx ];
417 ctx.cone_P = tangentCone( ctx.p );
418 std::cout << "#cone=" << ctx.cone_P.size() << std::endl;
419 ctx.cone_P.push_back( vertex_idx );
420 ctx.d_P = distances( ctx.p, ctx.cone_P );
421 ctx.max_d = *( std::max_element( ctx.d_P.cbegin(), ctx.d_P.cend() ) );
422 ctx.min_d = ctx.max_d / 3.0;
423 ctx.best = 0.0;
424 Index A, B, C;
425 Scalar d = bestTriangle( ctx, A, B, C );
426 Time = trace.endBlock();
427 std::cout << "Best triangle " << A << " " << B << " " << C
428 << " d=" << ctx.best << std::endl;
429 if ( d == 0 ) return;
430 std::vector< std::vector<SH3::SurfaceMesh::Vertex> > faces;
431 std::vector<SH3::SurfaceMesh::Vertex> triangle { 0, 1, 2 };
432 faces.push_back( triangle );
433 std::vector<RealPoint> positions;
434 std::vector< Point > vertices
435 { TC.point( ctx.cone_P[ A ] ),
436 TC.point( ctx.cone_P[ B ] ),
437 TC.point( ctx.cone_P[ C ] ) };
438 embedPointels( vertices, positions );
439 psTriangle = polyscope::registerSurfaceMesh("Triangle", positions, faces);
440}
441
442void myCallback()
443{
444 // Select a vertex with the mouse
445 if (polyscope::pick::haveSelection()) {
446 bool goodSelection = false;
447 auto selection = polyscope::pick::getSelection();
448 auto selectedSurface = static_cast<polyscope::SurfaceMesh*>(selection.first);
449 int idx = selection.second;
450
451 // Only authorize selection on the input surface and the reconstruction
452 auto surf = polyscope::getSurfaceMesh("Input surface");
453 goodSelection = goodSelection || (selectedSurface == surf);
454 const auto nv = selectedSurface->nVertices();
455 const auto nf = selectedSurface->nFaces();
456 const auto ne = selectedSurface->nEdges();
457 // Validate that it its a face index
458 if ( goodSelection )
459 {
460 if ( idx < nv )
461 {
462 vertex_idx = idx;
463 is_selected = true;
464 selected_kpoint = digital_points[ vertex_idx ] * 2;
465 std::ostringstream otext;
466 otext << "Selected vertex = " << vertex_idx
467 << " pos=" << selected_kpoint;
468 ImGui::Text( "%s", otext.str().c_str() );
469 }
470 else if ( idx - nv < nf )
471 {
472 face_idx = idx - nv;
473 is_selected = true;
474 selected_kpoint = Point::zero;
475 for ( auto i : selectedSurface->faces[ face_idx ] )
476 selected_kpoint += digital_points[ i ];
477 selected_kpoint /= 2;
478 std::ostringstream otext;
479 otext << "Selected face = " << face_idx
480 << " pos=" << selected_kpoint;
481 ImGui::Text( "%s", otext.str().c_str() );
482 }
483 else if ( idx - nv - nf < ne )
484 {
485 edge_idx = idx - nv - nf;
486 is_selected = false; // true; // ne fonctionne pas
487 selected_kpoint = Point::zero;
488 for ( auto i : selectedSurface->edgeIndices[ edge_idx ] )
489 selected_kpoint += digital_points[ i ];
490 selected_kpoint /= 2;
491 std::ostringstream otext;
492 otext << "Selected edge = " << edge_idx
493 << " pos=" << selected_kpoint;
494 ImGui::Text( "%s", otext.str().c_str() );
495 }
496 else
497 {
498 vertex_idx = -1;
499 face_idx = -1;
500 edge_idx = -1;
501 is_selected= false;
502 }
503 }
504 }
505 if (ImGui::Button("Compute tangent cone"))
506 computeTangentCone();
507 if (ImGui::Button("Compute symmetric convex set"))
508 computeSymmetricConvexSet();
509 ImGui::Checkbox("Perfect symmetry", &PSym );
510 ImGui::Checkbox("Full convexity", &enforceFC );
511 if (ImGui::Button("Compute great triangle"))
512 computeGreatTriangle();
513 if (ImGui::Button("Compute planes"))
514 computePlanes();
515 ImGui::Text( "Computation time = %f ms", Time );
516}
517
518int main( int argc, char* argv[] )
519{
521 params("surfaceComponents", "All");
522 std::string filename = examplesPath + std::string("/samples/bunny-32.vol");
523 if ( argc > 1 ) filename = std::string( argv[ 1 ] );
524 auto binary_image = SH3::makeBinaryImage(filename, params );
525 K = SH3::getKSpace( binary_image, params );
526 auto surface = SH3::makeDigitalSurface( binary_image, K, params );
527 auto primalSurface = SH3::makePrimalSurfaceMesh(surface);
529 auto dualSurface = SH3::makeDualPolygonalSurface( s2i, surface );
530 //Need to convert the faces
531 std::vector<std::vector<SH3::SurfaceMesh::Vertex>> faces;
532 std::vector<RealPoint> positions;
533 for(auto face= 0 ; face < primalSurface->nbFaces(); ++face)
534 faces.push_back(primalSurface->incidentVertices( face ));
535
536 //Recasting to vector of vertices
537 positions = primalSurface->positions();
538
539 surfmesh = SurfMesh(positions.begin(),
540 positions.end(),
541 faces.begin(),
542 faces.end());
543 std::vector<std::vector<SH3::SurfaceMesh::Vertex>> dual_faces;
544 std::vector<RealPoint> dual_positions;
545 for(auto face= 0 ; face < dualSurface->nbFaces(); ++face)
546 dual_faces.push_back( dualSurface->verticesAroundFace( face ));
547
548 //Recasting to vector of vertices
549 for ( auto vtx = 0; vtx < dualSurface->nbVertices(); ++vtx )
550 dual_positions.push_back( dualSurface->position( vtx ) );
551
552 dual_surfmesh = SurfMesh(dual_positions.begin(),
553 dual_positions.end(),
554 dual_faces.begin(),
555 dual_faces.end());
556 std::cout << surfmesh << std::endl;
557 std::cout << "number of non-manifold Edges = "
558 << surfmesh.computeNonManifoldEdges().size() << std::endl;
559 std::cout << dual_surfmesh << std::endl;
560 std::cout << "number of non-manifold Edges = "
561 << dual_surfmesh.computeNonManifoldEdges().size() << std::endl;
562 // Make digital surface
563 digitizePointels( positions, digital_points );
564 trace.info() << "Surface has " << digital_points.size() << " pointels." << std::endl;
567 TC.init( digital_points.cbegin(), digital_points.cend() );
569 ( digital_points.cbegin(), digital_points.cend(), 0 ).starOfPoints();
570 trace.info() << "#cell_cover = " << TC.cellCover().nbCells() << std::endl;
571 trace.info() << "#lattice_cover = " << LS.size() << std::endl;
572
573 // Make predicate for pointel-based digital surface
574 unorderedSet = std::unordered_set< Point >( digital_points.cbegin(),
575 digital_points.cend() );
576
577 // Initialize polyscope
578 polyscope::init();
579
580 psMesh = polyscope::registerSurfaceMesh("Input surface", positions, faces);
581 psDualMesh = polyscope::registerSurfaceMesh("Input dual surface", dual_positions, dual_faces);
582
583 // Set the callback function
584 polyscope::state::userCallback = myCallback;
585 polyscope::show();
586 return EXIT_SUCCESS;
587}
bool isFullySubconvex(const PointRange &Y, const LatticeSet &StarX) const
LatticePolytope makePolytope(const PointRange &X, bool make_minkowski_summable=false) const
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
Aim: A class that locally estimates a normal on a digital set using only a predicate "does a point x ...
auto dot(const PointVector< dim, OtherComponent, OtherStorage > &v) const -> decltype(DGtal::dotProduct(*this, v))
Dot product with a PointVector.
static Self diagonal(Component val=1)
static Self zero
Static const for zero PointVector.
Definition: PointVector.h:1595
Aim: This class is used to simplify shape and surface creation. With it, you can create new shapes an...
static Parameters parametersGeometryEstimation()
static Parameters defaultParameters()
Aim: This class is used to simplify shape and surface creation. With it, you can create new shapes an...
Definition: Shortcuts.h:105
static KSpace getKSpace(const Point &low, const Point &up, Parameters params=parametersKSpace())
Definition: Shortcuts.h:332
std::map< Surfel, IdxSurfel > Surfel2Index
Definition: Shortcuts.h:188
static CountedPtr< DigitalSurface > makeDigitalSurface(CountedPtr< TPointPredicate > bimage, const KSpace &K, const Parameters &params=parametersDigitalSurface())
Definition: Shortcuts.h:1209
static CountedPtr< PolygonalSurface > makeDualPolygonalSurface(Surfel2Index &s2i, CountedPtr< ::DGtal::DigitalSurface< TContainer > > aSurface)
Definition: Shortcuts.h:2268
static Parameters defaultParameters()
Definition: Shortcuts.h:203
static CountedPtr< SurfaceMesh > makePrimalSurfaceMesh(Cell2Index &c2i, CountedPtr< ::DGtal::DigitalSurface< TContainer > > aSurface)
Definition: Shortcuts.h:2372
static CountedPtr< BinaryImage > makeBinaryImage(Domain shapeDomain)
Definition: Shortcuts.h:561
Aim: A class that computes tangency to a given digital set. It provides services to compute all the c...
void beginBlock(const std::string &keyword="")
std::ostream & info()
double endBlock()
SMesh::Index Index
Space::RealPoint RealPoint
Definition: StdDefs.h:170
Space::Point Point
Definition: StdDefs.h:168
Space::Vector Vector
Definition: StdDefs.h:169
DGtal is the top-level namespace which contains all DGtal functions and types.
auto crossProduct(PointVector< 3, LeftEuclideanRing, LeftContainer > const &lhs, PointVector< 3, RightEuclideanRing, RightContainer > const &rhs) -> decltype(DGtal::constructFromArithmeticConversion(lhs, rhs))
Cross product of two 3D Points/Vectors.
Trace trace
Definition: Common.h:154
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: a geometric kernel to compute the convex hull of digital points with integer-only arithmetic.
Aim: Implements the quickhull algorithm by Barber et al. , a famous arbitrary dimensional convex hull...
Definition: QuickHull.h:140
bool setInput(const std::vector< InputPoint > &input_points, bool remove_duplicates=true)
Definition: QuickHull.h:382
bool getVertexPositions(std::vector< OutputPoint > &vertex_positions)
Definition: QuickHull.h:612
bool computeConvexHull(Status target=Status::VerticesCompleted)
Definition: QuickHull.h:460
Aim: Represents an embedded mesh as faces and a list of vertices. Vertices may be shared among faces ...
Definition: SurfaceMesh.h:92
Edges computeNonManifoldEdges() const
int main()
Definition: testBits.cpp:56
KSpace K
TriMesh::Face Face
TriMesh::Vertex Vertex