Find discontinuities

Hi,

I am trying to duplicate the function of Grasshopper’s Discontinuity component with Python/Rhinocommon. (I know I can just script the component, but I’m looking at applications where GH might not be present, like Mac)

I’ve hacked something together that works, but I’m not really sure it’s correct. In particular, how to determine when I’ve found all the discontinuities and break out of the loop. The GetNextDiscontinuity method returns a tuple with a boolean value and a number (parameter), it’s not explained exactly what the boolean represents, but I noticed it appeared to switch to False when I had found all discontinuities… At this point, it also returns a parameter of “virtual negative infinity” (-1.23432101234321E+308) - funny number! But I don’t know if I’m using the method correctly.

Anyway, code I hacked below… It just creates a square polycurve with two extraneous points which should not be found as discontinuous.

Thx, --Mitch

import Rhino
import scriptcontext as sc

pts=[]
pts.append(Rhino.Geometry.Point3d(0,0,0))
pts.append(Rhino.Geometry.Point3d(5,0,0))
pts.append(Rhino.Geometry.Point3d(10,0,0))
pts.append(Rhino.Geometry.Point3d(10,10,0))
pts.append(Rhino.Geometry.Point3d(5,10,0))
pts.append(Rhino.Geometry.Point3d(0,10,0))
pts.append(Rhino.Geometry.Point3d(0,0,0))

#create a polycurve
pc=Rhino.Geometry.PolyCurve()
for i in range(len(pts)-1):
    pc.Append(Rhino.Geometry.Line(pts[i],pts[i+1]))
sc.doc.Objects.AddCurve(pc)

#find discontinuities
dom=pc.Domain
cornerParams=[]
t=dom[0]
cont=Rhino.Geometry.Continuity.C1_locus_continuous
while True:
    result=pc.GetNextDiscontinuity(cont,t,dom[1])
    if not result[0]: break
    t=result[1]
    cornerParams.append(t)

#add points to see
for t in cornerParams:
    sc.doc.Objects.AddPoint(pc.PointAt(t))
sc.doc.Views.Redraw()

The virtual infinity value that you mention is in fact a RhinoCommon constant called RhinoMath.UnsetValue. YOu can test if a value is Infinity, NaN or UnsetValue using RhinoMath.IsValidDouble

There’s all sorts of handy utility functions in that namespace:
http://4.rhino3d.com/5/rhinocommon/html/AllMembers_T_Rhino_RhinoMath.htm

OK, thanks for that info! --Mitch

In fact, many basic geometries (in fact all that have struct datatypes) have ‘unset’ values. To name a few:

Arc.Unset
Circle.Unset
Point3d.Unset
Vector3d.Unset
BoundingBox.Unset

etc. etc.

They’re very useful in all kinds of algorithms to test if an assignment, that may depend on a lot of operations and if-statements, was ultimately successful.

Anyone have any comments on whether this is the correct way of using FindDiscontinuities (from the original post)?

#find discontinuities
dom=curve.Domain
cornerParams=[]
t=dom[0]
cont=Rhino.Geometry.Continuity.C1_locus_continuous
while True:
    result=pc.GetNextDiscontinuity(cont,t,dom[1])
    if not result[0]: break
    t=result[1]
    cornerParams.append(t)

Hi Mitch,

Any reason you cannot use rs.CurveDiscontinuity from the rhinoscriptsyntax?

Hi Dale,

Of course there is! The reason is… bah… ummm… I didn’t find it…?? :confounded:

And of course, how to use it correctly is right there in curve.py in the rhinoscript library folder…

Doh… Sorry for the noise… :disappointed: Thanks for pointing me in the right direction… :smile:

–Mitch

@dale,

i am not sure if there is a bug in the rs function and RhinoCommon. With the below curve example, the rhinoscript method and Rhino.Geometry.Curve.GetNextDiscontinuity() does not find the G2 (value = 5) and G1 (value = 4) discontinuities between both segments. I tested using RhinoCommon in python and using this script:

import rhinoscriptsyntax as rs

curve_id = rs.GetObject("Select a curve", rs.filter.curve)
if rs.IsCurve(curve_id):
    points = rs.CurveDiscontinuity(curve_id, 5)
    if points: rs.AddPoints(points)

If i explode the curve into its two segments and measure with GCon, the continuity between both segments is reported as G0.

Curve.3dm (5.8 KB)

c.