The IronPython script main.py follows. This script defines
all functions executed by the callbacks in the steps for the SpaceClaim wizard
BGAWizard
.
import System import clr import sys import os import math part = None def oninit(context): return def createMyFeature(ag): ExtAPI.CreateFeature("MyFeature1") def createSphere(x, y, z, radius): global part from System.Collections.Generic import List # get selected part if part==None: win = Window.ActiveWindow context = win.ActiveContext part = context.ActivePart.Master center = Geometry.Point.Create(x, y, z) profileFrame = Geometry.Frame.Create(center, Geometry.Direction.DirX, Geometry.Direction.DirY) sphereCircle = Geometry.Circle.Create(profileFrame, radius) sphereRevolveLine = Geometry.Line.Create(center, Geometry.Direction.DirX) profile = List[Geometry.ITrimmedCurve]() profile.Add(Geometry.CurveSegment.Create(sphereCircle, Geometry.Interval.Create(0, math.pi))); profile.Add(Geometry.CurveSegment.Create(sphereRevolveLine, Geometry.Interval.Create(-radius, radius))) path = List[Geometry.ITrimmedCurve]() sweepCircle = Geometry.Circle.Create(Geometry.Frame.Create(center, Geometry.Direction.DirY, Geometry.Direction.DirZ), radius) path.Add(Geometry.CurveSegment.Create(sweepCircle)) body = Modeler.Body.SweepProfile(Geometry.Profile(Geometry.Plane.Create(profileFrame), profile), path) DesignBody.Create(part, "sphere", body) def createCylinder(x, y, z, radius, h): global part from System.Collections.Generic import List # get selected part if part==None: win = Window.ActiveWindow context = win.ActiveContext part = context.ActivePart.Master defaultPointUV = Geometry.PointUV.Create(0, 0) profile = Geometry.CircleProfile(Geometry.Plane.PlaneXY, radius, defaultPointUV, 0) points = List[Geometry.Point]() points.Add(Geometry.Point.Create(0, 0, 0)) points.Add(Geometry.Point.Create(0, 0, h)) path = Geometry.PolygonProfile(Geometry.Plane.PlaneXY, points) body = Modeler.Body.SweepProfile(profile, path.Boundary) designBody = DesignBody.Create(part, "Cylinder", body) translation = Geometry.Matrix.CreateTranslation(Geometry.Vector.Create(x, y, z)) designBody.Transform(translation) def createCone(x, y, z, radius, h): global part from System.Collections.Generic import List # get selected part if part==None: win = Window.ActiveWindow context = win.ActiveContext part = context.ActivePart.Master defaultPointUV = Geometry.PointUV.Create(0, 0) path = Geometry.CircleProfile(Geometry.Plane.PlaneXY, radius, defaultPointUV, 0) points = List[Geometry.Point]() points.Add(Geometry.Point.Create(0, 0, 0)) points.Add(Geometry.Point.Create(radius, 0, h)) points.Add(Geometry.Point.Create(0, 0, h)) triangle = Geometry.PolygonProfile(Geometry.Plane.PlaneZX, points) body = Modeler.Body.SweepProfile(triangle, path.Boundary) designBody = DesignBody.Create(part, "Cone", body) translation = Geometry.Matrix.CreateTranslation(Geometry.Vector.Create(x, y, z)) designBody.Transform(translation) def createBox(xa, ya, za, xb, yb, zb): global part # get selected part if part==None: win = Window.ActiveWindow context = win.ActiveContext part = context.ActivePart.Master lengthX = xb - xa lengthY = yb - ya lengthZ = zb - za xa = xa + lengthX * 0.5 ya = ya + lengthY * 0.5 p = Geometry.PointUV.Create(0, 0) body = Modeler.Body.ExtrudeProfile(Geometry.RectangleProfile(Geometry.Plane.PlaneXY, lengthX, lengthY, p, 0), lengthZ) designBody = DesignBody.Create(part, "body", body) translation = Geometry.Matrix.CreateTranslation(Geometry.Vector.Create(xa, ya, za)) designBody.Transform(translation) def createGear(x, y, z, innerRadius, outerRadius, width, count, holeRadius): global part from System.Collections.Generic import List # get selected part if part==None: win = Window.ActiveWindow context = win.ActiveContext part = context.ActivePart.Master frame = Geometry.Frame.World # create gear outsideCircle = Geometry.Circle.Create(frame, outerRadius); insideCircle = Geometry.Circle.Create(frame, innerRadius); boundary = List[Geometry.ITrimmedCurve]() inwardLine = Geometry.Line.Create(frame.Origin, -frame.DirX); outwardLine = Geometry.Line.Create(frame.Origin, frame.DirX); axis = outsideCircle.Axis; nTeeth = count; repeatAngle = 2 * math.pi / nTeeth; toothAngle = 0.6 * repeatAngle; gapAngle = repeatAngle - toothAngle; for i in range(0, nTeeth): # an arc is just a parameter interval of a circle startTooth = i * repeatAngle; endTooth = startTooth + toothAngle; boundary.Add(Geometry.CurveSegment.Create(outsideCircle, Geometry.Interval.Create(startTooth, endTooth))); # rotate 'inwardLine' about the circle axis rotatedInwardLine = Geometry.Matrix.CreateRotation(axis, endTooth) * inwardLine; # a line segment is just a parameter interval of an unbounded line boundary.Add(Geometry.CurveSegment.Create(rotatedInwardLine, Geometry.Interval.Create(-outerRadius, -innerRadius))); startGap = endTooth; endGap = startGap + gapAngle; boundary.Add(Geometry.CurveSegment.Create(insideCircle, Geometry.Interval.Create(startGap, endGap))); rotatedOutwardLine = Geometry.Matrix.CreateRotation(axis, endGap) * outwardLine; boundary.Add(Geometry.CurveSegment.Create(rotatedOutwardLine, Geometry.Interval.Create(innerRadius, outerRadius))); hole = Geometry.Circle.Create(frame.Create(frame.Origin, frame.DirX, frame.DirY), holeRadius); boundary.Add(Geometry.CurveSegment.Create(hole)); body = Modeler.Body.ExtrudeProfile(Geometry.Profile(Geometry.Plane.Create(frame), boundary), width); pieces = body.SeparatePieces().GetEnumerator() while pieces.MoveNext(): designBody = DesignBody.Create(part, "GearBody", pieces.Current); translation = Geometry.Matrix.CreateTranslation(Geometry.Vector.Create(x, y, z)) designBody.Transform(translation) class Vector: def __init__(self, x = 0, y = 0, z = 0): self.x = x self.y = y self.z = z def Clone(self): return Vector(self.x, self.y, self.z) def NormSQ(self): return self.x*self.x + self.y*self.y + self.z*self.z def Norm(self): return math.sqrt(self.x*self.x + self.y*self.y + self.z*self.z) def Normalize(self): norm = self.Norm() self.x = self.x / norm self.y = self.y / norm self.z = self.z / norm def GetNormalize(self): norm = self.Norm(self) return Vector(self.x / norm, self.y / norm, self.z / norm) def __add__(va, vb): return Vector(va.x + vb.x, va.y + vb.y, va.z + vb.z) def __sub__(va, vb): return Vector(va.x - vb.x, va.y - vb.y, va.z - vb.z) def __mul__(v, x): return Vector(v.x*x, v.y*x, v.z*x) def Cross(va, vb): return Vector(va.y*vb.z - va.z*vb.z, -va.z*vb.x + va.x*vb.z, va.x*vb.y - va.y*vb.x) def Dot(va, vb): return va.x*vb.x + va.y*vb.y + va.z*vb.z def ToString(self): return "( " + str(self.x) + ", " + str(self.y) + ", " + str(self.z) + " )" def CreateBalls(primitive, pitch, radius, column, row, supr, columnSupr, rowSupr, center, dirColumn, dirRow): dirColumn.Normalize() dirRow.Normalize() startVector = center - dirColumn*column*pitch*0.5 - dirRow*row*pitch*0.5 startVector = startVector + dirColumn*radius + dirRow*radius startVector = startVector + dirRow.Cross(dirColumn)*radius stepVectorColumn = dirColumn * pitch stepVectorRow = dirRow * pitch if(supr == "Yes"): column_index_to_start_supress = int( column * 0.5 - columnSupr * 0.5 ) row_index_to_start_supress = int( row * 0.5 - rowSupr * 0.5 ) v = startVector.Clone() for i in range(column): for j in range(row): createBall = False if (supr == "Yes" and (i < column_index_to_start_supress or i >= column_index_to_start_supress + columnSupr or j < row_index_to_start_supress or j >= row_index_to_start_supress+ rowSupr) or supr == "No"): if primitive == "sphere": createSphere(v.x, v.y, v.z, radius) elif primitive == "cylinder": createCylinder(v.x, v.y, v.z, radius, radius * 2.) elif primitive == "cone": createCone(v.x, v.y, v.z, radius, radius * 2.) elif primitive == "cube": createBox(v.x - radius, v.y - radius, v.z - radius, v.x + radius, v.y + radius, v.z + radius) elif primitive == "gear": createGear(v.x, v.y, v.z, radius*0.5, radius, radius*2, 10, radius*0.2) v = v + stepVectorRow v = startVector.Clone() startVector = startVector + stepVectorColumn v = v + stepVectorColumn def CreateDie(width, thickness, zStart): createBox(-0.5 * width, -0.5 * width, zStart, 0.5 * width, 0.5 * width, zStart + thickness) def CreateSubstrate(width, thickness, zStart): createBox(-0.5 * width, -0.5 * width, zStart, 0.5 * width, 0.5 * width, zStart + thickness) def CreateSolderMask(width, thickness, zStart): createBox(-0.5 * width, -0.5 * width, zStart, 0.5 * width, 0.5 * width, zStart + thickness) def generateBGAGeometry(feature,fct): ps = feature.Properties Pitch = ps["Solder Ball Details/Pitch"].Value Solder_Ball_Radius = ps["Solder Ball Details/Solder Ball Radius"].Value No_Of_Solder_Ball_Column = ps["Solder Ball Details/Number of Solder Ball Columns"].Value No_Of_Solder_Ball_Row = ps["Solder Ball Details/Number of Solder Ball Rows"].Value No_Of_Solder_Ball_Column_Supress = ps["Central Balls/Central Thermal Balls/Number of Solder Ball Columns"].Value No_Of_Solder_Ball_Row_Supress = ps["Central Balls/Central Thermal Balls/Number of Solder Ball Rows"].Value Substrate_Thickness = ps["Substrate Details/Substrate Thickness"].Value Substrate_Width = ps["Substrate Details/Substrate Length"].Value Die_Thickness = ps["Die Details/Die Thickness"].Value Die_Width = ps["Die Details/Die Width"].Value Solder_Mask_Height = ps["Solder Ball Details/Solder Mask Height"].Value supress_balls = ps["Central Balls/Central Thermal Balls"].Value ballsPrimitive = ps["BallsPrimitive"].Value bodies = [] CreateBalls(ballsPrimitive, Pitch, Solder_Ball_Radius, No_Of_Solder_Ball_Column, No_Of_Solder_Ball_Row, supress_balls, No_Of_Solder_Ball_Column_Supress, No_Of_Solder_Ball_Row_Supress, Vector(0, 0, 0), Vector(1, 0, 0), Vector(0, 1, 0)) #Creating Substrate and soldermask CreateSubstrate(Substrate_Width, Substrate_Thickness, 0) CreateSolderMask(Substrate_Width, Solder_Mask_Height, 0) #Creating Die Die_Start = Substrate_Thickness CreateDie(Die_Width, Die_Thickness, Die_Start) return True def GenerateDie(step): global part win = Window.ActiveWindow context = win.ActiveContext part = context.ActivePart ps = step.Properties Die_Thickness = ps["Thickness"].Value Die_Width = ps["Width"].Value CreateDie(Die_Width, Die_Thickness, 0) part = None def GenerateSubstrateAndSolderMask(step): global part win = Window.ActiveWindow context = win.ActiveContext part = context.ActivePart Die_Thickness = step.PreviousStep.Properties["Thickness"].Value ps = step.Properties Substrate_Thickness = ps["SubstrateDetails/Thickness"].Value Substrate_Width = ps["SubstrateDetails/Length"].Value Solder_Mask_Height = ps["SolderMaskDetails/Height"].Value CreateSubstrate(Substrate_Width, Substrate_Thickness, Die_Thickness) CreateSolderMask(Substrate_Width, Solder_Mask_Height, Die_Thickness + Substrate_Thickness) part = None def GenerateBalls(step): global part win = Window.ActiveWindow context = win.ActiveContext part = context.ActivePart zStart = 0 zStart += step.PreviousStep.PreviousStep.Properties["Thickness"].Value zStart += step.PreviousStep.Properties["SubstrateDetails/Thickness"].Value zStart += step.PreviousStep.Properties["SolderMaskDetails/Height"].Value ps = step.Properties faces = ps["Face"].Value.Faces pitch = ps["SolderBallDetails/Pitch"].Value radius = ps["SolderBallDetails/Radius"].Value column = ps["SolderBallDetails/Number of Solder Ball Columns"].Value row = ps["SolderBallDetails/Number of Solder Ball Rows"].Value primitive = ps["SolderBallDetails/BallsPrimitive"].Value columnSupr = ps["Central Balls/Central Thermal Balls/Number of Solder Ball Columns"].Value rowSupr = ps["Central Balls/Central Thermal Balls/Number of Solder Ball Rows"].Value supr = ps["Central Balls/Central Thermal Balls"].Value for i in range(0, faces.Count): face = faces[i] edges = face.Edges if edges.Count == 0: continue # find two edges with a comon point edgeA = edges[0] startPointA = edgeA.Shape.StartPoint endPointA = edgeA.Shape.EndPoint for j in range(1, edges.Count): edgeB = edges[j] startPointB = edgeB.Shape.StartPoint endPointB = edgeB.Shape.EndPoint if startPointB == startPointA: basePoint = startPointB pointRow = endPointA pointColumn = endPointB elif endPointB == startPointA: basePoint = endPointB pointRow = endPointA pointColumn = startPointB elif startPointB == endPointA: basePoint = startPointB pointRow = startPointA pointColumn = endPointB elif endPointB == endPointA: basePoint = endPointB pointRow = startPointA pointColumn = startPointB if not basePoint is None: dirColumn = Vector(pointRow.X - basePoint.X, pointRow.Y - basePoint.Y, pointRow.Z - basePoint.Z) dirRow = Vector(pointColumn.X - basePoint.X, pointColumn.Y - basePoint.Y, pointColumn.Z - basePoint.Z) center = Vector(basePoint.X, basePoint.Y, basePoint.Z) + (dirRow + dirColumn)*0.5 CreateBalls(primitive, pitch, radius, column, row, supr, columnSupr, rowSupr, center, dirColumn, dirRow) break part = None