Community
Fusion API and Scripts
Got a new add-in to share? Need something specialized to be scripted? Ask questions or share what you’ve discovered with the community.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

can't use fitpoints on splines created with nurbs

7 REPLIES 7
SOLVED
Reply
Message 1 of 8
den
Participant
548 Views, 7 Replies

can't use fitpoints on splines created with nurbs

Hi, I'm having problems manipulating splines that I've created with nurbs curves.this is a picture with a swoopy linethis is a picture with a swoopy line

The program takes a component and the names of subcomponents to connect (as in connector ends being connected with a wire). I want the script to update the spline if it already exists because it's used on a downstream sweep to make a wire.

 

The spline is created with a nurbs curve based on the component transforms with four points (beginning and end plus a point on the z vector for both). See pic.

 

Ultimately I've given up on being able to modify the existing entity and am going to just create the wire with the script too, but I should have been able to.

 

  • after being created with sketchFittedSplines.addByNurbsCurve(the_nurb), subsequent access to the created spline by the fitPoints property gives points that aren't actually on the spline.
  • accessing the startSketchPoint, endSketchPoint, or fitPoints properties causes the control points from the underlying nurbs to be re-interpreted by the spline as fitPoints and the spline is redrawn accordingly wrong.
  • there is no mechanism to drop in a replacement NurbsCurve3D object to a spline to update its geometry.

I'd like a method to redefine an existing spline's geometry, in general, starting from a NurbsCurve3D object. I would also like a method for the API to cough up a set of fitPoints that exactly reproduce the NurbsCurve3D, but I think that's actually asking for the same thing.

Also if anyone has ideas how to make a script fire when a subcomponent moves, I'd like to hear.

 

Tags (2)
7 REPLIES 7
Message 2 of 8
BrianEkins
in reply to: den

This functionality was never fully implemented and has all of the problems you're describing.  There's nothing that can be done to work around the issues.  Hopefully the API will be enhanced in the future to make this work correctly.

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
Message 3 of 8
den
Participant
in reply to: BrianEkins

How about being able to create a spline using fitpoints but be able to control the takeoff angle of the first segment? That would also work for me but I haven't found any way to do. Simply creating a two point spline with the API and then afterward manipulating the tangent handles of the spline like you would in the UI would get the job done. I saw one post suggesting you could find the line that represented the handles, but they don't really exist in the data structure unless you create the spline with fitPoints.

I've also tried a short line segment at the beginning then binding a tangent constraint to it, but there's no way to control if the spline takes off into the line or away from it.

Message 4 of 8
BrianEkins
in reply to: den

There is some functionality in the API that didn't get documented that will let you do this.  Below is a sample doing what you described.

 

def run(context):
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        des = adsk.fusion.Design.cast(app.activeProduct)
        root = des.rootComponent

        sk = root.sketches.add(root.xYConstructionPlane)
        
        pnts = adsk.core.ObjectCollection.create()
        pnts.add(adsk.core.Point3D.create(1,0,0))
        pnts.add(adsk.core.Point3D.create(5,1,0))
        crv = sk.sketchCurves.sketchFittedSplines.add(pnts)
        
        # In this case, because the curve was just created, the tangent handle
        # won't exist, but in the general case you need to first check to see
        # if it exists and then activate it if it doesn't.  The code below
        # does this.  This is getting it for the first fit point.
        tangentLine = adsk.fusion.SketchLine.cast(None)
        fitPnt = adsk.fusion.SketchPoint.cast(crv.fitPoints.item(0))
        if not crv.getTangentHandle(fitPnt):
            tangentLine = crv.activateTangentHandle(fitPnt)
        else:
            tangentLine = crv.getTangentHandle(fitPnt)
        
        # Modify the line to change the tangency.
        tangentLine.endSketchPoint.move(adsk.core.Vector3D.create(1,3,0))
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
Message 5 of 8
den
Participant
in reply to: BrianEkins

getTangentHandle is fairly well documented in fusion.py, but I can't understand what's going on with this cast stuff. It seems to just create a new object, yes?


        tangentLine = adsk.fusion.SketchLine.cast(None)
        fitPnt = adsk.fusion.SketchPoint.cast(crv.fitPoints.item(0))
        if not crv.getTangentHandle(fitPnt):
            tangentLine = crv.activateTangentHandle(fitPnt)
        else:
            tangentLine = crv.getTangentHandle(fitPnt)
  

 

Message 6 of 8
BrianEkins
in reply to: den

You're right about it being in the documentation.  I was thinking this was done later.

 

Anyway, the casting doesn't really do anything as far as the function of the code.  You can take them out and it will work the same.  I do it as a way to "declare" the variable type to Spyder so I get code hints for those variables.

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
Message 7 of 8
den
Participant
in reply to: BrianEkins

Thanks, it's working. This was my first approach that I failed at, but now that I understand NURBS math better, I'd actually prefer that method. It sounds like a known API bug, though, so hopefully my voice gets added to the list of people who'd like it fixed. Would have saved a lot of swearing.

Message 8 of 8
den
Participant
in reply to: BrianEkins

Maybe removing "cast" isn't so simple. When I tried to access the Sketchpoint of the tangent line directly, the system throws an error suggesting a bug in the proxy scheme, so I left it and documented the issue inline. Below is the make_spline function. This works as much as I've tested it.

def get_z_vec(xform):
    return xform.getAsCoordinateSystem()[3]

def get_3Dsketch(sketch_name, comp): # lie, makes it if doesn't exist
    # also get the xy plane because that matches the 3D axis set
    logger.info("found {} existing sketches".format(comp.sketches.count))
    the_sketch = comp.sketches.itemByName(sketch_name)
    if the_sketch is None:
        the_sketch = comp.sketches.add(comp.xYConstructionPlane)
        the_sketch.name = sketch_name
        logger.info("creating sketch {}".format(sketch_name))
    else:
        logger.info("found sketch {}".format(sketch_name))
    return the_sketch

def to_point3d(point):
    """Returns a copy of a Point3D, Sketchpoint, or proxied Sketchpoint
    as Point3D"""
    if isinstance(point, Point3D):
        return point.copy()
    if isinstance(point, SketchPoint):
        #cast is required because some bug in the proxy system
        #won't allow direct access to the sketchpoint properties
        #using a tangent line
        return adsk.fusion.SketchPoint.cast(point).geometry.copy()

def move_sketch_point(skpoint, dest_point):
    """move point1 to the location of point2 (without destroying stuff)"""
    p1 = to_point3d(skpoint)
    p2 = to_point3d(dest_point)
    skpoint.move(p1.vectorTo(p2))

def get_end_tangent_handles(the_spline):
    """Get tangent handle line of sketchpoint, activating if necessary"""
    start_tan = the_spline.getTangentHandle(the_spline.startSketchPoint)
    if not start_tan:
        start_tan = the_spline.activateTangentHandle(the_spline.startSketchPoint)
    end_tan = the_spline.getTangentHandle(the_spline.endSketchPoint)
    if not end_tan:
        end_tan = the_spline.activateTangentHandle(the_spline.endSketchPoint)
    return start_tan, end_tan

def make_spline(comp, target_name):
    """ makes a spline in component comp
    Search the occurances in comp for a name and draw a spline between
    their origins on a dedicated sketch.
    Create sketch if doesn't exist.
    Adjust existing spline if it already exists.
    """
    STRETCH = 1

    # Get list of connectors
    conns = [o for o in comp.allOccurrences if o.component.name == target_name]
    if len(conns) != 2:
        logger.error("expected 2 {}, got {}".format(CONN_NAME, len(conns)))
        return None

    #find start and end vectors
    start_frame = conns[0].transform
    end_frame = conns[1].transform

    # beginning and end are the origins of the connectors
    # exit vector is along the z axis of the connector * STRETCH
    start0 = start_frame.translation.asPoint()
    start1 = start0.copy()
    start_vec = get_z_vec(start_frame)
    start_vec.scaleBy(STRETCH) # really need a better parameter concept than "stretch"
    start1.translateBy(start_vec)

    end0 = end_frame.translation.asPoint()
    end1 = end0.copy()
    end_vec = get_z_vec(end_frame)
    end_vec.scaleBy(STRETCH)
    end1.translateBy(end_vec)

    points = adsk.core.ObjectCollection.create() # todo try to use simple list see what happens
    points.add(start0) # start of spline
    points.add(end0) # end of spline

    #create/find sketch in comp0
    spline_sketch = get_3Dsketch(SPLINE_SKETCH_NAME, comp)

    #find existing spline and adjust if exists, else make new
    spline_count = spline_sketch.sketchCurves.sketchFittedSplines.count
    logger.info("found {} splines".format(spline_count))
    if spline_count > 1:
        return

    if spline_count == 0:
        logger.info("creating new spline")
        the_spline = spline_sketch.sketchCurves.sketchFittedSplines.add(points)
    else: # spline count == 1
        logger.info("adjusting old spline")
        the_spline = spline_sketch.sketchCurves.sketchFittedSplines.item(0)
        move_sketch_point(the_spline.startSketchPoint, start0)
        move_sketch_point(the_spline.endSketchPoint, end0)

    #get the end tangent handles of the spline to adjust it to
    #take off on the z axis
    start_tan, end_tan = get_end_tangent_handles(the_spline)

    # at start point, the end tangent handle is toward spline and viceversa
move_sketch_point(start_tan.endSketchPoint, start1)
move_sketch_point(end_tan.startSketchPoint, end1) return the_spline

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report