Sweep1 is completely baffling

Hi All,

I have been banging my head against this simple bit of code for the better part of today and I only seem to find more issues.

What I’m trying to do is to take a closed curve. Generate a shape with two arcs and a line and sweep it along that curve. My code for this is shown here:

import Rhino
import rhinoscriptsyntax as rs
import math
import scriptcontext

def _makeArcFromAngle(plane, cPoint, radius, startAngle, endAngle):
    center = plane.PointAt(cPoint[0], cPoint[1])
    circ = Rhino.Geometry.Circle(plane, center, radius)
    angleInt = Rhino.Geometry.Interval(startAngle, endAngle)
    arc = Rhino.Geometry.Arc(circ, angleInt)
    return arc
def getMidpointFromCrv(crv):
    dom = crv.Domain
    return dom.Mid

def buildSharpBoss1(crv, radius):

    curve = rs.coercecurve(crv)
    if not curve:
        return 0
    subcurves = curve.DuplicateSegments()
    if len(subcurves)>1:
        focCurve = subcurves[0]
    else:
        focCurve = curve
    focCrvMidpoint = getMidpointFromCrv(focCurve)
    zVector = Rhino.Geometry.Vector3d(0,0,1)
    xDir = Rhino.Geometry.Vector3d.CrossProduct(focCurve.TangentAt(focCrvMidpoint),zVector)
    plane = Rhino.Geometry.Plane(focCurve.PointAt(focCrvMidpoint), xDir,zVector)
    lArc = _makeArcFromAngle(plane, (-radius, radius), radius, 3*math.pi/2, 2*math.pi)
    rArc = _makeArcFromAngle(plane, (radius, radius), radius, math.pi, 3*math.pi/2)
    profile = Rhino.Geometry.PolyCurve()
    profile.Append(lArc)
    profile.Append(rArc)
    baseLine = Rhino.Geometry.Line(profile.PointAtEnd,profile.PointAtStart)
    profile.Append(baseLine)
    sweepBrep = Rhino.Geometry.Brep.CreateFromSweep(curve,profile,True,scriptcontext.doc.ModelAbsoluteTolerance)
    output = []
    for i in sweepBrep:
        output.append(scriptcontext.doc.Objects.AddBrep(i))
    scriptcontext.doc.Views.Redraw()
    return output

if __name__ == "__main__":
    for i in rs.SelectedObjects():
        if rs.IsCurve:
            buildSharpBoss1(i,1)

Using that code with this model:
Sweep Glitch Demo.3dm (841.3 KB)

I get the result shown in this image:

Is this a glitch? I’d expect maybe the sweep would go out of control, but this doesn’t seem to make any sense to me. If I go in and push the profile back out to the document and just hit sweep1 with the default options everything looks great.

I also went further and, following the recommendation in the SDK manual went to create the sweep using the Rhino.Geometry.SweepOneRail. This code is the one I spent most of my time fiddling with. No matter what I do I never get anything out of PerformSweep, always just an empty array. Is there something I’m missing. I see in this SweepOneRail.PerformSweep Method (Curve, IEnumerable(Curve), IEnumerable(Double)) there is the IEnumerable(Double) that is labeled as crossSectionParameters but I can’t find any documentation saying what that amounts to. I’m using this manual http://4.rhino3d.com/5/rhinocommon/ is that the right one?

def buildSharpBoss2(crv, radius):
    curve = rs.coercecurve(crv)
    if not curve:
        return 0
    subcurves = curve.DuplicateSegments()
    if len(subcurves)>1:
        focCurve = subcurves[0]
    else: 
        focCurve = curve
    focCrvMidpoint = getMidpointFromCrv(focCurve)
    zVector = Rhino.Geometry.Vector3d(0,0,1)
    xDir = Rhino.Geometry.Vector3d.CrossProduct(focCurve.TangentAt(focCrvMidpoint),zVector)
    plane = Rhino.Geometry.Plane(focCurve.PointAt(focCrvMidpoint), xDir,zVector)
    lArc = _makeArcFromAngle(plane, (-radius, radius), radius, 3*math.pi/2, 2*math.pi)
    rArc = _makeArcFromAngle(plane, (radius, radius), radius, math.pi, 3*math.pi/2)
    profile = Rhino.Geometry.PolyCurve()
    profile.Append(lArc)
    profile.Append(rArc)
    baseLine = Rhino.Geometry.Line(profile.PointAtEnd,profile.PointAtStart)
    profile.Append(baseLine)

    sweep = Rhino.Geometry.SweepOneRail()
    sweep.AngleToleranceRadians = scriptcontext.doc.ModelAngleToleranceRadians
    sweep.ClosedSweep = True
    sweep.MiterType=1
    sweep.SweepTolerance = scriptcontext.doc.ModelAbsoluteTolerance
    sweep.SetToRoadlikeTop()
    sweep.SetRoadlikeUpDirection(Rhino.Geometry.Vector3d(0,0,1))
    sweepBreps = sweep.PerformSweep(curve, profile)
    output =[]
    for i in sweepBreps:
        output.append(scriptcontext.doc.Objects.AddBrep(i))
    scriptcontext.doc.Views.Redraw()
    return output

Hi Alex,

For best results, your one and only shape curve should be located at the start of the rail curve. I’ve modified your script to do this (see attached).

– Dale

TestAlex.py (2.2 KB)

1 Like

Dale,

That works great thanks very much!

Forgive my ignorance, but I have a couple questions. First, your _CurveMidParameter function seems like it does the same thing as my function but then you got the point back with the ClosestPoint Function. Why add this extra step?
Also, in the main function, where I find the plane to build the curves on, you added some unitize functions, how does this affect the code’s function?

Hi Alex,

This:

def getMidpointFromCrv(crv):
    dom = crv.Domain
    return dom.Mid

returns a point at the curve domain’s ‘mid’ parameter, which isn’t the mid point of the curve (in arc length terms). In the case of this script, where you simply don’t want to to create the shape curve at a kink, your code was probably adequate.

Also, when vector calculations, you almost always want to be doing them with unitized vectors. Many RhinoCommon functions return unitized vectors. But it doesn’t hurt to ensure that they are (unitized).

– Dale

That makes perfect sense. Thanks very much for all of your help.