Merging SketchPoints with constraints

Merging SketchPoints with constraints

william-c-anderson
Advocate Advocate
939 Views
4 Replies
Message 1 of 5

Merging SketchPoints with constraints

william-c-anderson
Advocate
Advocate

I wish to (programmatically) merge one SketchPoint with another, to wit:

newSketchPoint.merge(oldSketchPoint)

In this case:

  • newSketchPoint is fixed
  • oldSketchPoint is a part of an underdefined sketchCurve and has one or more constraints (e.g. coincident constraints) with other underdefined sketchCurves

When I try this merger (either programmatically or manually), the constraint engine may "fight" me. It looks as if the constraint engine, in some cases, cannot prioritize among the existing constraints and the merge request, and its behavior can vacillate. This behavior is particularly evident when a constrainee of oldSketchPoint is a circle with a fixed center, i.e. a circle with only a single DoF.

 

I know that if I manually delete the constraints between oldSketchPoint and its constrainees, merge the point and then reconstrain, things go reasonably smoothly in the above case.

 

The question is, where is some sample code to do this 'unconstrain, merge, reconstrain' process programmatically?

 

0 Likes
Accepted solutions (1)
940 Views
4 Replies
Replies (4)
Message 2 of 5

BrianEkins
Mentor
Mentor

I'm not aware of any existing sample code that does what you want.  Theoretically, it should be possible but it would involve writing quite a bit of code.  You would need to find all constraints that are currently associated with the point and then save their information in your own data structure, delete the constraints, do the merge, and then re-create all of the constraints using the data you saved.  It would be a fair amount of code just because of all of the types of constraints, although it would be limited to just those that can be associated with a point so maybe it's not too big of a list.

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

william-c-anderson
Advocate
Advocate

I've been digging into the constraint documentation, and I know a lot more now that this morning when I posted the above. I have an even more fundamental question regarding constraints:

 

Once a constraint is added to a sketch, can the SketchEntities involved in that constraint be retrieved?

 

As far as I can tell, once you add a constraint to a sketch, the information in that constraint (other than its type) is essentially invisible to a program running under the API.

0 Likes
Message 4 of 5

BrianEkins
Mentor
Mentor

Each constraint returns the entity or entities that it is constraining.  For example, the HorizontalPointsConstraint object has the point1 and point2 properties that return the to SketchPoint objects that it's forcing to be horizontal.  All of the constraint objects should have similar properties.

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

william-c-anderson
Advocate
Advocate
Accepted solution

Well, @BrianEkins , here's something I cooked up this morning to move constraints from one sketchEntity to another. It is not thoroughly tested (use at your own risk), and it doesn't handle the most complex constraints (CircularPattern, Offset, Polygon and RectangularPattern), but it does the job that I needed in 40-ish lines of code. I will say that any API interface which requires this kind of coding is rather complex. I hope someone finds this useful / instructive.

 

Here the code for the moveconstraints.py module:

import adsk.core, adsk.fusion, traceback

def remove_suffix(text, suffix):
	return text[:-len(suffix)] if text.endswith(suffix) else text

# NOTA BENE: SOME CONSTRAINTS ARE NOT HANDLED:
# CircularPattern, Offset, Polygon, RectangularPattern

# list of [Constraint name, list of property names to retrieve in "add call" order]
constraintNameList = [
  ['Coincident',        ['point','entity']],
  ['Collinear',         ['lineOne','lineTwo']],
  ['Concentric',        ['entityOne','entityTwo']],
  ['Equal',             ['curveOne','curveTwo']],
  ['Horizontal',        ['line']],
  ['HorizontalPoints',  ['pointOne','pointTwo']],
  ['MidPoint',          ['point','midPointCurve']],
  ['Parallel',          ['lineOne','lineTwo']],
  ['Perpendicular',     ['lineOne','lineTwo']],
  ['Smooth',            ['curveOne','curveTwo']],
  ['Symmetry',          ['entityOne','entityTwo','symmetryLine']],
  ['Tangent',           ['curveOne','curveTwo']],
  ['Vertical',          ['line']],
  ['VerticalPoints',    ['pointOne','pointTwo']]
]

# build dictionary lookup for args list at import time
constraintArgs = {}
for c in constraintNameList: constraintArgs[c[0]] = c[1]

# move constraints from one SketchEntity to another
def moveConstraints(toEntity, fromEntity):

  toEntity = adsk.fusion.SketchEntity.cast(toEntity)
  fromEntity = adsk.fusion.SketchEntity.cast(fromEntity)
  count = fromEntity.geometricConstraints.count

  # for each constraint in fromEntity
  for i in list(range(count)):

    # get constraint name and arguments
    fromConstraint = fromEntity.geometricConstraints.item(i)
    name = remove_suffix(fromConstraint.objectType.split('::')[-1],'Constraint')
    argNames = constraintArgs[name]
    args = []

    # get the values of the arguments in the argument list
    for a in argNames: args.append(eval('fromConstraint.'+a))

    # substitute toEntity for fromEntity
    for i in list(range(len(args))):
      if args[i] == fromEntity:
        args[i] = toEntity
        
    # add new constraint back to sketch and delete old constraint
    eval('toEntity.parentSketch.geometricConstraints.add'+name+'(*args)')
    fromConstraint.deleteMe()

and here is a simple-minded test driver script, to be run during an open sketch:

 

#Author-WCA
#Description-tests moveConstraint

import adsk.core, adsk.fusion, traceback

from .moveconstraints import moveConstraints

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        filt = 'SketchPoints,SketchCurves'
        fromEnt = ui.selectEntity('Select fromEntity', filt)
        if fromEnt != None:
            toEnt = ui.selectEntity('Select toEntity', filt)
            if toEnt != None:
                moveConstraints(toEnt.entity, fromEnt.entity)
        ui.messageBox('moveConstraint() complete')

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