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: 

Multiple issues with as-built joint APIs

3 REPLIES 3
SOLVED
Reply
Message 1 of 4
rgoulden
473 Views, 3 Replies

Multiple issues with as-built joint APIs

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

 

 

3 REPLIES 3
Message 2 of 4
rgoulden
in reply to: rgoulden

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))

  

Message 3 of 4
marshaltu
in reply to: rgoulden

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 360 Developer
Autodesk, Inc.

Message 4 of 4
rgoulden
in reply to: marshaltu

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`).

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