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:
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.
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.
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.
Solved! Go to Solution.
Solved by ekinsb. Go to Solution.
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.
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.
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,
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.