Multiple issues with as-built joint APIs

Multiple issues with as-built joint APIs

Anonymous
812 Views
3 Replies
Message 1 of 4

Multiple issues with as-built joint APIs

Anonymous
Not applicable

I'm having some issues with using the API to get as-built joint. Specifically:

 

1. Occurrence.asBuiltJoints seems to not be returning a joint that is present.

2. Component.allAsBuiltJoints seems to be returning joints whose .occurrenceOne and .occurrenceTwo have incorrect .assemblyContexts. (Even though the immediate joint.assemblyContext is correct).

3. While trying to demonstrate 2. in the following script, I'm getting an InternalValidationError that I don't think I should be getting.

 

 

import adsk.core, adsk.fusion

def add_thingy(component, off=0):
  sketches = component.sketches
  xyPlane = component.xYConstructionPlane
  sketch = sketches.add(xyPlane)
  sketch.sketchCurves.sketchCircles.addByCenterRadius(adsk.core.Point3D.create(0,off,0), 5.0)
  extInput = component.features.extrudeFeatures.createInput(sketch.profiles.item(0), adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
  distance = adsk.core.ValueInput.createByReal(10.0)
  extInput.setDistanceExtent(False, distance)
  ext = component.features.extrudeFeatures.add(extInput)

def make_test_doc():
  # New document
  app = adsk.core.Application.get()
  doc = adsk.fusion.FusionDocument.cast(app.documents.add(0))
  rootOccs = doc.design.rootComponent.occurrences

  # With a repeated component
  matrix = adsk.core.Matrix3D.create()
  newOcc = rootOccs.addNewComponent(matrix)
  newComp = newOcc.component
  for i in range(3):
    t = matrix.translation
    t.x += 10
    matrix.translation = t
    rootOccs.addExistingComponent(newComp, matrix)

  # Put some stuff in that component
  matrix = adsk.core.Matrix3D.create()
  subOcc1 = newComp.occurrences.addNewComponent(matrix)
  subOcc2 = newComp.occurrences.addNewComponent(matrix)
  add_thingy(subOcc1.component, 0)
  add_thingy(subOcc2.component, 10)

  # And make an as-built joint between that stuff.
  abji = newComp.asBuiltJoints.createInput(subOcc1, subOcc2, None)
  abji.setAsRigidJointMotion()
  newComp.asBuiltJoints.add(abji)

  return doc


from time import sleep
def run(context):
  ui = None
  try:
    app = adsk.core.Application.get()
    ui  = app.userInterface
    doc = make_test_doc()
    root = doc.design.rootComponent

    some_occ = root.occurrences[2]
    ui.messageBox("%d == %d. Those should be the same, right?" % (
      some_occ.asBuiltJoints.count, # I'm getting 0 here, which misses the existing joint.
      some_occ.component.asBuiltJoints.count # I get 1 here, which is what I expect.
    ))

    # This next thing is causing some InternalValidationError here, which
    # seems like a seprate issue (unless I'm doing something wrong?)
    # The issue I was trying to demonstrate is it printing out
    # "joint.occ ctx: Component1:1" 4 times in a row, instead of
    # "Component1:1", "Component1:2", "Component1:3", "Component1:4"
    for joint in root.allAsBuiltJoints:
      ui.messageBox("""
joint context: %s
^ This seems correct, and steps through each relevant occurrences.
joint.occ ctx: %s
^ This should be the same, but instead it's stuck on the same occurence.
      """ % (
        joint.assemblyContext.name,
        joint.occurrenceOne.assemblyContext.name
      ))

  except:
    if ui:
      from traceback import format_exc
      ui.messageBox(format_exc(), "Exception", adsk.core.MessageBoxButtonTypes.OKButtonType, adsk.core.MessageBoxIconTypes.CriticalIconType)

 

Am I doing something wrong here, or have I encountered a bug?

If it helps: I'm using OS X, Fusion version 2.0.3410

 

 

0 Likes
Accepted solutions (1)
813 Views
3 Replies
Replies (3)
Message 2 of 4

Anonymous
Not applicable

Another (potentially related?) issue I encountered when trying to work around this: AsBuiltJoint.createForAssemblyContext(myContext) returns an object that does not always have the .occurrenceOne and .occurrenceTwo that I would expect (they're not within a subcontext of myContext).

 

FWIW, I'm currently working around the issues I observed with the following code. (I'd still like to hear if I'm doing something wrong and there's an easier way to find the right in-context occurrences).

 

    for joint in component.allAsBuiltJoints:
      # child = joint.occurrenceOne
      # parent = joint.occurrenceTwo
      # ^ That doesn't work, but the following workaround does. Not sure how fool-proof this is.
      def backtrack(occ):
        bt = []
        search = occ.assemblyContext
        while search.component != joint.assemblyContext.component:
          bt.append(list(search.assemblyContext.childOccurrences).index(search))
          search = search.assemblyContext
        search = joint.assemblyContext
        for i in reversed(bt):
          search = search.childOccurrences[i]
        return search
      child = joint.occurrenceOne.nativeObject.createForAssemblyContext(backtrack(joint.occurrenceOne))
      parent = joint.occurrenceTwo.nativeObject.createForAssemblyContext(backtrack(joint.occurrenceTwo))

  

0 Likes
Message 3 of 4

marshaltu
Autodesk
Autodesk
Accepted solution

Hello,

 

For the first issue, "some_occ" wasn't involved into AsBuilt joint yet. It should be correct to return 0 from "some_occ.asBuiltJoints.count". Please refer to the help for Occurrence.asBuiltJoints.

 

http://help.autodesk.com/view/fusion360/ENU/?guid=GUID-7B9EAEBD-189A-43FE-AD2E-BB812B24D21C

 

For the second issue, "InternalValidationError" was returned was because sick joint was created. It is our bug and I will log a defect to track it in our internal system. I modify the sample a little (marked as red) and now it should work well. The joints was created by using sub-occurrence1 and sub-occurrence2 in sub component(though it had 4 occurrences under root). We may not know which occurrence should be as its context. So the first one (occurrence1) was returned here. Maybe we can take context of joint into account when calculating the context of "joint.occ". However the context of joint and joint.occ are irrelevant in many cases. 

 

Thanks,

Marshal

 

 

#Author-
import adsk.core, adsk.fusion

def add_thingy(component, off=0):
  sketches = component.sketches
  xyPlane = component.xYConstructionPlane
  sketch = sketches.add(xyPlane)
  sketch.sketchCurves.sketchCircles.addByCenterRadius(adsk.core.Point3D.create(0,off,0), 5.0)
  extInput = component.features.extrudeFeatures.createInput(sketch.profiles.item(0), adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
  distance = adsk.core.ValueInput.createByReal(10.0)
  extInput.setDistanceExtent(False, distance)
  ext = component.features.extrudeFeatures.add(extInput)

def make_test_doc():
  # New document
  app = adsk.core.Application.get()
  doc = adsk.fusion.FusionDocument.cast(app.documents.add(0))
  rootOccs = doc.design.rootComponent.occurrences

  # With a repeated component
  matrix = adsk.core.Matrix3D.create()
  newOcc = rootOccs.addNewComponent(matrix)
  newComp = newOcc.component
  for i in range(3):
    t = matrix.translation
    t.x += 10
    matrix.translation = t
    rootOccs.addExistingComponent(newComp, matrix)

  # Put some stuff in that component
  matrix = adsk.core.Matrix3D.create()
  subOcc1 = newComp.occurrences.addNewComponent(matrix)
  subOcc2 = newComp.occurrences.addNewComponent(matrix)
  add_thingy(subOcc1.component, 0)
  add_thingy(subOcc2.component, 10)

  # And make an as-built joint between that stuff.
  abji = newComp.asBuiltJoints.createInput(subOcc1.createForAssemblyContext(newOcc), subOcc2.createForAssemblyContext(newOcc), None)
  abji.setAsRigidJointMotion()
  newComp.asBuiltJoints.add(abji)

  return doc


from time import sleep
def run(context):
  ui = None
  try:
    app = adsk.core.Application.get()
    ui  = app.userInterface
    doc = make_test_doc()
    root = doc.design.rootComponent

    some_occ = root.occurrences[2]
    ui.messageBox("%d == %d. Those should be the same, right?" % (
      some_occ.asBuiltJoints.count, # I'm getting 0 here, which misses the existing joint.
      some_occ.component.asBuiltJoints.count # I get 1 here, which is what I expect.
    ))

    # This next thing is causing some InternalValidationError here, which
    # seems like a seprate issue (unless I'm doing something wrong?)
    # The issue I was trying to demonstrate is it printing out
    # "joint.occ ctx: Component1:1" 4 times in a row, instead of
    # "Component1:1", "Component1:2", "Component1:3", "Component1:4"
    for joint in root.allAsBuiltJoints:
      ui.messageBox("""
joint context: %s
^ This seems correct, and steps through each relevant occurrences.
joint.occ ctx: %s
^ This should be the same, but instead it's stuck on the same occurence.
      """ % (
        joint.assemblyContext.name,
        joint.occurrenceOne.assemblyContext.name
      ))

  except:
    if ui:
      from traceback import format_exc
      ui.messageBox(format_exc(), "Exception", adsk.core.MessageBoxButtonTypes.OKButtonType, adsk.core.MessageBoxIconTypes.CriticalIconType)

 



Marshal Tu
Fusion Developer
>
Message 4 of 4

Anonymous
Not applicable

Thanks for the answers. Yes, I think it would be nice to be able to get in-context answers for joint.occurrenceOne/Two, because it's non-trivial to calculate that on our own.

 

It's worth noting that normal (not as-built) joints already return in-context results on these properties. (I originally ran into these issues when attempting to extend code that iterated through `Component.allJoints` to also process `Component.allAsBuiltJoints`).

0 Likes