2 Boolean geometry cylinder.
7 from __future__ import absolute_import
9 from fabmetheus_utilities.geometry.creation import lineation
10 from fabmetheus_utilities.geometry.creation import solid
11 from fabmetheus_utilities.geometry.geometry_utilities import evaluate
12 from fabmetheus_utilities.geometry.geometry_utilities import matrix
13 from fabmetheus_utilities.geometry.solids import cube
14 from fabmetheus_utilities.geometry.solids import triangle_mesh
15 from fabmetheus_utilities.vector3 import Vector3
16 from fabmetheus_utilities import euclidean
19 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
20 __credits__ = 'Nophead <http://hydraraptor.blogspot.com/>\nArt of Illusion <http://www.artofillusion.org/>'
21 __date__ = '$Date: 2008/21/04 $'
22 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
25 def addCylinder(faces, inradius, sides, topOverBottom, vertexes):
26 'Add cylinder by inradius.'
27 polygonBottom = euclidean.getComplexPolygonByComplexRadius(complex(inradius.x, inradius.y), sides)
28 polygonTop = polygonBottom
29 if topOverBottom <= 0.0:
30 polygonTop = [complex()]
31 elif topOverBottom != 1.0:
32 polygonTop = euclidean.getComplexPathByMultiplier(topOverBottom, polygonTop)
34 triangle_mesh.getAddIndexedLoop(polygonBottom, vertexes, -inradius.z),
35 triangle_mesh.getAddIndexedLoop(polygonTop, vertexes, inradius.z)]
36 triangle_mesh.addPillarByLoops(faces, bottomTopPolygon)
38 def addCylinderOutputByEndStart(endZ, inradiusComplex, outputs, sides, start, topOverBottom=1.0):
39 'Add cylinder triangle mesh by endZ, inradius and start.'
40 inradius = Vector3(inradiusComplex.real, inradiusComplex.imag, 0.5 * abs(endZ - start.z))
41 cylinderOutput = getGeometryOutput(inradius, sides, topOverBottom)
42 vertexes = matrix.getVertexes(cylinderOutput)
44 for vertex in vertexes:
46 translation = Vector3(start.x, start.y, inradius.z + min(start.z, endZ))
47 euclidean.translateVector3Path(vertexes, translation)
48 outputs.append(cylinderOutput)
50 def getGeometryOutput(inradius, sides, topOverBottom):
51 'Get cylinder triangle mesh by inradius.'
54 addCylinder(faces, inradius, sides, topOverBottom, vertexes)
55 return {'trianglemesh' : {'vertex' : vertexes, 'face' : faces}}
57 def getNewDerivation(elementNode):
59 return CylinderDerivation(elementNode)
61 def getTopOverBottom(angle, endZ, inradiusComplex, startZ):
62 'Get topOverBottom by angle in radians, endZ, inradius and start.'
63 return max(1.0 - abs(endZ - startZ) * math.tan(angle) / lineation.getRadiusAverage(inradiusComplex), 0.0)
65 def processElementNode(elementNode):
66 'Process the xml element.'
67 evaluate.processArchivable(Cylinder, elementNode)
70 class Cylinder( cube.Cube ):
74 cube.Cube.__init__(self)
76 def createShape(self):
78 sides = evaluate.getSidesMinimumThreeBasedOnPrecision(self.elementNode, max(self.inradius.x, self.inradius.y))
79 if self.elementNode.getCascadeBoolean(False, 'radiusAreal'):
80 radiusArealizedMultiplier = euclidean.getRadiusArealizedMultiplier(sides)
81 self.inradius.x *= radiusArealizedMultiplier
82 self.inradius.y *= radiusArealizedMultiplier
83 addCylinder(self.faces, self.inradius, sides, self.topOverBottom, self.vertexes)
85 def setToElementNode(self, elementNode):
87 attributes = elementNode.attributes
88 self.elementNode = elementNode
89 derivation = CylinderDerivation(elementNode)
90 self.inradius = derivation.inradius
91 self.topOverBottom = derivation.topOverBottom
92 if 'inradius' in attributes:
93 del attributes['inradius']
94 attributes['height'] = self.inradius.z + self.inradius.z
95 attributes['radius.x'] = self.inradius.x
96 attributes['radius.y'] = self.inradius.y
97 attributes['topOverBottom'] = self.topOverBottom
99 solid.processArchiveRemoveSolid(elementNode, self.getGeometryOutput())
102 class CylinderDerivation(object):
103 "Class to hold cylinder variables."
104 def __init__(self, elementNode):
106 self.inradius = evaluate.getVector3ByPrefixes(elementNode, ['demisize', 'inradius', 'radius'], Vector3(1.0, 1.0, 1.0))
107 self.inradius = evaluate.getVector3ByMultiplierPrefixes(elementNode, 2.0, ['diameter', 'size'], self.inradius)
108 self.inradius.z = 0.5 * evaluate.getEvaluatedFloat(self.inradius.z + self.inradius.z, elementNode, 'height')
109 self.topOverBottom = evaluate.getEvaluatedFloat(1.0, elementNode, 'topOverBottom')