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 / peg.py
1 """
2 Peg.
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 solid
13 from fabmetheus_utilities.geometry.geometry_utilities import evaluate
14 from fabmetheus_utilities.geometry.solids import cylinder
15 from fabmetheus_utilities.vector3 import Vector3
16 import math
17
18
19 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
20 __credits__ = 'Art of Illusion <http://www.artofillusion.org/>'
21 __date__ = '$Date: 2008/02/05 $'
22 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
23
24
25
26 def addPegOutput(bevel, endZ, outputs, radiusArealized, sides, start, topOverBottom):
27         'Add beveled cylinder to outputs given bevel, endZ, radiusArealized and start.'
28         height = abs(start.z - endZ)
29         bevelStartRatio = max(1.0 - bevel / height, 0.5)
30         oneMinusBevelStartRatio = 1.0 - bevelStartRatio
31         trunkEndZ = bevelStartRatio * endZ + oneMinusBevelStartRatio * start.z
32         trunkTopOverBottom = bevelStartRatio * topOverBottom + oneMinusBevelStartRatio
33         cylinder.addCylinderOutputByEndStart(trunkEndZ, radiusArealized, outputs, sides, start, trunkTopOverBottom)
34         capRadius = radiusArealized * trunkTopOverBottom
35         capStart = bevelStartRatio * Vector3(start.x, start.y, endZ) + oneMinusBevelStartRatio * start
36         radiusMaximum = max(radiusArealized.real, radiusArealized.imag)
37         endRadiusMaximum = radiusMaximum * topOverBottom - bevel
38         trunkRadiusMaximum = radiusMaximum * trunkTopOverBottom
39         capTopOverBottom = endRadiusMaximum / trunkRadiusMaximum
40         cylinder.addCylinderOutputByEndStart(endZ, capRadius, outputs, sides, capStart, capTopOverBottom)
41
42 def getGeometryOutput(derivation, elementNode):
43         'Get vector3 vertexes from attribute dictionary.'
44         if derivation == None:
45                 derivation = PegDerivation(elementNode)
46         positives = []
47         radiusArealized = complex(derivation.radiusArealized, derivation.radiusArealized)
48         addPegOutput(derivation.bevel, derivation.endZ, positives, radiusArealized, derivation.sides, derivation.start, derivation.topOverBottom)
49         return extrude.getGeometryOutputByNegativesPositives(elementNode, [], positives)
50
51 def getGeometryOutputByArguments(arguments, elementNode):
52         'Get vector3 vertexes from attribute dictionary by arguments.'
53         evaluate.setAttributesByArguments(['radius', 'endZ', 'start'], arguments, elementNode)
54         return getGeometryOutput(None, elementNode)
55
56 def getNewDerivation(elementNode):
57         'Get new derivation.'
58         return PegDerivation(elementNode)
59
60 def getTopAddBiconicOutput(bottomRadians, height, outputs, radius, sides, start, tipRadius, topRadians):
61         'Get top and add biconic cylinder to outputs.'
62         radiusMaximum = max(radius.real, radius.imag)
63         topRadiusMaximum = radiusMaximum - height * math.tan(bottomRadians)
64         trunkEndZ = start.z + height
65         trunkTopOverBottom = topRadiusMaximum / radiusMaximum
66         topRadiusComplex = trunkTopOverBottom * radius
67         cylinder.addCylinderOutputByEndStart(trunkEndZ, radius, outputs, sides, start, trunkTopOverBottom)
68         tipOverTop = tipRadius / topRadiusMaximum
69         if tipOverTop >= 1.0:
70                 return trunkEndZ
71         capStart = Vector3(start.x, start.y, trunkEndZ)
72         capEndZ = trunkEndZ + (topRadiusMaximum - tipRadius) / math.tan(topRadians)
73         cylinder.addCylinderOutputByEndStart(capEndZ, topRadiusComplex, outputs, sides, capStart, tipOverTop)
74         return capEndZ
75
76 def processElementNode(elementNode):
77         'Process the xml element.'
78         solid.processElementNodeByGeometry(elementNode, getGeometryOutput(None, elementNode))
79
80 def setTopOverBottomByRadius(derivation, endZ, radius, startZ):
81         'Set the derivation topOverBottom by the angle of the elementNode, the endZ, float radius and startZ.'
82         angleDegrees = evaluate.getEvaluatedFloat(None, derivation.elementNode, 'angle')
83         if angleDegrees != None:
84                 derivation.topOverBottom = cylinder.getTopOverBottom(math.radians(angleDegrees), endZ, complex(radius, radius), startZ)
85
86
87 class PegDerivation:
88         'Class to hold peg variables.'
89         def __init__(self, elementNode):
90                 'Set defaults.'
91                 self.bevelOverRadius = evaluate.getEvaluatedFloat(0.25, elementNode, 'bevelOverRadius')
92                 self.clearanceOverRadius = evaluate.getEvaluatedFloat(0.0, elementNode, 'clearanceOverRadius')
93                 self.elementNode = elementNode
94                 self.endZ = evaluate.getEvaluatedFloat(10.0, elementNode, 'endZ')
95                 self.start = evaluate.getVector3ByPrefix(Vector3(), elementNode, 'start')
96                 self.radius = lineation.getFloatByPrefixBeginEnd(elementNode, 'radius', 'diameter', 2.0)
97                 self.sides = evaluate.getSidesMinimumThreeBasedOnPrecision(elementNode, max(self.radius.real, self.radius.imag))
98                 self.radiusArealized = evaluate.getRadiusArealizedBasedOnAreaRadius(elementNode, self.radius, self.sides)
99                 self.topOverBottom = evaluate.getEvaluatedFloat(0.8, elementNode, 'topOverBottom')
100                 setTopOverBottomByRadius(self, self.endZ, self.radiusArealized, self.start.z)
101                 # Set derived variables.
102                 self.bevel = evaluate.getEvaluatedFloat(self.bevelOverRadius * self.radiusArealized, elementNode, 'bevel')
103                 self.clearance = evaluate.getEvaluatedFloat(self.clearanceOverRadius * self.radiusArealized, elementNode, 'clearance')