-
Notifications
You must be signed in to change notification settings - Fork 60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mesh Traversal #1377
Comments
Thanks @Grantim, this is all super useful! Quick question regarding:
Which of the below edges would belong to the green hit point? Is it always the closest or a random assignment? |
It is not guaranteed to be closest, as far as MeshTriPoint also has /// barycentric coordinates
/// \details a in [0,1], a=0 => point is on next( e ) edge, a=1 => point is in dest( e )
/// b in [0,1], b=0 => point is on e edge, b=1 => point is in dest( next( e ) )
/// a+b in [0,1], a+b=0 => point is in org( e ), a+b=1 => point is on prev( e.sym() ) edge
TriPointf bary; it can be represented by each of these edges. P.S.
|
One more question regarding these functions. What is the purpose of MeshLib/source/MRMesh/MREdgeMetric.h Lines 15 to 16 in 18e2196
|
Basically EdgeMetric is needed to calculate distance on edge-based operation. Example of /// expands the region (of faces or vertices) on given metric value. returns false if callback also returns false
MRMESH_API bool dilateRegionByMetric( const MeshTopology& topology, const EdgeMetric& metric, VertBitSet& region, float dilation, ProgressCallback callback = {} ); lets assume that we start in red vertex: /// returns edge's length as a metric
[[nodiscard]] MRMESH_API EdgeMetric edgeLengthMetric( const Mesh & mesh ); with Otherwise if we use /// metric returning 1 for every edge
[[nodiscard]] MRMESH_API EdgeMetric identityMetric(); with So EdgeMetric allows you to control geometry properties of expansion and also in some other algorithms. Another example: /// builds shortest path in given metric from start to finish vertices; if no path can be found then empty path is returned
[[nodiscard]] MRMESH_API EdgePath buildSmallestMetricPath( const MeshTopology & topology, const EdgeMetric & metric,
VertId start, VertId finish, float maxPathMetric = FLT_MAX ); If we use here |
Makes sense. To make sure I understand it correctly: MRMESH_API bool dilateRegion( const Mesh& mesh, VertBitSet& region, float dilation, ProgressCallback callback = {} ); is equivalent to this: [[nodiscard]] MRMESH_API EdgeMetric edgeLengthMetric( const Mesh & mesh );
MRMESH_API bool dilateRegionByMetric( const MeshTopology& topology, const EdgeMetric& metric, VertBitSet& region, float dilation, ProgressCallback callback = {} ); |
Yes it is right bool dilateRegion( const Mesh& mesh, VertBitSet& region, float dilation, ProgressCallback callback )
{
return dilateRegionByMetric( mesh.topology, edgeLengthMetric( mesh ), region, dilation, callback );
} |
Awesome! Thanks a lot, now I have a much better understanding of how to navigate the mesh. As a side note, I think there is a minor error in your first reply. Shouldn't this: assert( mesh.topology.next( 0_e ) == 5_e );
assert( mesh.topology.next( 2_e ) == 1_e );
assert( mesh.topology.next( 4_e ) == 3_e ); be corrected to this? assert( mesh.topology.next( 0_e ) == 2_e );
assert( mesh.topology.next( 2_e ) == 4_e );
assert( mesh.topology.next( 4_e ) == 0_e ); Maybe you could edit your post to keep it consistent for future reference? |
Gotcha. Thanks again for a clear explanation! |
Closing now, please feel free to reopen if needed |
Is there a robust way of checking the direction of an 2023-07-09.11-08-10.mp4 |
One way is to calculate normal of contour and comare it with surface normal const Vector3f cSurfaceNorm = Vector3f::plusZ();
Vector3f contourNormal;
for ( auto e : contour )
contourNormal += cross( mesh.orgPnt( e ), mesh.destPnt( e ) );
if ( dot( contourNormal, cSurfaceNorm ) < 0.0f )
reverse( contour ); this method should work in most cases, but because it based on geometry (which can be degeneratre it can fail in some rare cases) Other, more robust method: auto insideRegion = fillContourLeft( mesh.topology, contour );
if ( ( mesh.topology.findBoundaryFaces() & insideRegion ).any() )
insideRegion = mesh.topology.getValidFaces() - insideRegion; Cannot say which method is faster, but second should always work (as long as |
Thanks @Grantim, the first method is more suitable for my applications. It works like a charm! |
Closing this issue, if you have any related questions please reopen it |
You need these contours to be oriented this way MeshLib/source/MRMesh/MRFillContour.h Lines 8 to 10 in ae1704c
mesh.topology.deleteFaces( fillContourLeft( mesh.topology, contours ) );
mesh.invalidateCaches(); // important to call after direct changing of `MeshTopology` |
Thanks a lot. |
I'm trying to gain a better understanding of how to navigate the mesh topology. Could you please point me in the right direction when it comes to the following operations?
Face/Edge/Vertex Selection
Given a ray, how can I select the intersecting mesh element? The function below returns a
MeshTriPoint
, is there a way to retrieve the corresponding Face, Edge or Vertex?MeshLib/source/MRMesh/MRMeshIntersect.h
Lines 30 to 31 in 20f169b
Internal Face Selection
Given a closed edge loop (cyan), select all internal faces (yellow):
Hole & Boundary Selection
Given a single edge (cyan), select the entire edge loop forming the hole boundary (yellow). Same applies to external boundaries:
Expanding/Shrinking Selection
Given an arbitrary amount of selected faces expand or shrink the selection to include the neighboring faces:
The text was updated successfully, but these errors were encountered: