| 336 | } |
| 337 | |
| 338 | Expected<Mesh> offsetOneDirection( const MeshPart& mp, float offset, const GeneralOffsetParameters& params /*= {} */ ) |
| 339 | { |
| 340 | MR_TIMER; |
| 341 | const bool unsignedOffset = params.signDetectionMode == SignDetectionMode::Unsigned; |
| 342 | auto res = generalOffsetMesh( mp, unsignedOffset ? std::abs( offset ) : offset, params ); |
| 343 | if ( !res ) |
| 344 | return res; |
| 345 | |
| 346 | auto& resMesh = res.value(); |
| 347 | |
| 348 | if ( unsignedOffset ) |
| 349 | { |
| 350 | // delete shell faces from resMesh that project on wrong side of input mesh |
| 351 | |
| 352 | // do not trust degenerate faces with huge aspect ratios |
| 353 | auto badFaces = findDegenerateFaces( mp, 1000 ).value(); |
| 354 | // do not trust only boundary degenerate faces (excluding touching the boundary only by short edge) |
| 355 | BitSetParallelFor( badFaces, [&] ( FaceId f ) |
| 356 | { |
| 357 | float perimeter = 0; |
| 358 | float bdLen = 0; |
| 359 | for ( EdgeId e : leftRing( mp.mesh.topology, f ) ) |
| 360 | { |
| 361 | auto elen = mp.mesh.edgeLength( e ); |
| 362 | perimeter += elen; |
| 363 | if ( mp.mesh.topology.isBdEdge( e, mp.region ) ) |
| 364 | bdLen += elen; |
| 365 | } |
| 366 | if ( perimeter * 0.1f >= bdLen ) |
| 367 | badFaces.reset( f ); |
| 368 | } ); |
| 369 | const auto goodFaces = mp.mesh.topology.getFaceIds( mp.region ) - badFaces; |
| 370 | |
| 371 | // for open input mesh, let us find only necessary portion on the shell |
| 372 | auto innerFaces = findInnerShellFacesWithSplits( MeshPart{ mp.mesh, &goodFaces }, resMesh, |
| 373 | { |
| 374 | .side = offset > 0 ? Side::Positive : Side::Negative |
| 375 | } ); |
| 376 | resMesh.topology.deleteFaces( resMesh.topology.getValidFaces() - innerFaces ); |
| 377 | resMesh.pack(); |
| 378 | |
| 379 | if ( offset < 0 ) |
| 380 | resMesh.topology.flipOrientation(); |
| 381 | } |
| 382 | |
| 383 | return resMesh; |
| 384 | } |
| 385 | |
| 386 | Expected<Mesh> offsetPolyline( const Polyline3& polyline, float offset, const OffsetParameters& params /*= {} */ ) |
| 387 | { |
no test coverage detected