6 from __future__ import absolute_import
8 from fabmetheus_utilities.geometry.creation import extrude
9 from fabmetheus_utilities.geometry.creation import lineation
10 from fabmetheus_utilities.geometry.creation import peg
11 from fabmetheus_utilities.geometry.creation import solid
12 from fabmetheus_utilities.geometry.geometry_utilities import evaluate
13 from fabmetheus_utilities.geometry.geometry_utilities import matrix
14 from fabmetheus_utilities.geometry.manipulation_matrix import translate
15 from fabmetheus_utilities.geometry.solids import cylinder
16 from fabmetheus_utilities.geometry.solids import sphere
17 from fabmetheus_utilities.vector3 import Vector3
18 from fabmetheus_utilities import euclidean
22 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
23 __credits__ = 'Art of Illusion <http://www.artofillusion.org/>'
24 __date__ = '$Date: 2008/02/05 $'
25 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
28 def addAssemblyCage(derivation, negatives, positives):
29 'Add assembly linear bearing cage.'
30 addCageGroove(derivation, negatives, positives)
31 for pegCenterX in derivation.pegCenterXs:
32 addPositivePeg(derivation, positives, pegCenterX, -derivation.pegY)
33 addPositivePeg(derivation, positives, pegCenterX, derivation.pegY)
34 translate.translateNegativesPositives(negatives, positives, Vector3(0.0, -derivation.halfSeparationWidth))
37 addCageGroove(derivation, femaleNegatives, femalePositives)
38 for pegCenterX in derivation.pegCenterXs:
39 addNegativePeg(derivation, femaleNegatives, pegCenterX, -derivation.pegY)
40 addNegativePeg(derivation, femaleNegatives, pegCenterX, derivation.pegY)
41 translate.translateNegativesPositives(femaleNegatives, femalePositives, Vector3(0.0, derivation.halfSeparationWidth))
42 negatives += femaleNegatives
43 positives += femalePositives
45 def addCage(derivation, height, negatives, positives):
46 'Add linear bearing cage.'
47 copyShallow = derivation.elementNode.getCopyShallow()
48 copyShallow.attributes['path'] = [Vector3(), Vector3(0.0, 0.0, height)]
49 extrudeDerivation = extrude.ExtrudeDerivation(copyShallow)
50 roundedExtendedRectangle = getRoundedExtendedRectangle(derivation.demiwidth, derivation.rectangleCenterX, 14)
51 outsidePath = euclidean.getVector3Path(roundedExtendedRectangle)
52 extrude.addPositives(extrudeDerivation, [outsidePath], positives)
53 for bearingCenterX in derivation.bearingCenterXs:
54 addNegativeSphere(derivation, negatives, bearingCenterX)
56 def addCageGroove(derivation, negatives, positives):
57 'Add cage and groove.'
58 addCage(derivation, derivation.demiheight, negatives, positives)
59 addGroove(derivation, negatives)
61 def addGroove(derivation, negatives):
62 'Add groove on each side of cage.'
63 copyShallow = derivation.elementNode.getCopyShallow()
64 extrude.setElementNodeToEndStart(copyShallow, Vector3(-derivation.demilength), Vector3(derivation.demilength))
65 extrudeDerivation = extrude.ExtrudeDerivation(copyShallow)
66 bottom = derivation.demiheight - 0.5 * derivation.grooveWidth
67 outside = derivation.demiwidth
68 top = derivation.demiheight
70 complex(-outside, bottom),
71 complex(-derivation.innerDemiwidth, derivation.demiheight),
72 complex(-outside, top)]
74 complex(outside, top),
75 complex(derivation.innerDemiwidth, derivation.demiheight),
76 complex(outside, bottom)]
77 extrude.addNegatives(extrudeDerivation, negatives, euclidean.getVector3Paths([leftGroove, rightGroove]))
79 def addNegativePeg(derivation, negatives, x, y):
80 'Add negative cylinder at x and y.'
81 negativePegRadius = derivation.pegRadiusArealized + derivation.halfPegClearance
82 inradius = complex(negativePegRadius, negativePegRadius)
83 copyShallow = derivation.elementNode.getCopyShallow()
84 start = Vector3(x, y, derivation.height)
85 sides = evaluate.getSidesMinimumThreeBasedOnPrecision(copyShallow, negativePegRadius)
86 cylinder.addCylinderOutputByEndStart(0.0, inradius, negatives, sides, start, derivation.topOverBottom)
88 def addNegativeSphere(derivation, negatives, x):
89 'Add negative sphere at x.'
90 radius = Vector3(derivation.radiusPlusClearance, derivation.radiusPlusClearance, derivation.radiusPlusClearance)
91 sphereOutput = sphere.getGeometryOutput(derivation.elementNode.getCopyShallow(), radius)
92 euclidean.translateVector3Path(matrix.getVertexes(sphereOutput), Vector3(x, 0.0, derivation.demiheight))
93 negatives.append(sphereOutput)
95 def addPositivePeg(derivation, positives, x, y):
96 'Add positive cylinder at x and y.'
97 positivePegRadius = derivation.pegRadiusArealized - derivation.halfPegClearance
98 radiusArealized = complex(positivePegRadius, positivePegRadius)
99 copyShallow = derivation.elementNode.getCopyShallow()
100 start = Vector3(x, y, derivation.demiheight)
101 endZ = derivation.height
102 peg.addPegOutput(derivation.pegBevel, endZ, positives, radiusArealized, derivation.sides, start, derivation.topOverBottom)
104 def getBearingCenterXs(bearingCenterX, numberOfSteps, stepX):
105 'Get the bearing center x list.'
107 for stepIndex in xrange(numberOfSteps + 1):
108 bearingCenterXs.append(bearingCenterX)
109 bearingCenterX += stepX
110 return bearingCenterXs
112 def getGeometryOutput(elementNode):
113 'Get vector3 vertexes from attribute dictionary.'
114 derivation = LinearBearingCageDerivation(elementNode)
117 if derivation.typeStringFirstCharacter == 'a':
118 addAssemblyCage(derivation, negatives, positives)
120 addCage(derivation, derivation.height, negatives, positives)
121 return extrude.getGeometryOutputByNegativesPositives(elementNode, negatives, positives)
123 def getGeometryOutputByArguments(arguments, elementNode):
124 'Get vector3 vertexes from attribute dictionary by arguments.'
125 evaluate.setAttributesByArguments(['length', 'radius'], arguments, elementNode)
126 return getGeometryOutput(elementNode)
128 def getNewDerivation(elementNode):
129 'Get new derivation.'
130 return LinearBearingCageDerivation(elementNode)
132 def getPegCenterXs(numberOfSteps, pegCenterX, stepX):
133 'Get the peg center x list.'
135 for stepIndex in xrange(numberOfSteps):
136 pegCenterXs.append(pegCenterX)
140 def getRoundedExtendedRectangle(radius, rectangleCenterX, sides):
141 'Get the rounded extended rectangle.'
142 roundedExtendedRectangle = []
143 halfSides = int(sides / 2)
144 halfSidesPlusOne = abs(halfSides + 1)
145 sideAngle = math.pi / float(halfSides)
146 extensionMultiplier = 1.0 / math.cos(0.5 * sideAngle)
147 center = complex(rectangleCenterX, 0.0)
148 startAngle = 0.5 * math.pi
149 for halfSide in xrange(halfSidesPlusOne):
150 unitPolar = euclidean.getWiddershinsUnitPolar(startAngle)
151 unitPolarExtended = complex(unitPolar.real * extensionMultiplier, unitPolar.imag)
152 roundedExtendedRectangle.append(unitPolarExtended * radius + center)
153 startAngle += sideAngle
154 center = complex(-rectangleCenterX, 0.0)
155 startAngle = -0.5 * math.pi
156 for halfSide in xrange(halfSidesPlusOne):
157 unitPolar = euclidean.getWiddershinsUnitPolar(startAngle)
158 unitPolarExtended = complex(unitPolar.real * extensionMultiplier, unitPolar.imag)
159 roundedExtendedRectangle.append(unitPolarExtended * radius + center)
160 startAngle += sideAngle
161 return roundedExtendedRectangle
163 def processElementNode(elementNode):
164 'Process the xml element.'
165 solid.processElementNodeByGeometry(elementNode, getGeometryOutput(elementNode))
168 class LinearBearingCageDerivation(object):
169 'Class to hold linear bearing cage variables.'
170 def __init__(self, elementNode):
172 self.length = evaluate.getEvaluatedFloat(50.0, elementNode, 'length')
173 self.demilength = 0.5 * self.length
174 self.elementNode = elementNode
175 self.radius = lineation.getFloatByPrefixBeginEnd(elementNode, 'radius', 'diameter', 5.0)
176 self.cageClearanceOverRadius = evaluate.getEvaluatedFloat(0.05, elementNode, 'cageClearanceOverRadius')
177 self.cageClearance = self.cageClearanceOverRadius * self.radius
178 self.cageClearance = evaluate.getEvaluatedFloat(self.cageClearance, elementNode, 'cageClearance')
179 self.racewayClearanceOverRadius = evaluate.getEvaluatedFloat(0.1, elementNode, 'racewayClearanceOverRadius')
180 self.racewayClearance = self.racewayClearanceOverRadius * self.radius
181 self.racewayClearance = evaluate.getEvaluatedFloat(self.racewayClearance, elementNode, 'racewayClearance')
182 self.typeMenuRadioStrings = 'assembly integral'.split()
183 self.typeString = evaluate.getEvaluatedString('assembly', elementNode, 'type')
184 self.typeStringFirstCharacter = self.typeString[: 1 ].lower()
185 self.wallThicknessOverRadius = evaluate.getEvaluatedFloat(0.5, elementNode, 'wallThicknessOverRadius')
186 self.wallThickness = self.wallThicknessOverRadius * self.radius
187 self.wallThickness = evaluate.getEvaluatedFloat(self.wallThickness, elementNode, 'wallThickness')
188 self.zenithAngle = evaluate.getEvaluatedFloat(45.0, elementNode, 'zenithAngle')
189 self.zenithRadian = math.radians(self.zenithAngle)
190 self.demiheight = self.radius * math.cos(self.zenithRadian) - self.racewayClearance
191 self.height = self.demiheight + self.demiheight
192 self.radiusPlusClearance = self.radius + self.cageClearance
193 self.cageRadius = self.radiusPlusClearance + self.wallThickness
194 self.demiwidth = self.cageRadius
195 self.bearingCenterX = self.cageRadius - self.demilength
196 separation = self.cageRadius + self.radiusPlusClearance
197 bearingLength = -self.bearingCenterX - self.bearingCenterX
198 self.numberOfSteps = int(math.floor(bearingLength / separation))
199 self.stepX = bearingLength / float(self.numberOfSteps)
200 self.bearingCenterXs = getBearingCenterXs(self.bearingCenterX, self.numberOfSteps, self.stepX)
201 if self.typeStringFirstCharacter == 'a':
202 self.setAssemblyCage()
203 self.rectangleCenterX = self.demiwidth - self.demilength
205 def setAssemblyCage(self):
206 'Set two piece assembly parameters.'
207 self.grooveDepthOverRadius = evaluate.getEvaluatedFloat(0.15, self.elementNode, 'grooveDepthOverRadius')
208 self.grooveDepth = self.grooveDepthOverRadius * self.radius
209 self.grooveDepth = evaluate.getEvaluatedFloat(self.grooveDepth, self.elementNode, 'grooveDepth')
210 self.grooveWidthOverRadius = evaluate.getEvaluatedFloat(0.6, self.elementNode, 'grooveWidthOverRadius')
211 self.grooveWidth = self.grooveWidthOverRadius * self.radius
212 self.grooveWidth = evaluate.getEvaluatedFloat(self.grooveWidth, self.elementNode, 'grooveWidth')
213 self.pegClearanceOverRadius = evaluate.getEvaluatedFloat(0.0, self.elementNode, 'pegClearanceOverRadius')
214 self.pegClearance = self.pegClearanceOverRadius * self.radius
215 self.pegClearance = evaluate.getEvaluatedFloat(self.pegClearance, self.elementNode, 'pegClearance')
216 self.halfPegClearance = 0.5 * self.pegClearance
217 self.pegRadiusOverRadius = evaluate.getEvaluatedFloat(0.5, self.elementNode, 'pegRadiusOverRadius')
218 self.pegRadius = self.pegRadiusOverRadius * self.radius
219 self.pegRadius = evaluate.getEvaluatedFloat(self.pegRadius, self.elementNode, 'pegRadius')
220 self.sides = evaluate.getSidesMinimumThreeBasedOnPrecision(self.elementNode, self.pegRadius)
221 self.pegRadiusArealized = evaluate.getRadiusArealizedBasedOnAreaRadius(self.elementNode, self.pegRadius, self.sides)
222 self.pegBevelOverPegRadius = evaluate.getEvaluatedFloat(0.25, self.elementNode, 'pegBevelOverPegRadius')
223 self.pegBevel = self.pegBevelOverPegRadius * self.pegRadiusArealized
224 self.pegBevel = evaluate.getEvaluatedFloat(self.pegBevel, self.elementNode, 'pegBevel')
225 self.pegMaximumRadius = self.pegRadiusArealized + abs(self.halfPegClearance)
226 self.separationOverRadius = evaluate.getEvaluatedFloat(0.5, self.elementNode, 'separationOverRadius')
227 self.separation = self.separationOverRadius * self.radius
228 self.separation = evaluate.getEvaluatedFloat(self.separation, self.elementNode, 'separation')
229 self.topOverBottom = evaluate.getEvaluatedFloat(0.8, self.elementNode, 'topOverBottom')
230 peg.setTopOverBottomByRadius(self, 0.0, self.pegRadiusArealized, self.height)
231 self.quarterHeight = 0.5 * self.demiheight
232 self.pegY = 0.5 * self.wallThickness + self.pegMaximumRadius
233 cagePegRadius = self.cageRadius + self.pegMaximumRadius
234 halfStepX = 0.5 * self.stepX
235 pegHypotenuse = math.sqrt(self.pegY * self.pegY + halfStepX * halfStepX)
236 if cagePegRadius > pegHypotenuse:
237 self.pegY = math.sqrt(cagePegRadius * cagePegRadius - halfStepX * halfStepX)
238 self.demiwidth = max(self.pegY + self.pegMaximumRadius + self.wallThickness, self.demiwidth)
239 self.innerDemiwidth = self.demiwidth
240 self.demiwidth += self.grooveDepth
241 self.halfSeparationWidth = self.demiwidth + 0.5 * self.separation
242 if self.pegRadiusArealized <= 0.0:
243 self.pegCenterXs = []
245 self.pegCenterXs = getPegCenterXs(self.numberOfSteps, self.bearingCenterX + halfStepX, self.stepX)