RhinoCommon differences between rhino5 and rhino7 on Rhino.Geometry.Intersect.Intersection.CurveCurve

Hi,

With both the calls

Rhino.Geometry.Intersect.Intersection.CurveCurve(ent1, ent2, 0.0001, 0)
Rhino.Geometry.Intersect.Intersection.CurveCurve(ent1, ent2, 0.0001, 0.0001)

passing as ent1 and ent2 a segment and a 90deg arc with similar length and radius of 100, tangent on the joint, I have different results on Rhinoceros 5.14 and Rhinoceros 7.5:


on rhino5.14 I retrieve an IntersectionResult declared as point
on rhino7.5 I retrieve an IntersectionResult declared as overlap, but if I measure the overlap length I retrieve 10E-14.
The geometries are overlapping on the double precision, as reported in the attached images related to the same data structures on rhino5.14 and on rhino 7.5

I have worked around in Rhino7.5 measuring the overlap and declaring it as a point intersection.
Should this be done internally in the creation of the intersection events, given that I ask for a tolerance of 10E-4 ?
What does this tolerance mean?

Hi @cavalli.stefano,

Can you provide a 3dm file with geometry that intersects in Rhino 5 and does not in Rhino 7?

If the curves approach each other to within tolerance, an intersection is assumed. In general, using the document’s model absolute tolerance is a good idea.

– Dale

In both cases there is the intersection, but in rhino7 it is declared as overlapping.

I have created a plugin that starts a RhinoCommon method to detect the overlap in Rhino7:
R7TestPlugin001IntersectionOverlap.7z (41.9 KB)

If I paste the same static method to a rhino 5.14 32bit environment, it tells me that the intersection type is a point intersection rather than an overlap intersection, and I was considering correct what rhino5.14 told me even if the concept of overlap is subjected to various interpretations.
With the explanation you gave me on last post about the meaning of tolerance, there is no connection to the length of an overlap intersection rather than a point intersection.

At the moment I have added an if to collapse the problem, however in my opinion it’s better if there is the same result on different versions of Rhinoceros.
I have double checked on different computers, all on windows 10.

Can you provide a 3dm file with geometry that intersects in Rhino 5 and does not in Rhino 7? I want to see what Rhino’s Intersect command reports and I need a 3dm file in the unit system your using.

– Dale

The sample I posted 4 days ago is running in RhinoCommon, with data created inside the method and no connection to the rhinodoc.
The method

    private static void Test_IntersectionResultPointR5_IntersectionResultOverlapR7_EvenIfAnalyticalOverlap10Eminus14AndInputTolerance10Eminus5()
    {
        var tol = 0.00001;
        Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance = tol;
        Rhino.RhinoDoc.ActiveDoc.ModelRelativeTolerance = tol;
        var pointLineStart =
            new Point3d(20.000000000000007, 500, 0);
        var pointLineStop =
            new Point3d(908, 500, 0);
        var pointArcStart = 
            new Point3d(20.000000000000011, 500, 0);
        var pointArcCenter = 
            new Point3d(20, 480, 0);
        var pointArcStop = 
            new Point3d(0, 480, 0);
        var radius = pointArcStart - pointArcCenter;
        var angleStart = Math.Atan2(pointArcStart.Y - pointArcCenter.Y, pointArcStart.X - pointArcCenter.X);
        var segmentStart = Transform.Rotation(Math.PI / 2, new Point3d(0, 0, 0)) * (pointArcStart - pointArcCenter);
        var tangentStart = segmentStart;
        tangentStart.Unitize();

        var line = new LineCurve(new Line(pointLineStart, pointLineStop));
        var arc = new ArcCurve(new Arc(pointArcStart, tangentStart, pointArcStop));
        var ent1 = line;
        var ent2 = arc;
        var result = Rhino.Geometry.Intersect.Intersection.CurveCurve(ent1, ent2, tol, tol)?.ToList() ?? new List<Rhino.Geometry.Intersect.IntersectionEvent>();
        string reportText = "";
        foreach (var item in result)
        {
            if (reportText.Length > 0)
                reportText += ";";
            reportText += string.Format("intersection isPoint='{0}' isOverlap='{1}'", item.IsPoint, item.IsOverlap);
        }
        if (reportText.Length == 0)
            reportText = "no intersection found";
        reportText = "R7TestPlugin001IntersectionOverlapCommand result: " + System.DateTime.Now.ToLongTimeString() + " " + reportText;
        Rhino.RhinoApp.WriteLine(reportText);
    }

is depending only in the tolerance defined inside, isn’t it?

Also, the assignment made in the first 2 instructions should be neglected because the tolerance is passed in
Rhino.Geometry.Intersect.Intersection.CurveCurve(ent1, ent2, tol, tol)
?

Stefano.3dm (14.6 KB)

So I attached the .3dm file for the 2 curves in question. Just to summarize, the first curve is a simple line segment in the x direction (a 2 point degree 1 nurbs aligned exactly in the x-direction). And an 90 arc curve that almost forms a perfect tangent continuous join to the line curve. The “imperfection” is a mismatch between the start of the 2 curves on the order of 10^-14.

I agree that the intersection results differ between Rhino 5 and Rhino 7. In fact I have been working on this code lately and in the Rhino 8 WIP the results go back to the Rhino 5 results.

I’ll try to give a high level view of Curve-x-Curve intersector(CCX). Focusing on the what the results mean and how tolerance parameters are used. The function Rhino.Geometry.Intersect.Intersection.CurveCurve is a computer function with inputs of parameters and data structures and and outputs of other data structures. Its complete description would involve tolerance parameters, Nurbs curve definitions, IEEE floating point computation and other implementation details. However, the model of what is supposed to happen is 3d geometry of piecewise smooth curves ( A polyline is not smooth, it may have kinks, but the pieces between the kinks are smooth line segments).

Given a pair of curves in 3d geometry an intersection point is a 3d point that is common to both curves. These points come in two types. An isolated intersection point has a region around it that contains no other intersection points. The ccx-point type intersection event from CCX is modeled on these isolated intersection points. Other intersection points are not isolated but are contained in curves of intersection points. For example consider two arcs of the unit circle, one a semi-circle consisting of angles 0 through 180 degrees and the other a 90 degree arc of the same circle with angles -45 degrees to 45 degrees. These arcs overlap in a 45 degree arc. A ccx-overlap event from CCX is modeling this type of an intersection event.
image
Overlap.3dm (21.9 KB)

Intersections in Rhino are tolerant of slight imperfections of the input data. The intersection tolerance specifies how close curves must be for the intersector to consider the curves intersect. For example a pair of skew lines in 3d do not intersect in real geometry. They do have a unique pair of points that achieve the minimum distance between the curves. When these curves are intersected with CCX if that distance is less than intersection tolerance a ccx-point event is reported. This tolerance is also used for tangent intersections and endpoint intersections.


IntersectionTolerance.3dm (23.8 KB)

There is also an overlap tolerance. The default overlap tolerance is double the intersection tolerance, this can be achieved by setting overlap tolerance = 0.0.
The overlap tolerance specifies the maximum allowed deviation to still be considered an overlap. overlaps start and end at points that would otherwise be ccx_point events.


OverlapTolerance.3dm (21.1 KB)

There are some other special cases. In particular there is no minimum overlap length, but this can easily be tested by the user when processing ccx-overlap events.

In the 8.0 WIP I am eliminating super small overlaps like the one you reported using ON_PointsAreCoincident which tests that points are within an absolute distance of ~2e-10 or relative tolerance of ~2^-13. This will take care of small rounding errors without sacrificing much accuracy. Small overlaps can happen and when constructing high quality curves, for example in curve joining, one needs to know where the overlaps are.
For this reason I cannot just ignore overlaps smaller than intersection tolerance. Although in some application that may be completely appropriate.

2 Likes

Summarizing the CCX computation theory that could define the bugfix or the new Rhinoceros version, it is correct to say that the 4th parameter in RhinoCommon Method
Rhino.Geometry.Intersect.Intersection.CurveCurve(ent1, ent2, intersectionTolerance, overlapTolerance)
defines the deviation as the “chordal tolerance” of one escaping curve from the other, to activate an overlap of unknown length along the curvilinear coordinate of each curve?

Hi Greg,

I really appreciate this elaborate explanation.

Can I state in more layman’s terms what happens like so:

Both curves get "a lot of" sample points.

sample points are found that are within tolerance distance of the other curve.

An overlap is where a sequence of neighboring points is in tolerance
An intersection point is where an isolated point is in tolerance

-Willem

I was trying describe the behavior of the CCX function, an overview of the functional specification. I was not describing the implementation. But you are correct that there is a lot of curve evaluation involved. I’m sure if you do a literature search for nurbs curve intersections you will get a better idea of the implementation.

1 Like

“Chordal Tolerance” is a terrible description the distance used is closest point distance.

Ok, I agree.

Thanks for the synchronization.