Bug with intersect tolerance in curve curve intersection

I’m trying to remove curves with a certain margin from a boundary by using higher values of intersection tolerance. There seems to be a bug with the intersection tolerance when the boundary has horizontal or vertical lines: see image

the code basically comes down to this:

import Rhino
import rhinoscriptsyntax as rs

boundary=rs.GetObject("boundary")
curves=rs.GetObjects("curves to test")
plane=Rhino.Geometry.Plane.WorldXY

for curve in curves:
    b=rs.coercecurve(boundary)
    c=rs.coercecurve(curve)
    bb=c.GetBoundingBox(True)
    cen=bb.Center
    
    x=10 #intersection tolerance
    y=0 #overlap tolerance
    
    intersections = Rhino.Geometry.Intersect.Intersection.CurveCurve(b,c,x,y)
    if intersections.Count>0 or not b.Contains(cen, plane)==Rhino.Geometry.PointContainment.Inside:
        rs.DeleteObject(curve)

In this case, I would take the center of the bounding box of the little grain-like curves and test if they are further removed than 10 units from the boundary curve and that they are inside the boundary curve. In other words, don’t use and intersection test but use boundary.ClosestPoint(cen)

That will not give the result I want. For circles it would work, but for example long rectangles could have a center farther away from the boundary then set units, while still intersecting the boundary.

I see, you are right. Ultimately, you may want to use a combination of

  • closest-point on bounding box min and max point as a quick test to rule out most of the contained elements
  • boundary-curve intersection with a strict tolerance (0.001 units) to rule out intersecting elements
  • iterative closest point on both boundary and element curves to find the two points with the closest distance between two non-intersecting curves
  • point-is-inside test.

Hi Gijs,

How about testing the deviations:

http://4.rhino3d.com/5/rhinocommon/?topic=html/M_Rhino_Geometry_Curve_GetDistancesBetweenCurves.htm

Cool scripts you are sharing lately btw. I think many can appreciate them, both for practical use and learning more than basic scripting.

Groetjes
Willem

thanks @Willem,

I will try your suggestion, seems like that will be more waterproof.

as for sharing the scripts, that’s indeed the main reason for me to post the scripts. As I was trying to figure out the dynamic display stuff, there were a few but not many examples, so I hope it is useful for others when searching around for solutions.

@Willem,

it seems difficult to make it work with distance between curves, because it doesn’t simply accept polycurves. I also noticed that this will make a lot more computations.

Hi Gijs,

I see that indeed the GetDistanceBetweenCurves is not fruitful, it appears to only operate on curves that are intersecting or close to intersecting eachother… my bad

Best in that case would be the approach Menno is describing.

Or maybe create an inward offset of your boundarycurve and test that for intersections?

-Willem

@Willem , I tried first with offset, but found it to be unreliable, because offsets can fail easily or generate more than 1 curve. But the method described by @menno seems like it will also be quite computational intensive for the dynamic display at least. Any idea who at McNeel I can ask to look into this?

Hi Gijs,

You might consider offsetting the boundary curves and then use one of the point and/or curve containment tests to see if the inner curves fall within its boundary.

Rhino.Geometry.Curve.PlanarClosedCurveRelationship
Rhino.Geometry.Curve.PlanarCurveCollision
Rhino.Geometry.Curve.Contains

Feel free to post your test geometry so we can all experiment!

– Dale

test-delete-curves.3dm (585.8 KB)

for example run the code I posted above on both left and right to see the difference…

the problem I have with offsetting is: how do I pick a point that is quite near to the border but inside the boundary? Because I noticed that if I pick let’s say the boundary boundingbox center, it can fail where it would normally (using rhino offset manually) doesn’t fail.

I believe I have managed that in the past by evaluating the curve tangent at an arbitrary point, create a plane with the tangent and the world Zaxis, Rhino.Geometry.Plane(Point3d, xDirection: tangent, yDirection: Zaxis)
for the resulting plane create the point at z=1 and z=-1
Now you have 2 points that lay on either side of the curve. Test which curve is inside and use that for the offset.

Actually; It’s as simple as taking the boundingbox, inflate it just to be sure.
Take a corner point for offsetting and offset a negative number. that will offset the curve to the inside.

-HTH
Willem

Indeed. Just pick boundingbox.max and you should always be on the outside. Then use a negative number to let it offset to the inside.

Thanks @Willem, @jordy1989

I found out the offset method also allows offsetting without picking a point. Instead using plane, and vector. I will look which is most reliable

ok, fyi I tried both methods. The one using a point and a vector seems more reliable than the method using only plane. Besides that the latter needs help from .CurveOrientation to know the right side to offset to.