Announcements
Autodesk Community will be read-only between April 26 and April 27 as we complete essential maintenance. We will remove this banner once completed. Thanks for your understanding

Fit-point splines sharing a sketch point

rarora7777
Explorer Explorer
799 Views
3 Replies
Message 1 of 4

Fit-point splines sharing a sketch point

rarora7777
Explorer
Explorer

I have a network of interconnected 3D curves. The data is stored in two CSV files: one containing the 3D points and another containing sequences of indices into the set of points specifying curves. I'm able to load this data into Fusion and build spline curves (SketchFittedSpline curves). However, I want a user to be able to move these points interactively, and the splines to react to the user input. Therefore, I try to merge the logically duplicate points obtained via SketchFittedSpline.firPoints. This works sometimes, but fails with a runtime error at other times:

"RuntimeError: 5: Failed to solve. Please try revising dimensions or constraints."

 

Here's a small reproducible example:

#Author-Rahul Arora
#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

        points = adsk.core.ObjectCollection.create()
        points.add(adsk.core.Point3D.create(-1, 0, 0))
        points.add(adsk.core.Point3D.create( 0, 0, 0))
        points.add(adsk.core.Point3D.create( 1, 0, 0))
        points.add(adsk.core.Point3D.create( 0, 1, 0))
        
        design = product
        root = design.activeComponent
        sketch = root.sketches.add(root.xYConstructionPlane);
        
        idx1 = [0, 1, 2]
        idx2 = [1, 3]
        
        pts1 = adsk.core.ObjectCollection.create()
        for i in idx1 :        
            pts1.add(points[i])

        pts2 = adsk.core.ObjectCollection.create()        
        for i in idx2 :
            pts2.add(points[i])
            
        sketch.sketchCurves.sketchFittedSplines.add(pts1)
        spline1 = sketch.sketchCurves.sketchFittedSplines.item(sketch.sketchCurves.sketchFittedSplines.count - 1)
        
        sketch.sketchCurves.sketchFittedSplines.add(pts2)
        spline2 = sketch.sketchCurves.sketchFittedSplines.item(sketch.sketchCurves.sketchFittedSplines.count - 1)
        
        pts1 = spline1.fitPoints
        pts2 = spline2.fitPoints
        
        assert pts1.count == len(idx1)
        assert pts2.count == len(idx2)
        
        if pts1.item(1) != pts2.item(0) and pts1.item(1).geometry.distanceTo(pts2.item(0).geometry) < 1e-6:
            pts1.item(1).merge(pts2.item(0))

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

Lines 44-47 are just sanity checks and you can ignore them. Line 48 (the last line before the except statement) is where the error occurs.

 

What am I doing wrong?

Reply
Reply
0 Likes
800 Views
3 Replies
Replies (3)
Message 2 of 4

BrianEkins
Mentor
Mentor

The most efficient way to approach this is to create a sketch point for each of the coordinates and then use the Sketch point objects as input instead of Point3D objects when creating the spline.

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
Reply
Reply
0 Likes
Message 3 of 4

rarora7777
Explorer
Explorer

Hi Brian! Thanks for your quick response.

 

Actually, this is what I tried in the first place. But the sketchFittedSplines.add() function seems to create new sketch points. Here's an example:

#Author-Rahul Arora
#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

        points = adsk.core.ObjectCollection.create()
        points.add(adsk.core.Point3D.create(-1, 0, 0))
        points.add(adsk.core.Point3D.create( 0, 0, 0))
        points.add(adsk.core.Point3D.create( 1, 0, 0))
        points.add(adsk.core.Point3D.create( 0, 1, 0))
        
        
        design = product
        root = design.activeComponent
        sketch = root.sketches.add(root.xYConstructionPlane);
        
        for i in range(0, points.count) :
            sketch.sketchPoints.add(points.item(i))
        
        idx1 = [0, 1, 2]
        idx2 = [1, 3]
        
        pts1 = adsk.core.ObjectCollection.create()
        for i in idx1 :  
            pts1.add(sketch.sketchPoints.item(i))

        pts2 = adsk.core.ObjectCollection.create()
        for i in idx2 :
            pts2.add(sketch.sketchPoints.item(i))
            
        ui.messageBox('(before) #SketchPoints: ' + str(sketch.sketchPoints.count))
        
        sketch.sketchCurves.sketchFittedSplines.add(pts1)
        spline1 = sketch.sketchCurves.sketchFittedSplines.item(sketch.sketchCurves.sketchFittedSplines.count - 1)
        
        sketch.sketchCurves.sketchFittedSplines.add(pts2)
        spline2 = sketch.sketchCurves.sketchFittedSplines.item(sketch.sketchCurves.sketchFittedSplines.count - 1)

        
        ui.messageBox('(after) #SketchPoints: ' + str(sketch.sketchPoints.count))
        

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

 Th number of points increases from 5 (4 of my points + the origin, I guess) to 9.

 

The same effect can be observed in the UI as well. Create a few sketch points and then try to create a fit spline though them, and you'd see 2 sketch points at each location.

 

Is there a catch or workaround?

Reply
Reply
0 Likes
Message 4 of 4

rarora7777
Explorer
Explorer

However, I replaced the merge operation in the original code with coincidence constraints and that seems to work well. I tried on a complex example as well and it works well for me. But I'd still be interested to know why the merge operation fails, or if there is a better way to avoid duplicate points.

 

Here's the code with the coincidence constraints:

#Author-Rahul Arora
#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

        points = adsk.core.ObjectCollection.create()
        points.add(adsk.core.Point3D.create(-1, 0, 0))
        points.add(adsk.core.Point3D.create( 0, 0, 0))
        points.add(adsk.core.Point3D.create( 1, 0, 0))
        points.add(adsk.core.Point3D.create( 0, 1, 0))
        
        design = product
        root = design.activeComponent
        sketch = root.sketches.add(root.xYConstructionPlane);
        
        idx1 = [0, 1, 2]
        idx2 = [1, 3]
        
        pts1 = adsk.core.ObjectCollection.create()
        for i in idx1 :        
            pts1.add(points[i])

        pts2 = adsk.core.ObjectCollection.create()        
        for i in idx2 :
            pts2.add(points[i])
            
        sketch.sketchCurves.sketchFittedSplines.add(pts1)
        spline1 = sketch.sketchCurves.sketchFittedSplines.item(sketch.sketchCurves.sketchFittedSplines.count - 1)
        
        sketch.sketchCurves.sketchFittedSplines.add(pts2)
        spline2 = sketch.sketchCurves.sketchFittedSplines.item(sketch.sketchCurves.sketchFittedSplines.count - 1)
        
        pts1 = spline1.fitPoints
        pts2 = spline2.fitPoints
        
        assert pts1.count == len(idx1)
        assert pts2.count == len(idx2)
        
        if pts1.item(1) != pts2.item(0) and pts1.item(1).geometry.distanceTo(pts2.item(0).geometry) < 1e-6:
            sketch.geometricConstraints.addCoincident(pts1.item(1), pts2.item(0))

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

Maybe it'll help someone in the future.

Reply
Reply
0 Likes