MCPcopy Create free account
hub / github.com/MeshInspector/MeshLib / findDisorientedFaces

Function findDisorientedFaces

source/MRMesh/MRMeshFixer.cpp:302–371  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

300}
301
302Expected<FaceBitSet> findDisorientedFaces( const Mesh& mesh, const FindDisorientationParams& params )
303{
304 MR_TIMER;
305 auto disorientedFaces = mesh.topology.getValidFaces();
306
307 Mesh cpyMesh;
308 const Mesh* targetMesh{ &mesh };
309 EdgeBitSet outHoles;
310 if ( params.virtualFillHoles && mesh.topology.findNumHoles( &outHoles ) > 0 )
311 {
312 cpyMesh = mesh;
313 targetMesh = &cpyMesh;
314 auto sb = subprogress( params.cb, 0.0f, 0.5f );
315 int i = 0;
316 int num = int( outHoles.count() );
317 auto metric = getMinAreaMetric( mesh );
318 for ( auto e : outHoles )
319 {
320 ++i;
321 fillHole( cpyMesh, e, { .metric = metric } ); // use simplest filling
322 if ( !reportProgress( sb, float( i ) / float( num ) ) )
323 return unexpectedOperationCanceled();
324 }
325 }
326
327 auto sb = subprogress( params.cb, targetMesh == &mesh ? 0.0f : 0.5f, 1.0f );
328
329 auto keepGoing = BitSetParallelFor( mesh.topology.getValidFaces(), [&] ( FaceId f )
330 {
331 auto normal = Vector3d( mesh.normal( f ) );
332 auto triCenter = Vector3d( mesh.triCenter( f ) );
333 int counter = 0;
334 auto interPred = [f, &counter] ( const MeshIntersectionResult& res )->bool
335 {
336 if ( res.proj.face != f ) // TODO: we should also try grouping intersections, to ignore too close ones (by some epsilon), to filter several layered areas
337 ++counter;
338 return true;
339 };
340 rayMeshIntersectAll( *targetMesh, Line3d( triCenter, normal ), interPred );
341 bool pValid = counter % 2 == 0;
342 auto pCounter = counter;
343 bool nValid = true;
344 int nCounter = INT_MAX;
345 bool resValid = pValid;
346 if ( params.mode != FindDisorientationParams::RayMode::Positive )
347 {
348 counter = 0;
349 rayMeshIntersectAll( *targetMesh, Line3d( triCenter, -normal ), interPred );
350 nValid = counter % 2 == 1;
351 nCounter = counter - 1; // ideal face has 0-pCounter and 1-nCounter: so we decrement nCounter for fair compare
352
353 resValid = pValid && nValid;
354 if ( params.mode == FindDisorientationParams::RayMode::Shallowest && pValid != nValid )
355 {
356 if ( pCounter == nCounter )
357 resValid = true;
358 else if ( nCounter < pCounter )
359 resValid = nValid;

Callers

nothing calls this directly

Calls 12

subprogressFunction · 0.85
getMinAreaMetricFunction · 0.85
fillHoleFunction · 0.85
reportProgressFunction · 0.85
BitSetParallelForFunction · 0.85
rayMeshIntersectAllFunction · 0.85
findNumHolesMethod · 0.80
countMethod · 0.80
normalMethod · 0.80
triCenterMethod · 0.80
resetMethod · 0.45

Tested by

no test coverage detected