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