275 lines
11 KiB
Python
275 lines
11 KiB
Python
#Author-Autodesk Inc.
|
|
#Description-Create a bottle.
|
|
|
|
import adsk.core, adsk.fusion, traceback, math
|
|
|
|
# scale of the bottle size
|
|
scale = 2.0
|
|
|
|
# unit - cm
|
|
height = 21
|
|
topWidth = 2.8
|
|
topHight = 1.9
|
|
bodyTopWidth = 0.4
|
|
bottomWidth = 3.2
|
|
upperArcCenterToTop = 4.5
|
|
upperArcRadius = 16
|
|
lowerArcRadius = 15
|
|
filletRadius = 0.5
|
|
thickness = 0.3
|
|
threadPitch = 0.4
|
|
|
|
# used for direct modeling
|
|
upperArcMidPtXOffset = -0.18
|
|
upperArcMidPtYOffset = -4.1
|
|
upperArcEndPtXOffset = 0.46
|
|
upperArcEndPtYOffset = -7.2
|
|
lowerArcMidPtXOffsetFromOriginPt = 4.66
|
|
lowerArcMidPtYOffsetFromOriginPt = 5.9
|
|
|
|
bottomCenter = adsk.core.Point3D.create(0, 0, 0)
|
|
bottleMaterial = 'PrismMaterial-006'
|
|
bottleAppearance = 'Prism-154'
|
|
materialLibId = 'C1EEA57C-3F56-45FC-B8CB-A9EC46A9994C'
|
|
appearanceLibId = 'BA5EE55E-9982-449B-9D66-9F036540E140'
|
|
|
|
nearZero = 0.000001
|
|
|
|
app = adsk.core.Application.get()
|
|
ui = app.userInterface
|
|
|
|
newComp = None
|
|
|
|
def createNewComponent():
|
|
# Get the active design.
|
|
product = app.activeProduct
|
|
design = adsk.fusion.Design.cast(product)
|
|
rootComp = design.rootComponent
|
|
allOccs = rootComp.occurrences
|
|
newOcc = allOccs.addNewComponent(adsk.core.Matrix3D.create())
|
|
return newOcc.component
|
|
|
|
def createBottle():
|
|
product = app.activeProduct
|
|
design = adsk.fusion.Design.cast(product)
|
|
if not design:
|
|
ui.messageBox('It is not supported in current workspace, please change to MODEL workspace and try again.')
|
|
return
|
|
currentDesignType = design.designType
|
|
|
|
global newComp
|
|
newComp = createNewComponent()
|
|
if newComp is None:
|
|
ui.messageBox('New component failed to create', 'New Component Failed')
|
|
return
|
|
|
|
# add sketch
|
|
sketches = newComp.sketches
|
|
sketch = sketches.add(newComp.xYConstructionPlane)
|
|
|
|
# add sketch curves
|
|
sketchlines = sketch.sketchCurves.sketchLines
|
|
|
|
endPt = bottomCenter.copy() #start from bottomCenter
|
|
endPt.y = bottomCenter.y + height
|
|
heightLine = sketchlines.addByTwoPoints(bottomCenter, endPt)
|
|
|
|
endPt.x = endPt.x + topWidth
|
|
topLine = sketchlines.addByTwoPoints(heightLine.endSketchPoint, endPt)
|
|
|
|
endPt.y = endPt.y - topHight
|
|
topHightLine = sketchlines.addByTwoPoints(topLine.endSketchPoint, endPt)
|
|
|
|
endPt.x = endPt.x + bodyTopWidth
|
|
topBodyLine = sketchlines.addByTwoPoints(topHightLine.endSketchPoint, endPt)
|
|
|
|
sketchArcs = sketch.sketchCurves.sketchArcs
|
|
|
|
if currentDesignType == adsk.fusion.DesignTypes.DirectDesignType:
|
|
endPt.x = topBodyLine.endSketchPoint.geometry.x + upperArcEndPtXOffset
|
|
endPt.y = topBodyLine.endSketchPoint.geometry.y + upperArcEndPtYOffset
|
|
ptOnArc = adsk.core.Point3D.create(topBodyLine.endSketchPoint.geometry.x + upperArcMidPtXOffset, topBodyLine.endSketchPoint.geometry.y + upperArcMidPtYOffset)
|
|
upperArc = sketchArcs.addByThreePoints(topBodyLine.endSketchPoint, ptOnArc, endPt)
|
|
|
|
endPt = bottomCenter.copy()
|
|
endPt.x = bottomWidth
|
|
ptOnArc = adsk.core.Point3D.create(lowerArcMidPtXOffsetFromOriginPt, lowerArcMidPtYOffsetFromOriginPt)
|
|
else:
|
|
deltPos = 0.1
|
|
endPt.x = topWidth + bodyTopWidth + bodyTopWidth
|
|
endPt.y = height / 2
|
|
ptOnArc = adsk.core.Point3D.create(endPt.x - deltPos, endPt.y + deltPos)
|
|
upperArc = sketchArcs.addByThreePoints(topBodyLine.endSketchPoint, ptOnArc, endPt)
|
|
|
|
endPt = bottomCenter.copy()
|
|
endPt.x = bottomWidth
|
|
ptOnArc = adsk.core.Point3D.create(endPt.x + deltPos, endPt.y + deltPos)
|
|
|
|
lowerArc = sketchArcs.addByThreePoints(upperArc.endSketchPoint, ptOnArc, endPt)
|
|
buttomLine = sketchlines.addByTwoPoints(lowerArc.startSketchPoint, heightLine.startSketchPoint)
|
|
|
|
# add constraints
|
|
heightLine.startSketchPoint.isFixed = True
|
|
sketchConstraints = sketch.geometricConstraints
|
|
sketchConstraints.addHorizontal(buttomLine)
|
|
sketchConstraints.addPerpendicular(buttomLine, heightLine)
|
|
sketchConstraints.addPerpendicular(heightLine, topLine)
|
|
sketchConstraints.addPerpendicular(topLine, topHightLine)
|
|
sketchConstraints.addPerpendicular(topHightLine, topBodyLine)
|
|
|
|
# add dimensions
|
|
sketchDims = sketch.sketchDimensions
|
|
|
|
startPt = heightLine.startSketchPoint.geometry
|
|
endPt = heightLine.endSketchPoint.geometry
|
|
textPos = adsk.core.Point3D.create((startPt.x + endPt.x) / 2, (startPt.y + endPt.y) / 2, 0)
|
|
textPos.x = textPos.x - 1
|
|
sketchDims.addDistanceDimension(heightLine.startSketchPoint, heightLine.endSketchPoint, adsk.fusion.DimensionOrientations.AlignedDimensionOrientation, textPos)
|
|
|
|
startPt = topLine.startSketchPoint.geometry
|
|
endPt = topLine.endSketchPoint.geometry
|
|
textPos = adsk.core.Point3D.create((startPt.x + endPt.x) / 2, (startPt.y + endPt.y) / 2, 0)
|
|
textPos.y = textPos.y + 1
|
|
sketchDims.addDistanceDimension(topLine.startSketchPoint, topLine.endSketchPoint, adsk.fusion.DimensionOrientations.AlignedDimensionOrientation, textPos)
|
|
|
|
startPt = topHightLine.startSketchPoint.geometry
|
|
endPt = topHightLine.endSketchPoint.geometry
|
|
textPos = adsk.core.Point3D.create((startPt.x + endPt.x) / 2, (startPt.y + endPt.y) / 2, 0)
|
|
textPos.x = textPos.x + 1
|
|
sketchDims.addDistanceDimension(topHightLine.startSketchPoint, topHightLine.endSketchPoint, adsk.fusion.DimensionOrientations.AlignedDimensionOrientation, textPos)
|
|
|
|
startPt = topBodyLine.startSketchPoint.geometry
|
|
endPt = topBodyLine.endSketchPoint.geometry
|
|
textPos = adsk.core.Point3D.create((startPt.x + endPt.x) / 2, (startPt.y + endPt.y) / 2, 0)
|
|
textPos.y = textPos.y + 1
|
|
sketchDims.addDistanceDimension(topBodyLine.startSketchPoint, topBodyLine.endSketchPoint, adsk.fusion.DimensionOrientations.AlignedDimensionOrientation, textPos)
|
|
|
|
startPt = buttomLine.startSketchPoint.geometry
|
|
endPt = buttomLine.endSketchPoint.geometry
|
|
textPos = adsk.core.Point3D.create((startPt.x + endPt.x) / 2, (startPt.y + endPt.y) / 2, 0)
|
|
textPos.y = textPos.y - 1
|
|
sketchDims.addDistanceDimension(buttomLine.startSketchPoint, buttomLine.endSketchPoint, adsk.fusion.DimensionOrientations.AlignedDimensionOrientation, textPos)
|
|
|
|
startPt = topLine.endSketchPoint.geometry
|
|
endPt = upperArc.centerSketchPoint.geometry
|
|
textPos = adsk.core.Point3D.create((startPt.x + endPt.x) / 2, (startPt.y + endPt.y) / 2, 0)
|
|
if currentDesignType == adsk.fusion.DesignTypes.DirectDesignType:
|
|
sketchDims.addDistanceDimension(topLine.endSketchPoint, upperArc.centerSketchPoint, adsk.fusion.DimensionOrientations.VerticalDimensionOrientation, textPos)
|
|
else:
|
|
distDim = sketchDims.addDistanceDimension(topLine.endSketchPoint, upperArc.centerSketchPoint, adsk.fusion.DimensionOrientations.VerticalDimensionOrientation, textPos)
|
|
distDim.parameter.value = upperArcCenterToTop
|
|
|
|
startPt = upperArc.centerSketchPoint.geometry
|
|
textPos = adsk.core.Point3D.create(startPt.x + deltPos, startPt.y, 0)
|
|
radialArc = sketchDims.addRadialDimension(upperArc, textPos)
|
|
radialArc.parameter.value = upperArcRadius
|
|
|
|
startPt = lowerArc.centerSketchPoint.geometry
|
|
textPos = adsk.core.Point3D.create(startPt.x + deltPos, startPt.y, 0)
|
|
radialArc = sketchDims.addRadialDimension(lowerArc, textPos)
|
|
radialArc.parameter.value = lowerArcRadius
|
|
|
|
# create revolve
|
|
revolveFeats = newComp.features.revolveFeatures
|
|
|
|
revolveInput = revolveFeats.createInput(sketch.profiles[0], heightLine, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
|
|
revolveInput.setAngleExtent(True, adsk.core.ValueInput.createByReal(2 * math.pi))
|
|
revolveFeat = revolveFeats.add(revolveInput)
|
|
|
|
# create fillets
|
|
filletFeats = newComp.features.filletFeatures
|
|
|
|
# select the edges to do fillets
|
|
faces = revolveFeat.faces
|
|
body = faces[0].body
|
|
edgeCol = adsk.core.ObjectCollection.create()
|
|
for edge in body.edges:
|
|
circle = edge.geometry
|
|
if math.fabs(circle.radius - bottomWidth) < nearZero or math.fabs(circle.radius - topWidth - bodyTopWidth) < nearZero:
|
|
edgeCol.add(edge)
|
|
|
|
filletInput = filletFeats.createInput()
|
|
filletInput.addConstantRadiusEdgeSet(edgeCol, adsk.core.ValueInput.createByReal(filletRadius), True)
|
|
filletFeats.add(filletInput)
|
|
|
|
# create shell
|
|
shellFeats = newComp.features.shellFeatures
|
|
|
|
# select the faces to remove
|
|
faceCol = adsk.core.ObjectCollection.create()
|
|
for face in faces:
|
|
# find the top face
|
|
if face.geometry.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType:
|
|
edge0 = face.edges[0]
|
|
if edge0.geometry.center.isEqualTo(heightLine.endSketchPoint.worldGeometry):
|
|
faceCol.add(face)
|
|
break
|
|
|
|
shellInput = shellFeats.createInput(faceCol)
|
|
shellInput.insideThickness = adsk.core.ValueInput.createByReal(thickness)
|
|
shellFeats.add(shellInput)
|
|
|
|
# create thread
|
|
threadFeats = newComp.features.threadFeatures
|
|
|
|
# select the face to do thread
|
|
threadFace = None
|
|
for faceTemp in faces:
|
|
surf = faceTemp.geometry
|
|
if surf.surfaceType == adsk.core.SurfaceTypes.CylinderSurfaceType and math.fabs(surf.radius - topWidth) < nearZero:
|
|
threadFace = faceTemp
|
|
break
|
|
|
|
threadQuery = threadFeats.threadDataQuery
|
|
threadType = threadQuery.defaultMetricThreadType
|
|
designation = ''
|
|
threadClass = ''
|
|
results = threadQuery.recommendThreadData(topWidth * 2, False, threadType)
|
|
if results[0]:
|
|
designation = results[1]
|
|
threadClass = results[2]
|
|
|
|
# find closest thread pitch
|
|
threadInfo = threadFeats.createThreadInfo(False, threadType, designation, threadClass)
|
|
designations = threadQuery.allDesignations(threadType, threadInfo.threadSize)
|
|
minGap = math.fabs(threadInfo.threadPitch - threadPitch)
|
|
for des in designations :
|
|
tempThreadInfo = threadFeats.createThreadInfo(False, threadType, des, threadClass)
|
|
tempGap = math.fabs(tempThreadInfo.threadPitch - threadPitch)
|
|
if tempGap < minGap :
|
|
threadInfo = tempThreadInfo
|
|
minGap = tempGap
|
|
|
|
faces = adsk.core.ObjectCollection.create()
|
|
faces.add(threadFace)
|
|
threadInput = threadFeats.createInput(faces, threadInfo)
|
|
threadInput.isModeled = True
|
|
threadFeats.add(threadInput)
|
|
|
|
# create scale
|
|
scaleFeats = newComp.features.scaleFeatures
|
|
|
|
objCol = adsk.core.ObjectCollection.create()
|
|
objCol.add(body)
|
|
|
|
scaleInput = scaleFeats.createInput(objCol, newComp.originConstructionPoint, adsk.core.ValueInput.createByReal(scale))
|
|
scaleFeats.add(scaleInput)
|
|
|
|
# set material
|
|
materialLibs = app.materialLibraries
|
|
materials = materialLibs.itemById(materialLibId).materials
|
|
appearances = materialLibs.itemById(appearanceLibId).appearances
|
|
|
|
body.material = materials.itemById(bottleMaterial)
|
|
body.appearance = appearances.itemById(bottleAppearance)
|
|
|
|
app.activeViewport.refresh()
|
|
|
|
def run(context):
|
|
try:
|
|
createBottle()
|
|
|
|
except:
|
|
if ui:
|
|
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
|