| 484 | } |
| 485 | |
| 486 | Expected<SurfacePath, PathError> computeFastMarchingPath( const MeshPart & mp, |
| 487 | const MeshTriPoint & start, const MeshTriPoint & end, |
| 488 | const VertBitSet* vertRegion, VertScalars * outSurfaceDistances ) |
| 489 | { |
| 490 | MR_TIMER; |
| 491 | SurfacePath res; |
| 492 | auto s = start; |
| 493 | auto e = end; |
| 494 | if ( fromSameTriangle( mp.mesh.topology, s, e ) ) |
| 495 | return res; // path does not cross any edges |
| 496 | |
| 497 | // the region can be specified by faces or by vertices, but not in both ways at the same time |
| 498 | assert( !mp.region || !vertRegion ); |
| 499 | |
| 500 | VertBitSet myVertRegion; |
| 501 | if ( mp.region ) |
| 502 | { |
| 503 | myVertRegion = getIncidentVerts( mp.mesh.topology, *mp.region ); |
| 504 | vertRegion = &myVertRegion; |
| 505 | } |
| 506 | |
| 507 | // build distances from end to start, so to get correct path in reverse order |
| 508 | bool connected = false; |
| 509 | auto distances = computeSurfaceDistances( mp.mesh, end, start, vertRegion, &connected ); |
| 510 | if ( !connected ) |
| 511 | return unexpected( PathError::StartEndNotConnected ); |
| 512 | |
| 513 | res = computeSteepestDescentPath( mp.mesh, distances, start, { .end = end } ); |
| 514 | if ( res.empty() ) // no edge is crossed only if start and end are from the same triangle |
| 515 | return unexpected( PathError::InternalError ); |
| 516 | |
| 517 | if ( outSurfaceDistances ) |
| 518 | *outSurfaceDistances = std::move( distances ); |
| 519 | return res; |
| 520 | } |
| 521 | |
| 522 | Expected<SurfacePath, PathError> computeSurfacePath( const MeshPart & mp, |
| 523 | const MeshTriPoint & start, const MeshTriPoint & end, int maxGeodesicIters, |
no test coverage detected