NurbsCurve3D won't eat its own dog food

GRSnyder
Collaborator

NurbsCurve3D won't eat its own dog food

GRSnyder
Collaborator
Collaborator

I've been using Onur R. Bingol's very nice NURBS-Python package to do some NURBS-based curve fitting. I do the fitting in NURBS-Python (aka geomdl) and then just copy the parameters over into NurbsCurve3Ds for use inside Fusion 360.

 

Generally speaking, this works fine. However, I haven't been able to get a loop curve to port over correctly; Fusion 360 complains about the knot vector.

 

I thought, "No problem, I'll just look at some existing NurbsCurve3D loops and see exactly what they expect." But despite trying to emulate what I was getting from NurbsCurve3D.getData(), I still didn't have any luck creating a valid loop.

 

OK, all the above is background. Here's the crux of the issue: even if you feed back the exact data you receive from NurbsCurve3D.getData() to NurbsCurve3D.createRational(), it still doesn't work. The script below demonstrates. (And again, this is only for loops, aka periodic curves.)

 

getData() returns a control point vector that includes a duplicate of the first control point at the end of the list. Does createRational() expect this?

 

The knot vector also looks a bit odd. It starts with N zeroes (where N is the degree) which seems standard. But the end is just a single 1.0, which is different from the knots returned by nonperiodic curves.

 

Is there an example somewhere that shows a NURBS loop being created?

 

import adsk.core as core
import adsk.fusion as fusion
import traceback

points = [
    core.Point3D.create(0.5, 0, 0),
    core.Point3D.create(0, 0.5, 0),
    core.Point3D.create(-0.5, 0, 0),
    core.Point3D.create(0, -0.5, 0),
]

def toObjectCollection(iterable):
    collection = core.ObjectCollection.create()
    for item in iterable:
        collection.add(item)
    return collection

def run(context):

    try:
        app = core.Application.get()
        root = app.activeProduct.rootComponent

        # Create sketch and curve loop
        sketch = root.sketches.add(root.xYConstructionPlane)
        fittedSplines = sketch.sketchCurves.sketchFittedSplines
        spline = fittedSplines.add(toObjectCollection(points))
        spline.isClosed = True
        nurbsCurve = spline.geometry

        # Harvest NURBS parameters
        ok, controlPoints, degree, knots, rational, weights, periodic = nurbsCurve.getData()

        # Verify that parameters are as expected
        assert ok, "Unable to read NURBS data"
        assert len(controlPoints) == 25, "Unexpected number of control points"
        assert controlPoints[0].isEqualTo(controlPoints[-1]), "First and last point not equal"
        assert degree == 5, "Unexpected degree"
        assert len(knots) == len(controlPoints), "nControlPoints != nKnots"
        assert all(w == 1.0 for w in weights), "Some weights not 1.0"
        assert periodic, "Unexpected nonloop curve"

        # Copy all arrays and points, just to verify that this is not the issue
        controlPoints = [point.copy() for point in controlPoints]
        knots = [knot for knot in knots]
        weights = [weight for weight in knots]

        # Throws "RuntimeError 3: Invalid argument controlPoints"
        dupCurve = core.NurbsCurve3D.createRational(controlPoints, degree, knots, weights, periodic)

    except:
        if app.userInterface:
            app.userInterface.messageBox('Failed:\n{}'.format(traceback.format_exc()))
0 Likes
Reply
Accepted solutions (1)
418 Views
2 Replies
Replies (2)

KrisKaplan
Autodesk
Autodesk
Accepted solution

Hi,

 

I can reproduce the issue you described. The problem should be limited to the case of periodic curves. The argument validation was falling into the wrong case for these. I filed issue FUS-77775 for this, and it will be fixed for the next normal release later this month.

 

Kris



Kris Kaplan
0 Likes

GRSnyder
Collaborator
Collaborator

Awesome, thanks for the update, @KrisKaplan!

0 Likes