IsPointInSurface bug?

I’m using the IsPointInSurface method to check what points are inside a closed surface. Initially it was all good but when I use strictly_in = True and I add a tolerance to the method, I still end up with some points on a few edges and vertices of my geometry, even though they should all be inside by at least the tolerance.

You can try it by creating a box in rhino, let’s say 100x100x100. Then use the PointGrid command to create a volumetric point cloud inside of it. And finaly, run this simple python script:

import rhinoscriptsyntax as rs

polysurface_id = rs.GetObject("Select a polysurface", 56)
point_cloud = rs.GetObject("Select a point cloud")
points = rs.PointCloudPoints(point_cloud)

for point in points:
    if rs.IsPointInSurface(polysurface_id, point, True, 10):
        rs.AddPoint(point)

You will see you will still have some points on the surface, like the screenshot below:

Am I doing something wrong or is this a bug?

Hi Roberto - looking at the underlying RhinoCommon function

https://developer.rhino3d.com/api/rhinocommon/rhino.geometry.brep/ispointinside

the tolerance is used like this with StrictlyIn:

  • strictlyIn
  • Type: System.Boolean
  • if true, point is in if inside brep by at least tolerance. if false, point is in if truly in or within tolerance of boundary.

-Pascal

Sorry Pascal, I’m still not getting it. If it is checking if the points are inside the volume by at least the specified tolerance, then why is it keeping some points on the edges? Shouldn’t those be excluded?

It might or might not be what Pascal had in mind, but I have better success directly using the RhinoCommon method that he linked to:

_Box 0 100,100,100 _Enter
_PointGrid 11 0 100,100,100 _Enter
import rhinoscriptsyntax as rs

polysurface_id = rs.GetObject("Select a polysurface", 56)
point_cloud = rs.GetObject("Select a point cloud")
point_ids = rs.PointCloudPoints(point_cloud)

brep = rs.coercebrep(polysurface_id)
points = rs.coerce3dpointlist(point_ids)

for point in points:
    if brep.IsPointInside(point, 9., True):
        rs.AddPoint(point)

Note that if I use a tolerance of 10., then from the many points that are theoretically exactly 10 units inside the Brep, some will be included and some won’t. That’s just how floating point math work and there isn’t much we can do for that.

Bugtrack item for fixing the RhinoScript method:
https://mcneel.myjetbrains.com/youtrack/issue/RH-80622/Rhinoscriptsyntax-IsPointInSurface-includes-too-many-points

1 Like

Hi Roberto - I was not actually 100% sure what the problem was on your side, I just noticed that tolerance might initially seem ‘backwards’ in this case - large tolerance meaning more points are likely to be excluded from being inside, not more included.

-Pascal

Thank you very much Pierre, I’ll try using RhinoCommon and see if it works for me.

Yeap, so the problem is that despite the tolerance value, some points are not being excluded, even though they should. If you see the screenshot I shared, the points I highlighted should have been filtered out given the tolerance, but they are still there. It seems that this method has a problem filtering points on edges and vertices.

Ok, quick update on this:

The IsPointInSurface method in the rhinoscriptsyntax library seems to not be working properly when a tolerance is specified (see screenshot in the op).

Using the IsPointInside method in the “rhino common” library in the same geometry worked perfectly.

However, when trying slightly more complex geometry, even IsPointInside failed to filter out all the points. See images below:


test_geo_toShare.3dm (3.4 MB)

I got these points by using the geometry attached and the script that @pierrec posted.

I believe both methods are buggy as they are failing to filter out points outside closed polysurfaces for certain tolerances (depending on the tolerance they might work).