Python version of DivideCurveLength

I’m finally moving to Python from VBscript, and I have a hiccup with the DivideCurveLength function–actually it’s a pretty big problem since I can’t possibly “afford” to work around this by actually splitting curves up, this could be called a million times per run–in Python it doesn’t seem to accept the option of specifying a range to divide? The context help in the editor doesn’t mention it and I get an error about too many arguments.

Hi Jim,

This is best done without actually creating the split curve objects. Doing this leads you in the realm of RhinoCommon and that is much easier navigated with some help.

However I have no time atm to help out, so if you don’t get a proper answer soon, send me a message and I’ll try to help you out when I have more time at hand.

-Willem

As Willem said, you’re going to need to dive into RhinoCommon for this one…

Have a look at the following quick sample, I need to go to bed now, but can pick it up again tomorrow - or someone closer to your time zone will continue…

CHeers, --Mitch

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

def DivideCrvInterval(crv,sParam,eParam,count):
    #this part actually divides the curve (virtually) and returns the parameters
    crv_seg=crv.Trim(sParam,eParam)
    out_params=crv_seg.DivideByCount(count,True)
    return out_params

def TestDivideCurveInterval():
    crv_ID=rs.GetObject("Select curve to divide",4,True)
    if crv_ID:
        #get interval on curve
        pt_0=rs.GetPointOnCurve(crv_ID,"Pick start point of interval")
        if not pt_0: return
        pt_1=rs.GetPointOnCurve(crv_ID,"Pick end point of interval")
        if not pt_1: return
        divs=rs.GetInteger("Number of divisions?",minimum=2)
        if not divs: return
        par_0=rs.CurveClosestPoint(crv_ID,pt_0)
        par_1=rs.CurveClosestPoint(crv_ID,pt_1)
        if par_0==par_1: return
        #reverse interval if descending
        if par_0>par_1: par_1,par_0=[par_0,par_1]
        #get the underlying geometry from the curve object
        crv_geo=sc.doc.Objects.Find(crv_ID).Geometry
        #do the divide
        div_params=DivideCrvInterval(crv_geo,par_0,par_1,divs)
        #Add points to see
        pts=[crv_geo.PointAt(param) for param in div_params]
        rs.AddPoints(pts)
TestDivideCurveInterval()

Hi Jim,

you might use attached DivideCurveLengthEx() method. It should work like the RhinoScript (vb) method and allows to specify an interval.

For the interval you can use a list or two floats or Rhino.Geometry.Interval(t0, t1). Note that the interval is not normalized, as in the RhinoScript (vb) method.

DivideCurveLengthEx.py (1.5 KB)

c.

I see I answered the wrong method here… Thanks Clement for picking up where I left off.

Here is a mod of my above scriptlet which works by length. Divides from the first picked point to the last along the curve regardless of the curve direction.

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

def DivideCrvIntervalByLength(crv,sParam,eParam,s_len,add_end):
    #this part actually divides the curve (virtually) and returns the div points
    flip=False
    if sParam>eParam:
        sParam,eParam=[eParam,sParam] ; flip=True
    crv_seg=crv.Trim(sParam,eParam)
    if crv_seg.GetLength()<=s_len: return
    if flip: crv_seg.Reverse()
    div_params=crv_seg.DivideByLength(s_len,True)
    div_pts=[crv_seg.PointAt(param) for param in div_params]
    #add end point if desired
    if add_end: div_pts.append(crv_seg.PointAtEnd)
    return div_pts

def TestDivideCurveIntervalByLength():
    crv_ID=rs.GetObject("Select curve to divide",4,True)
    if not crv_ID: return
    tol=sc.doc.ModelAbsoluteTolerance
    #get interval on curve
    pt_0=rs.GetPointOnCurve(crv_ID,"Pick start point of interval")
    if not pt_0: return
    pt_1=rs.GetPointOnCurve(crv_ID,"Pick end point of interval")
    if not pt_1: return
    len=rs.GetReal("Segment length?",minimum=tol)
    if not len: return
    par_0=rs.CurveClosestPoint(crv_ID,pt_0)
    par_1=rs.CurveClosestPoint(crv_ID,pt_1)
    if par_0==par_1: return
    #get the underlying geometry from the curve object
    crv_geo=sc.doc.Objects.Find(crv_ID).Geometry
    #do the divide
    pts=DivideCrvIntervalByLength(crv_geo,par_0,par_1,len,True)
    if not pts: return
    #Add points to see
    rs.AddPoints(pts)
TestDivideCurveIntervalByLength()

Thanks a lot guys, I wound up modifying Mitch’s to return the parameters only.