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: 

Coincident constraints between model and sketch space

4 REPLIES 4
SOLVED
Reply
Message 1 of 5
thekestrel
1204 Views, 4 Replies

Coincident constraints between model and sketch space

Hi,

    I'm needing some advice for the best way to proceed with some constraints.

 

I've made a programatically created parameterized drawing which draws 3 perpendicular rectangles as seem below in Figure 1.

 

Figure 1:

Rects1.PNG

 

If I change one of the user parameters, I get something like what is seen in Figure 2, when what I actually want is what is in Figure 3.

 

Figure 2:

Notice how the 3 planes are now not centered on each other. Obviously this is because they are lacking a constraint to do so, but this is where I was having an issue.

Rects2.PNG

 

Figure 3:

To make this I manually constraints the center of each rectangle to the origin and now I can resize at will and everything stays centered.

Rects3.PNG

 

Here is the code to generate the image above. I have bolded the line where I tried to constrain the the sketch point back to the from point model space, but this errors out. 

import adsk.core, adsk.fusion, traceback, math

user_params = {}


def addRect(sketches, plane, center, length_params):
    # Reference the width and height user parameters values
    width = user_params[length_params[0]].value
    height = user_params[length_params[1]].value

    # Create the rectangle
    sketch = sketches.add(plane)
    sketchlines = sketch.sketchCurves.sketchLines;  
    #recLines = sketchlines.addCenterPointRectangle(center, adsk.core.Point3D.create(width / 2, height / 2, 0))
    p1 = adsk.core.Point3D.create(-width / 2, -height / 2, 0)
    p2 = adsk.core.Point3D.create(width / 2, height / 2, 0)
    recLines = sketchlines.addTwoPointRectangle(p1, p2)
  
    # Constrain the Rectangle to stay rectangular
    constraints = sketch.geometricConstraints
    constraints.addPerpendicular(recLines.item(0), recLines.item(1))
    constraints.addHorizontal(recLines.item(0))    
    constraints.addParallel(recLines.item(0), recLines.item(2))
    constraints.addParallel(recLines.item(1), recLines.item(3))

    # Add construction lines to constrain the rectangle to the center point
    lines = sketch.sketchCurves.sketchLines
    diagonal1 = lines.addByTwoPoints(recLines.item(0).startSketchPoint, recLines.item(2).startSketchPoint)  
    diagonal1.isConstruction = True
    diagonal1.isVisible = False
    diagonal2 = lines.addByTwoPoints(recLines.item(1).startSketchPoint, recLines.item(3).startSketchPoint)    
    diagonal2.isConstruction = True
    diagonal2.isVisible = False
  
    # Constrain the rectangle to be centered on the center point
    sketchpoints = sketch.sketchPoints; 
    sk_center = sketchpoints.add(center)
    sk_center.isfixed = True
    constraints.addCoincident(sk_center, diagonal1)
    constraints.addCoincident(sk_center, diagonal2)
    #constraints.addCoincident(sk_center, sketch.modelToSketchSpace(center))
    
    # Dimension the rectangle with the user parameters
    w = sketch.sketchDimensions.addDistanceDimension(recLines.item(0).startSketchPoint, recLines.item(0).endSketchPoint,
                                                     adsk.fusion.DimensionOrientations.HorizontalDimensionOrientation,
                                                     adsk.core.Point3D.create(0, height, 0)); 
    w.parameter.expression = length_params[0]    
    h = sketch.sketchDimensions.addDistanceDimension(recLines.item(1).startSketchPoint, recLines.item(1).endSketchPoint,
                                                     adsk.fusion.DimensionOrientations.VerticalDimensionOrientation,
                                                     adsk.core.Point3D.create(width, 0, 0));     
    h.parameter.expression = length_params[1]    
    

def createParam(design, name, value, units, comment):
    userValue = adsk.core.ValueInput.createByString(value)
    newParam = design.userParameters.add(name, userValue, units, comment)

    return newParam

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

        # Get the root component of the active design.
        rootComp = design.rootComponent

        # Create a new sketch on the xy plane.
        sketches = rootComp.sketches;
               
        cm = unitsMgr.defaultLengthUnits           
        user_params['g_width'] = createParam(design, 'g_width', '10cm', cm, '')
        user_params['g_height'] = createParam(design, 'g_height', '10cm', cm, '')
        
        center = adsk.core.Point3D.create(0, 5, 0)
        
        addRect(sketches, rootComp.xZConstructionPlane, center, ['g_width', 'g_height'])
        addRect(sketches, rootComp.xYConstructionPlane, center, ['g_height', 'g_width'])
        addRect(sketches, rootComp.yZConstructionPlane, center, ['g_width', 'g_height'])

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

  If someone can suggest how to fix it would be appreciated. If you have any other tips for a more elegant solution I'm open to suggestions.

 

    You can see for instance I commented out a 'addCenterPointRectangle' implementation and replaced it with an 'addTwoPointRectangle' solution thinking it may have been part of the problem with each rectangle creating its own center, but the rectangle has no persistent concept of a center, this just appears to be a convenience function for the creation of rectangles. I was surprised to see that no constraints are added by default the Rectangle creation methods, so its taken a page of code to recreate that.

 

Thanks in advance, Paul.

 

 

 

4 REPLIES 4
Message 2 of 5
ekinsb
in reply to: thekestrel

Thanks for the great explanation of the problem and the code.  You were so close.  If you just edit the line that failing to the line below it will work.

 

constraints.addCoincident(sk_center, sketch.originPoint)

What you're existing line is doing is just getting the XYZ coordinates for the model origin but in sketch space.  That function call returns a Point3D object which is just an API wrapper for the XYZ coordinates.  Creating a constraint requires a sketch point.  However, when you create a new sketch, the model construction point is automatically projected into the sketch, so you already have a sketch point there and the Sketch.originPoint property returns that sketch point.

 

I'm a little bit surprised that the rectangle methods aren't adding the constraints too. I would have expected it to, but now that it's out with the current behavior it becomes a big question as to whether we "fix" it or not.  If we do make it create the constraints it will break your program because your constraint placement will fail because it will be over-constraining the sketch.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 3 of 5
thekestrel
in reply to: ekinsb

Thanks Brian,

     That works like a champ. I was hoping someone like yourself would be able to answer quickly and save me an hour or two of fumbling around =). I'm not so worried about breaking my program if you fixed the constraints of the rectangles by default, but who knows if others rely on it being this way. I learned a lot by recreating it, but if you choose to leave the constraints out you should have example code that shows how to recreate them exactly the way they are implemented and save people a bunch of time. That would shore up some of the difference between the  API and whats available via the user interface.

 

     The only other question I had about that program is notice how I have set the diagonal1 and diagonal2 construction lines to invisible, they are still visible, why? When you create a rectangle from a center point manually, you don't see diagonals, but in sketch mode you can see they are used to constrain to the center point so I assume Fusion 360 is doing something similar. Looking at the sketch mode of this was how I tried to determine what to do to reverse engineer it programmatically, but full examples would be good. I think I got most-of-it right-ish, but its a lot of code =P. Without the constraints the rectangle primitive is more like 4 lines, because as soon as you move a point without constraints it ceases to be a rectangle, so having an unconstrainted rectangle primitive only saves me 1-2 lines of code from out-right making a constrained rectangle from basic lines.

 

Sincerely, Paul.

Message 4 of 5
ekinsb
in reply to: thekestrel

I think the isVisible property should probably be read-only because it's intended to let you determine if an existing sketch entity is visible or not and as far I'm aware it's only when creating a sketch on a face where the edges are projected into the and the origin construction point is also projected onto the sketch.  These entities are invisible until you move the mouse over them and they're available for selection to add dimension and constraints to.  Setting any sketch entity to be invisible is not currently supported and in your case the set doesn't do anything.

 

But I also don't see the behavior you described of using the "Center Rectangle" command.  When I create a centered rectangle, I see the diagonal lines displayed as construction lines and when I exit the sketch, the lines are still displayed.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 5 of 5
thekestrel
in reply to: ekinsb

Brian,

      Thanks again for the response. Apparently I'm seeing things now, as I also see the diagonal construction lines when using the Center Rectangle button.... *sigh* More coffee required =P...

 

Paul.

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