Hi everybody,
I’m currently looking for a pythonic way to check, whether a point is directly located on a mesh or not. Any suggestions?
Thanks.
Hi everybody,
I’m currently looking for a pythonic way to check, whether a point is directly located on a mesh or not. Any suggestions?
Thanks.
Does “on a mesh” mean lie on a face or that it coicides with one of the vertices of that face?
Or enclosed inside a solid mesh
https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Geometry_Mesh_ClosestPoint.htm
Then
https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Geometry_Point3d_DistanceTo.htm
Then
test if the distance from input point to closest point is on mesh within tolerance with if distance <= tolernace
Yes, with “on a mesh” I indeed mean that the point lies either on a mesh face, or coincides with a mesh edge or vertex. I guess that I could have been more precise in my explanation. Thanks for the reply, @ivelin.peychev .
Thanks @Michael_Pryor, I’m already aware that this could work, but I was looking for a more precise way, I guess. Maybe my initial question was not that well elaborated.
When I use Rhino.Geometry.Mesh.ClosestPoint()
, a mesh point is found for each and every point, even points that are far away from the mesh. I get that the distance tolerance comparison should remedy this, by sorting out points that lie beyond the tolerance.
However, the tolerance is really hard to get right, especially if their are a couple of points that are pretty near the mesh, but geometrically not on the mesh.
Let’s say I iteratively create the mesh points myself by walking along the mesh on a “random” path. In order to make this work, at each step, I produce a point in the general direction x-amount of units away from the previous point. This temporary point is usually NOT a mesh point, but rather close to the mesh, depending on the mesh curvature. It thus needs to be “projected” on the mesh with Rhino.Geometry.Mesh.ClosestPoint()
to become a mesh point.
Now, as mentioned above, this procedure is flawed, since it finds a mesh point for every point, even if my directional vector places the temporary point way beyond the mesh edge/border. Defining a tolerance really doesn’t work in this case, since every point is a mesh point. The temporary point can’t really be evaluated by distance to a projected mesh point, since this also culls points that have valid mesh points, but are initially far away from the mesh, because of its curvature and the straight vector that it follows along from the original point.
Sooo… what are you trying to do? What is the underlying question? It sounds like @Michael_Pryor’s solution works for the case of one point and one mesh but this is not your case…?
Not sure if this is helpful to your case, but Mesh.ClosestMeshPoint returns more information, that might be what you’re looking for.
Pretty much what I explained in my second post above. A random walker of sorts that stops when it leaves the mesh, or trespasses the mesh edge/border for surface-like meshes, like in the example diagrams. It’s path will be recorded as a curve.
No, it unfortunately doesn’t work, as mentioned above, since the distance between the translated point (by directional vector) and its projection on the mesh (mesh point) can be bigger than the tolerance, even if the mesh point is a true mesh point. This happens, if the curvature of the mesh is “steep” and the vector length is rather large (cf. diagram 2). The result is a distance between the points that is larger than the tolerance and might even be larger than the distance between a trespassing point and its projected mesh point.
The walker would thus erroneously stop in these locations on the mesh. The distance can’t really be trusted!
Thanks for the reply, @Dancergraham!
Thanks @AndersDeleuran, but I don’t really see what could be helpful.
How to check if a point is on a mesh?
If you want to check if a point is on a mesh then my answer is the way. What you want to do it seems has nothing to do with testing if it is on the mesh, but I would still say the way you would do what you want to do is to say if the point is too far away then don’t pull it to the mesh. Or pull the point to the mesh, make a vector from the the previous point to new point and compare it to a vector from previous point to the new point pulled to mesh, measure the angle between the vectors and test against some maximum allowed deviation angle.
Sure, my first explanation of the problem wasn’t precise enough. Checking if a point is on a mesh, or rather if it has a corresponding mesh point, is still the core issue of the bigger problem though.
Ignoring temporary points that are too far away is not an option. As mentioned above, depending on the local curvature of the mesh and the length of the translation vector, the temporary moved point can be far away AND have valid projected mesh point.
The deviation by vector angle doesn’t necessarily inform on whether a project mesh point is valid or not for the same reasons. The angle depends greatly on the curvature of the mesh.
as this problem only shows itself on mesh boders, can’t you just duplicate the boundary as polyline and make a closest-point check there too? If both mesh and polyline have the same distance, you are beyond the mesh.
Nice suggestion, @atair. I’m going to try that. Thanks.
This is why you should be fully descriptive from the start.
If both mesh and polyline have the same distance, you are beyond the mesh.
To be safe I wouldn’t check exact equality, I would check if abs(distanceToMesh-distanceToPolyline)<tolerance with tolerance being the document tolerance or something like 0.001, there are always floating point differences to small degrees with closest to mesh stuff.
even nicer:
https://developer.rhino3d.com/api/RhinoCommon/html/Overload_Rhino_RhinoMath_EpsilonEquals.htm
exists for points, vectors etc.
Well nicer I am not sure, its not saving much code. Either will do. The point is to not do ==
A big thank you to everybody, especially @atair, @Michael_Pryor, @ivelin.peychev, @Dancergraham and @AndersDeleuran for your time, patience and help! Thanks to you guys, I have managed to solve the big mystery!
Although, @Michael_Pryor would have merited to win the solution cup for his first comment that answered my poorly, superficially formulated original question, I’ve decided to hand it to @atair instead. He joined the thread later, read through most of the comment history, and came up with a great solution to my actual problem.