- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I need a way to determine the appropriate angle to use when creating a face to sketch profile CenterKeyPoint joint using a face from a body
that is not aligned with x, y, or z axis.
Run the script below and step through the history to see the problem I need to solve or view the screencast.
Thanks in advance!
import adsk.core, adsk.fusion, traceback
#==============================================================================
# class used to pass position and size of desired rectangle taking default units as input
#==============================================================================
class rect:
def __init__(self, insert=(0, 0), size=(0, 0)):
app = adsk.core.Application.get()
design = adsk.fusion.Design.cast(app.activeProduct)
self.unitsManager = design.unitsManager
x = self.convertToInternal(insert[0])
y = self.convertToInternal(insert[1])
self.defaultLength = size[0]
self.defaultWidth = size[1]
self.length = self.convertToInternal(size[0])
self.width = self.convertToInternal(size[1])
self.startPoint = adsk.core.Point3D.create(x, -y, 0)
self.endPoint = adsk.core.Point3D.create(x + self.length, -(y + self.width), 0)
def convertToInternal(self, valueIn):
return self.unitsManager.convert(valueIn, self.unitsManager.defaultLengthUnits, self.unitsManager.internalUnits)
#==============================================================================
# find the largest face and it's length & width edges for a body
#==============================================================================
class findMatchFace:
def __init__(self, body):
faceAreas = []
for face in body.faces:
faceAreas.append(face.area)
idx = faceAreas.index(max(faceAreas))
self.face = body.faces.item(idx)
edgeLengths = []
for edge in self.face.edges:
edgeLengths.append(edge.length)
idx = edgeLengths.index(max(edgeLengths))
self.edge = self.face.edges.item(idx)
self.lengthVector = self.edgeToVector(self.edge)
self.widthVector = None
for edge in self.face.edges:
vector = self.edgeToVector(edge)
if vector.isPerpendicularTo(self.lengthVector):
self.widthVector = vector
break
def edgeToVector(self, edge):
v1x = edge.startVertex.geometry.x
v1y = edge.startVertex.geometry.y
v1z = edge.startVertex.geometry.z
v2x = edge.endVertex.geometry.x
v2y = edge.endVertex.geometry.y
v2z = edge.endVertex.geometry.z
return adsk.core.Vector3D.create(v2x-v1x, v2y-v1y, v2z-v1z)
#==============================================================================
# class used to map component bodies to a board on xy plane
#==============================================================================
class mapper:
def __init__(self):
self.sketch = None
self.boardNum = 0
self.app = adsk.core.Application.get()
self.ui = self.app.userInterface
self.design = adsk.fusion.Design.cast(self.app.activeProduct)
self.rootComp = self.design.rootComponent
self.mapOcc = self.rootComp.occurrences.addNewComponent(adsk.core.Matrix3D.create())
self.mapComp = self.mapOcc.component
self.mapComp.name = 'map'
self.xYPlane = self.mapComp.xYConstructionPlane
lib = self.app.materialLibraries.itemByName('Fusion 360 Material Library')
self.paperMaterial = lib.materials.itemByName('Paper')
def _newSketch(self, compOcc=None, offset=0):
try:
if offset == 0:
self.sketch = compOcc.component.sketches.add(self.xYPlane)
else:
offsetValue = adsk.core.ValueInput.createByReal(offset)
planes = self.mapOcc.component.constructionPlanes
planeInput = planes.createInput()
planeInput.setByOffset(self.xYPlane, offsetValue)
plane = planes.add(planeInput)
self.sketch = compOcc.component.sketches.add(plane)
self.sketchLines = self.sketch.sketchCurves.sketchLines
self.sketchTexts = self.sketch.sketchTexts
except:
self.ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
def _add(self, rect):
sketchLines = self.sketchLines.addTwoPointRectangle(rect.startPoint, rect.endPoint)
return sketchLines
def addBoard(self, rect):
self.boardOcc = self.mapComp.occurrences.addNewComponent(adsk.core.Matrix3D.create())
self.boardComp = self.boardOcc.component
self.boardNum += 1
self.boardName = 'Board {}'.format(self.boardNum)
self.boardComp.name = self.boardName
self._newSketch(compOcc=self.boardOcc)
self.sketch.name = self.boardName
self._add(rect)
idx = len(self.sketch.profiles) - 1
prof = self.sketch.profiles.item(idx)
# Create the patch feature
patches = self.boardComp.features.patchFeatures
patchInput = patches.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
patchFeature = patches.add(patchInput)
self.boardBody = patchFeature.bodies.item(0)
self.boardBody.name = self.boardName
self.boardBody.material = self.paperMaterial
def addComponent(self, source, targetRect, name):
self.body = source.body
self.compOcc = self.boardComp.occurrences.addNewComponent(adsk.core.Matrix3D.create())
self.compComp = self.compOcc.component
self.compComp.name = name
self._newSketch(self.boardOcc)
self.sketch.name = '{}{}'.format(name, "_target")
self._add(targetRect)
idx = len(self.sketch.profiles) - 1
targetProf = self.sketch.profiles.item(idx)
self.mapJoint(self.compOcc, targetProf, source)
def mapJoint(self, compOcc, targetProf, source):
self.body.copyToComponent(compOcc)
self.bodyOcc = compOcc.bRepBodies.item(0)
matchFace = findMatchFace(self.bodyOcc)
# Create the first joint geometry with the end face
geo0 = adsk.fusion.JointGeometry.createByPlanarFace(matchFace.face, None, adsk.fusion.JointKeyPointTypes.CenterKeyPoint)
# Create the second joint geometry with the sketch profile
geo1 = adsk.fusion.JointGeometry.createByProfile(targetProf, None, adsk.fusion.JointKeyPointTypes.CenterKeyPoint)
# Create joint input
joints = self.rootComp.joints
jointInput = joints.createInput(geo0, geo1)
jointInput.angle = source.angle
jointInput.isFlipped = True
# Create the joint
joints.add(jointInput)
self.bodyOcc.material = self.paperMaterial
#==============================================================================
# This class will create a body which will be moved to serveral alignments with
# respect to x,y,z axis, copied, then mapped to a sketch profile with a joint.
#==============================================================================
class createSourceComponent:
def __init__(self):
app = adsk.core.Application.get()
actDoc = app.activeDocument.dataFile
if actDoc != None:
app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
design = adsk.fusion.Design.cast(app.activeProduct)
self.rootComp = design.rootComponent
occs = self.rootComp.occurrences
for occ in occs:
if occ.component.name.startswith('map'):
occ.deleteMe()
break
for occ in occs:
if occ.component.name.startswith('map'):
occ.deleteMe()
break
rootComp = design.rootComponent
mapSourceOcc = rootComp.occurrences.addNewComponent(adsk.core.Matrix3D.create())
self.mapSourceComp = mapSourceOcc.component
self.mapSourceComp.name = 'mapSource'
sketches = self.mapSourceComp.sketches
sketch = sketches.add(self.rootComp.xYConstructionPlane)
sketchLines = sketch.sketchCurves.sketchLines
compRect = rect(insert=(0, -4), size=(18, 4))
self.length = compRect.defaultLength
self.width = compRect.defaultWidth
self.thick = .75 * 2.54
sketchLines.addTwoPointRectangle(compRect.startPoint, compRect.endPoint)
self.targetProf1 = sketch.profiles.item(0)
profiles = adsk.core.ObjectCollection.create()
profiles.add(self.targetProf1)
extrudeFeats = self.mapSourceComp.features.extrudeFeatures
extrudeFeature = extrudeFeats.addSimple(profiles,
adsk.core.ValueInput.createByReal(self.thick),
adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
self.body = extrudeFeature.bodies.item(0)
self.bodies = adsk.core.ObjectCollection.create()
self.bodies.add(extrudeFeature.bodies.item(0))
chkRotate = checkRotate(self.body)
self.isRotate = chkRotate.isRotate
self.angle = chkRotate.angle
self.odd = chkRotate.odd
def move(self, vector):
transform = adsk.core.Matrix3D.create()
transform.translation = vector
moveFeats = self.mapSourceComp.features.moveFeatures
moveFeatureInput = moveFeats.createInput(self.bodies, transform)
moveFeats.add(moveFeatureInput)
chkRotate = checkRotate(self.body)
self.isRotate = chkRotate.isRotate
self.angle = chkRotate.angle
self.odd = chkRotate.odd
def rotate(self, angle, axis, origin):
transform = adsk.core.Matrix3D.create()
transform.setToRotation(angle, axis, origin)
moveFeats = self.mapSourceComp.features.moveFeatures
moveFeatureInput = moveFeats.createInput(self.bodies, transform)
moveFeats.add(moveFeatureInput)
chkRotate = checkRotate(self.body)
self.isRotate = chkRotate.isRotate
self.angle = chkRotate.angle
self.odd = chkRotate.odd
#==============================================================================
# check body orientation with respect to X,Y,Z axis & determine if rotation is
# required when assemble joint is created with sketch profile in XY plane
#==============================================================================
RadFor90 = round(1.5707963267948966, 3) # 90 deg in radians
class checkRotate:
def __init__(self, body):
source = findMatchFace(body)
lengthVector = source.lengthVector
widthVector = source.widthVector
app = adsk.core.Application.get()
design = adsk.fusion.Design.cast(app.activeProduct)
xVector = design.rootComponent.xConstructionAxis.geometry.direction
yVector = design.rootComponent.yConstructionAxis.geometry.direction
zVector = design.rootComponent.zConstructionAxis.geometry.direction
aList = []
aList.append(round(lengthVector.angleTo(xVector), 3)) # 0 - lengthToX
aList.append(round(widthVector.angleTo(xVector), 3)) # 1 - widthToX
aList.append(round(lengthVector.angleTo(yVector), 3)) # 2 - lengthToY
aList.append(round(widthVector.angleTo(yVector), 3)) # 3 - widthToY
aList.append(round(lengthVector.angleTo(zVector), 3)) # 4 - lengthToZ
self.odd = self.chkOriented(aList)
aList.append(round(widthVector.angleTo(zVector), 3)) # 5 - widthToZ
self.isRotate = False
self.angle = adsk.core.ValueInput.createByReal(0)
t1 = (aList[0] == RadFor90 and aList[1] == 0)
t2 = (aList[1] == RadFor90 and aList[0] == 0 and aList[4] != RadFor90)
t3 = ((aList[0] == RadFor90) and (aList[1] == RadFor90)) and ((aList[4] != 0) and (aList[2] != RadFor90))
t4 = (aList[0] == RadFor90 and aList[3] == RadFor90)
# print('t1 {} t2 {} t3 {} t4 {}'.format(t1, t2, t3, t4))
if (t1 or t2 or t3 or t4):
self.angle = adsk.core.ValueInput.createByReal(-RadFor90)
self.isRotate = True
print('>*>*>*>* -90 angle rotate required!')
if self.odd:
print('>*>*>*>* special angle required!')
print('>>>>> {} - rotate: {} odd: {} lengthToX: {} widthToX: {} lengthToY: {} widthToY: {} lengthToZ: {} widthToZ: {}'.format(
body.name,self.isRotate,self.odd, aList[0], aList[1], aList[2], aList[3], aList[4], aList[5]))
def chkOriented(self, aList):
hasOdd = False
hasNormal = False
for angle in aList:
if angle != RadFor90 and angle != 0:
hasOdd = True
else:
hasNormal = True
return hasOdd and not hasNormal
#==============================================================================
# Create a demo showing the issue I am having with a face to profile CenterKeyPoint
# joint assembly. I need a way to determine the appropriate angle to use
# when creating a face to profile CenterKeyPoint joint using face from a body
# that is not aligned with x,y, or z.
#==============================================================================
def run(context):
app = adsk.core.Application.get()
ui = app.userInterface
try:
# length 0 deg to X, width 0 deg to Y, length & width 90 deg to Z
source = createSourceComponent()
# rotate on Y 45 deg to X and Z axis
angle = -0.785398 # -45 degrees
axis = adsk.core.Vector3D.create(0.0, 10.0, 0.0)
origin = adsk.core.Point3D.create(0.0, 0.0, 0.0)
source.rotate(angle, axis, origin)
mapBody = mapper()
boardRect = rect(insert=(0,0), size=(96,12))
mapBody.addBoard(boardRect)
xOffset = 0
yOffset = 0
compRect = rect(insert=(xOffset, yOffset), size=(source.length, source.width))
mapBody.addComponent(source, compRect, 'Y45ToXandZ')
# rotate on X 45 deg to Y and Z axis
angle = -0.785398 # -45 degrees
axis = adsk.core.Vector3D.create(10, 0.0, 0.0)
origin = adsk.core.Point3D.create(0.0, 0.0, 0.0)
source.rotate(angle, axis, origin)
xOffset += source.length
compRect = rect(insert=(xOffset, yOffset), size=(source.length, source.width))
mapBody.addComponent(source, compRect, 'X45ToYandZ')
# rotate on Z 45 deg to X and Y axis
angle = -0.785398 # -45 degrees
axis = adsk.core.Vector3D.create(0.0, 0.0, 10)
origin = adsk.core.Point3D.create(0.0, 0.0, 0.0)
source.rotate(angle, axis, origin)
xOffset += source.length
compRect = rect(insert=(xOffset, yOffset), size=(source.length, source.width))
mapBody.addComponent(source, compRect, 'Z45ToXandY')
camera_ = app.activeViewport.camera
camera_.isFitView = True
app.activeViewport.camera = camera_
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Solved! Go to Solution.