How do I interpolate points on a spline curve?

How do I interpolate points on a spline curve?

Anonymous
Not applicable
1,197 Views
2 Replies
Message 1 of 3

How do I interpolate points on a spline curve?

Anonymous
Not applicable

Hello,

 

I would like to translate an occurrence to match its origin onto an arbitrary point on a Spline curve. I figure I will need to compute any point's worldGeometry  (not just the control points) on a spline curve.

 

I noticed in other modeling software, there are mainly 2 different approaches:

1) convert the bezier curve to a mesh then obtain points. Or

2) programmatically interpolate points given the curve

 

How can this be accomplished in Fusion 360? I am very new to its API and could not find the right function calls.

 

Any help much appreciated!

0 Likes
Accepted solutions (1)
1,198 Views
2 Replies
Replies (2)
Message 2 of 3

ekinsb
Alumni
Alumni
Accepted solution

You don't say where the spline curve is coming from.  It could be a spline in a sketch or an edge of a surface or solid.  I'm assuming it's from a sketch.  From a SketchFittedSpline you can call it's "worldGeometry" property which will return a NurbsCurve3D object in model space.  From the NurbsCurve3D object you can call it's "evaluator" property to get a CurveEvaluator3D object.  This supports the various functions to map between the parametric space of the curve into 3D model space.  You can use the functionality on the CurveEvaluator3D object to step along the curve in either model space or parametric space. It also supports getting an approximation of the curve within a specified tolerance using the getStrokes method. 


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
0 Likes
Message 3 of 3

joergDVRXK
Contributor
Contributor

Hi ekinsb,

 

this helped me a lot! What i didn't find out is how to get y-values at specific x-values I need to compare from two splines (top and bottom of an airfoil). I helped me with  vertical lines intersecting the splines. Is there a better way?

 

The first code is how i got to the strokes and draw a controlspline from the coords. Second code is the workaroud i did.

 

# Author-
# Description-

import adsk.core, adsk.fusion, adsk.cam, traceback


def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface

        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        root = design.rootComponent
        sketches = root.sketches
        planes = root.constructionPlanes

        # Airfoil to and bottom coordinates
        top = [
            (1, 0),
            (0.9500060048000001, 0.011403607702036947),
            (0.8998757757000001, 0.02118734215427778),
            (0.7996548491000002, 0.03759505829989787),
            (0.6994757059000001, 0.050663035770012375),
            (0.5993329668, 0.06082124092104867),
            (0.5492810503000002, 0.06434546516111436),
            (0.49923563900000006, 0.06734973008643069),
            (0.44919585720000005, 0.06990403022013698),
            (0.39918547390000003, 0.07010851421987976),
            (0.3491742149, 0.07038299274276187),
            (0.29918459820000004, 0.06892760662234321),
            (0.24922438000000002, 0.06512240436796102),
            (0.19928242640000005, 0.059857316345244056),
            (0.1493543589, 0.05348231516988902),
            (0.09945343810000001, 0.04493748377721448),
            (0.07452524550000002, 0.03888520734961975),
            (0.049617444200000006, 0.031203058454637563),
            (0.024739541800000004, 0.021131096555326523),
            (0.012328112600000002, 0.013895287735577513),
            (0.0, 0.0),
        ]
        bottom = [
            (0.0, 0.0),
            (0.012702165999999999, -0.010605030826180075),
            (0.025281242, -0.014611209167270196),
            (0.050333835, -0.01696454993041875),
            (0.0753478225, -0.017248250595970918),
            (0.1003467035, -0.016722092092898405),
            (0.1503105225, -0.013850091522683114),
            (0.20025923499999998, -0.010168231783843155),
            (0.2501975035, -0.005926469409904652),
            (0.3001542355, -0.002674534908729641),
            (0.35009548799999995, 0.0014072552837521369),
            (0.400038792, 0.005379064601482417),
            (0.4500158525, 0.00754118861648348),
            (0.49999645649999996, 0.00951334566600468),
            (0.5499785524999999, 0.011405516624797524),
            (0.5999751954999999, 0.01251782319898882),
            (0.6999889964999999, 0.013642627599856422),
            (0.8000770245, 0.010788123986987967),
            (0.900196198, 0.006263910730164931),
            (0.9502668814999997, 0.00340690755196121),
            (1, 0),
        ]

        # make a sketch
        plane = root.xYConstructionPlane
        sketch = root.sketches.add(plane)

        # collections for curvepoints
        coll_top = adsk.core.ObjectCollection.create()
        coll_bottom = adsk.core.ObjectCollection.create()
        coll_top_bottom = adsk.core.ObjectCollection.create()

        # create points
        for coords in top:
            point = adsk.core.Point3D.create(coords[0], coords[1], 0)
            coll_top.add(point)
            coll_top_bottom.add(point)

        for i, coords in enumerate(bottom):
            point = adsk.core.Point3D.create(coords[0], coords[1], 0)
            coll_bottom.add(point)
            if i > 0:
                coll_top_bottom.add(point)

        # sketch spline to get good curve at the nose, break it at the nose to get separate intersections later
        spline = sketch.sketchCurves.sketchFittedSplines.add(coll_top_bottom)
        spline.isClosed = False
        breakline = sketch.sketchCurves.sketchLines.addByTwoPoints(
            adsk.core.Point3D.create(-0.1, 0, 0), adsk.core.Point3D.create(0.1, 0, 0)
        )
        splines = spline.breakCurve(coll_top_bottom.item(coll_top.count + 1))
        endPoint = splines[1].addFitPoint(0.999999)
        splines[0].isFixed = True
        sketch.geometricConstraints.addCoincident(endPoint, splines[0].startSketchPoint)
        splines[1].isFixed = True
        breakline.deleteMe()

        # get NurbsCurve3d
        nurb_top = splines[0].worldGeometry
        nurb_bottom = splines[1].worldGeometry

        # get CurveEvaluator3D
        curveEvaluator_top = nurb_top.evaluator
        curveEvaluator_bottom = nurb_bottom.evaluator

        # get Parameters at start and end of splines
        param_top1 = curveEvaluator_top.getParameterAtPoint(splines[0].startSketchPoint.worldGeometry)
        param_top2 = curveEvaluator_top.getParameterAtPoint(splines[0].endSketchPoint.worldGeometry)
        param_bottom1 = curveEvaluator_top.getParameterAtPoint(splines[1].startSketchPoint.worldGeometry)
        param_bottom2 = curveEvaluator_top.getParameterAtPoint(splines[1].endSketchPoint.worldGeometry)

        # get strokes
        strokes_top = curveEvaluator_top.getStrokes(param_top1[1], param_top2[1], 0.001)
        strokes_bottom = curveEvaluator_bottom.getStrokes(param_bottom1[1], param_bottom2[1], 0.001)

        # extract coords
        coords_top = [strokes_top[1][i].asArray() for i in range(len(strokes_top[1]))]
        coords_bottom = [strokes_bottom[1][i].asArray() for i in range(len(strokes_bottom[1]))]

        # sketch spline from that for comparing
        sketch2 = sketches.add(plane)

        coll_top2 = adsk.core.ObjectCollection.create()
        for coords in coords_top:
            point = adsk.core.Point3D.create(coords[0], coords[1], coords[2])
            coll_top2.add(point)

        spline2 = sketch2.sketchCurves.sketchFittedSplines.add(coll_top2)

    except:
        if ui:
            ui.messageBox("Failed:\n{}".format(traceback.format_exc()))

 

 

 

 

workaround:

 

import adsk.core, adsk.fusion, adsk.cam, traceback


def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface

        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        root = design.rootComponent
        sketches = root.sketches
        planes = root.constructionPlanes

        # Airfoil to and bottom coordinates
        top = [
            (1, 0),
            (0.9500060048000001, 0.011403607702036947),
            (0.8998757757000001, 0.02118734215427778),
            (0.7996548491000002, 0.03759505829989787),
            (0.6994757059000001, 0.050663035770012375),
            (0.5993329668, 0.06082124092104867),
            (0.5492810503000002, 0.06434546516111436),
            (0.49923563900000006, 0.06734973008643069),
            (0.44919585720000005, 0.06990403022013698),
            (0.39918547390000003, 0.07010851421987976),
            (0.3491742149, 0.07038299274276187),
            (0.29918459820000004, 0.06892760662234321),
            (0.24922438000000002, 0.06512240436796102),
            (0.19928242640000005, 0.059857316345244056),
            (0.1493543589, 0.05348231516988902),
            (0.09945343810000001, 0.04493748377721448),
            (0.07452524550000002, 0.03888520734961975),
            (0.049617444200000006, 0.031203058454637563),
            (0.024739541800000004, 0.021131096555326523),
            (0.012328112600000002, 0.013895287735577513),
            (0.0, 0.0),
        ]
        bottom = [
            (0.0, 0.0),
            (0.012702165999999999, -0.010605030826180075),
            (0.025281242, -0.014611209167270196),
            (0.050333835, -0.01696454993041875),
            (0.0753478225, -0.017248250595970918),
            (0.1003467035, -0.016722092092898405),
            (0.1503105225, -0.013850091522683114),
            (0.20025923499999998, -0.010168231783843155),
            (0.2501975035, -0.005926469409904652),
            (0.3001542355, -0.002674534908729641),
            (0.35009548799999995, 0.0014072552837521369),
            (0.400038792, 0.005379064601482417),
            (0.4500158525, 0.00754118861648348),
            (0.49999645649999996, 0.00951334566600468),
            (0.5499785524999999, 0.011405516624797524),
            (0.5999751954999999, 0.01251782319898882),
            (0.6999889964999999, 0.013642627599856422),
            (0.8000770245, 0.010788123986987967),
            (0.900196198, 0.006263910730164931),
            (0.9502668814999997, 0.00340690755196121),
            (1, 0),
        ]

        # make a sketch
        plane = root.xYConstructionPlane
        sketch = root.sketches.add(plane)

        # collections for curvepoints
        coll_top = adsk.core.ObjectCollection.create()
        coll_bottom = adsk.core.ObjectCollection.create()
        coll_top_bottom = adsk.core.ObjectCollection.create()

        # create points
        for coords in top:
            point = adsk.core.Point3D.create(coords[0], coords[1], 0)
            coll_top.add(point)
            coll_top_bottom.add(point)

        for i, coords in enumerate(bottom):
            point = adsk.core.Point3D.create(coords[0], coords[1], 0)
            coll_bottom.add(point)
            if i > 0:
                coll_top_bottom.add(point)

        # sketch spline to get good curve at the nose, break it at the nose to get separate intersections later
        spline = sketch.sketchCurves.sketchFittedSplines.add(coll_top_bottom)
        spline.isClosed = False
        breakline = sketch.sketchCurves.sketchLines.addByTwoPoints(
            adsk.core.Point3D.create(-0.1, 0, 0), adsk.core.Point3D.create(0.1, 0, 0)
        )
        splines = spline.breakCurve(coll_top_bottom.item(coll_top.count + 1))
        endPoint = splines[1].addFitPoint(0.999999)
        splines[0].isFixed = True
        sketch.geometricConstraints.addCoincident(endPoint, splines[0].startSketchPoint)
        splines[1].isFixed = True
        breakline.deleteMe()

        # get length of rootline to calculate vertical lines through the Airfoil
        rootline = sketch.sketchCurves.sketchLines.addByTwoPoints(
            splines[0].endSketchPoint, splines[0].startSketchPoint
        )
        rootline.isConstruction = True
        lines_count = 20

        x_values = [(rootline.length / lines_count) * i for i in range(lines_count + 1)]

        # draw vertical lines
        coll_lines = adsk.core.ObjectCollection.create()
        for x in x_values:
            p1 = adsk.core.Point3D.create(x, -10, 0)
            p2 = adsk.core.Point3D.create(x, 10, 0)
            line = sketch.sketchCurves.sketchLines.addByTwoPoints(p1, p2)
            coll_lines.add(line)

        # get the intersection coordinates
        intersectionPoints_top = (splines[0].intersections(coll_lines))[2]
        intersectionPoints_bottom = (splines[1].intersections(coll_lines))[2]

        top_array = [i.asArray() for i in intersectionPoints_top]
        bottom_array = [i.asArray() for i in intersectionPoints_bottom]

        # get coords of the middleline
        midcoords = [(top_array[i][0], 0.5 * (top_array[i][1] + bottom_array[i][1]), 0) for i in range(len(top_array))]
        midcoords.insert(0, (0, 0, 0))

        # factor for y-scaling from midcoord
        factor = 1.5

        # calculate coordinates of the thickened airfoil
        top_new = [
            (top_array[i][0], midcoords[i][1] + factor * (top_array[i][1] - midcoords[i][1]), 0)
            for i in range(1, len(top_array))
        ]
        bottom_new = [
            (bottom_array[i][0], midcoords[i][1] + factor * (bottom_array[i][1] - midcoords[i][1]), 0)
            for i in range(len(bottom_array))
        ]

        thick_coords = list(reversed(top_new)) + list(bottom_new)

        # draw the splines
        coll_midline = adsk.core.ObjectCollection.create()
        coll_thick = adsk.core.ObjectCollection.create()

        coll_midline.add(adsk.core.Point3D.create(0, 0, 0))
        for coord in midcoords:
            point = adsk.core.Point3D.create(coord[0], coord[1], 0)
            coll_midline.add(point)
        coll_midline.add(adsk.core.Point3D.create(1, 0, 0))

        sketch.sketchCurves.sketchFittedSplines.add(coll_midline)

        for coord in thick_coords:
            point = adsk.core.Point3D.create(coord[0], coord[1], 0)
            coll_thick.add(point)

        sketch.sketchCurves.sketchFittedSplines.add(coll_thick)

 

 

 

 

0 Likes