Drag knife toolpath generation

Hi,

I’d like to generate a drag knife toolpath using python/grasshopper.

It basically comes down to this:

For each point on a line (with the distance of the points approaching 0), IF continuous, offset this point in the direction of the tangent by the distance the drag knife is from the centre. With all these points combined, you should get a new curve.

However, if it isn’t continuous, it should make a circle segment, with the radius being the distance the drag knife is from the centre.

Here is an illustration of what i mean:

Further down the road i’d also like to export this to gcode.

This is what i’ve written so far (or well, found it in a video) :

import rhinoscriptsyntax as rs

class TanLines:
def init (self, INcurve, INnumOfDivs):
self.curve = INcurve
self.numOfDivs = INnumOfDivs

def tanPoints(self):
    doms = rs.CurveDomain(self.curve)
    minDom = doms[0]
    maxDom = doms[1]


    for i in range(0, 30):
        param = (maxDom-minDom)/30 * i

        pt = rs.EvaluateCurve(self.curve,  param)
        tan = rs.CurveTangent(self.curve, param)
        tanPt = rs.VectorAdd(tan, pt)
        rs.AddLine(pt, tanPt)
 curve = rs.GetObject("Select a curve")
 obj = TanLines(curve, rs.GetReal("number", 30, 0, 100))
 obj.tanPoints();

Kind regards,
Thomas

Update: almost there.

This is the current script:

import rhinoscriptsyntax as rs
import Rhino
import scriptcontext
import System.Guid

class TanLines:
def init (self, INcurve, INnumOfDivs):
self.curve = INcurve
self.numOfDivs = int(INnumOfDivs)

def tanPoints(self):
    doms = rs.CurveDomain(self.curve)
    minDom = doms[0]
    maxDom = doms[1]
    points = Rhino.Collections.Point3dList(30)
    for i in range(0, self.numOfDivs):
        param = (maxDom-minDom)/self.numOfDivs * i
        pt = rs.EvaluateCurve(self.curve,  param)
        tan = rs.CurveTangent(self.curve, param)
        tanPt = rs.PointAdd(tan, pt)
        rs.AddLine(pt, tanPt,)
        points.Add(tanPt)
    print "Before sort ..."
    for point in points:
        print "point: {0}".format(point)
    nc = Rhino.Geometry.NurbsCurve.Create(False, 2, points)
    rc = Rhino.Commands.Result.Failure
    if nc and nc.IsValid:
        if scriptcontext.doc.Objects.AddCurve(nc)!=System.Guid.Empty:
            scriptcontext.doc.Views.Redraw()
            rc = Rhino.Commands.Result.Success
    return rc

curve = rs.GetObject(“Select a curve”)
obj = TanLines(curve, rs.GetReal(“divisions”, 200, 0, 10000))
obj.tanPoints()

This it what it generates:

dragknife.3dm (572.1 KB)

Any help as to how to get the distance of the translated points close to 0, and how to get a circle on places the curve is not continuous?

Regards,
Thomas

I’ve managed to generate the circles on places the curve is not contiuous, but it’s kind of hacky…
Hear me out: First you create a polygon, then you use the FilletCorner command with 0.05 radius,
then you divide the curve in 0,001 parts and run my script and it kinda creates that effect.

It’s hacky but whatever does the trick right?
If someone has tips/other solutions i’d greatly appreciate it!

New code can be found here: (doesn’t include the filletCorners command yet)

import rhinoscriptsyntax as rs
import Rhino
import scriptcontext
import System.Guid

class TanLines:
    def __init__ (self, INcurve, INdivideBy, INradius):
        self.curve = INcurve
        self.divideBy = float(INdivideBy)
        self.radius = int(INradius)

    def tanPoints(self):
        doms = rs.CurveDomain(self.curve)
        minDom = doms[0]
        maxDom = doms[1]
        points = Rhino.Collections.Point3dList(30)
        lengthCurve = rs.CurveLength(self.curve)
        self.numOfDivs = lengthCurve/self.divideBy

        for i in range(0, int(self.numOfDivs)):
            param = (maxDom-minDom)/self.numOfDivs * i

            pt = rs.EvaluateCurve(self.curve,  param)
            tan = rs.CurveTangent(self.curve, param)
            if i < 1:
                tan = rs.VectorScale(rs.CurveTangent(self.curve, param), -self.radius*2)
            elif i == self.numOfDivs-1:
                tan = rs.VectorScale(rs.CurveTangent(self.curve, param), self.radius*2)
            else:
                tan = rs.VectorScale(rs.CurveTangent(self.curve, param), self.radius)

            tanPt = rs.PointAdd(tan, pt)
            #rs.AddLine(pt, tanPt)
            points.Add(tanPt)
        print "Before sort ..."
        for point in points:
            print "point: {0}".format(point)
        nc = Rhino.Geometry.NurbsCurve.Create(False, 1, points)
        rc = Rhino.Commands.Result.Failure
        if nc and nc.IsValid:
            if scriptcontext.doc.Objects.AddCurve(nc)!=System.Guid.Empty:
                scriptcontext.doc.Views.Redraw()
                rc = Rhino.Commands.Result.Success
        return rc

curve = rs.GetObject("Select a curve")
obj = TanLines(curve, rs.GetReal("length", 200, 0, 10000), rs.GetReal("Radius", 200, 0, 10000))
obj.tanPoints()

Kind regards,
and please let this be a dialogue :slight_smile:

I’m very interested in your script and would like to try it. My question is: how do I load this script into Rhino?

Thanks,
-Justin

@jkindelspire,

copy the script code in your clipboard, then in Rhino type _EditPythonScript and paste it. Now just click on the green triangle to start the script.

c.