chiark / gitweb /
9104056654c1b00067800fb3d6c39c5666cee6c4
[cura.git] / Cura / fabmetheus_utilities / geometry / solids / sphere.py
1 """
2 Boolean geometry sphere.
3
4 """
5
6
7 from __future__ import absolute_import
8 #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.
9 import __init__
10
11 from fabmetheus_utilities.geometry.creation import solid
12 from fabmetheus_utilities.geometry.geometry_utilities import evaluate
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
17 import math
18
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'
23
24
25 def addSphere(elementNode, faces, radius, vertexes):
26         'Add sphere by radius.'
27         bottom = -radius.z
28         sides = evaluate.getSidesMinimumThreeBasedOnPrecision(elementNode, max(radius.x, radius.y, radius.z))
29         sphereSlices = max(sides / 2, 2)
30         equator = euclidean.getComplexPolygonByComplexRadius(complex(radius.x, radius.y), sides)
31         polygons = [triangle_mesh.getAddIndexedLoop([complex()], vertexes, bottom)]
32         zIncrement = (radius.z + radius.z) / float(sphereSlices)
33         z = bottom
34         for sphereSlice in xrange(1, sphereSlices):
35                 z += zIncrement
36                 zPortion = abs(z) / radius.z
37                 multipliedPath = euclidean.getComplexPathByMultiplier(math.sqrt(1.0 - zPortion * zPortion), equator)
38                 polygons.append(triangle_mesh.getAddIndexedLoop(multipliedPath, vertexes, z))
39         polygons.append(triangle_mesh.getAddIndexedLoop([complex()], vertexes, radius.z))
40         triangle_mesh.addPillarByLoops(faces, polygons)
41
42 def getGeometryOutput(elementNode, radius):
43         'Get triangle mesh from attribute dictionary.'
44         faces = []
45         vertexes = []
46         addSphere(elementNode, faces, radius, vertexes)
47         return {'trianglemesh' : {'vertex' : vertexes, 'face' : faces}}
48
49 def getNewDerivation(elementNode):
50         'Get new derivation.'
51         return SphereDerivation(elementNode)
52
53 def processElementNode(elementNode):
54         'Process the xml element.'
55         evaluate.processArchivable(Sphere, elementNode)
56
57
58 class Sphere(cube.Cube):
59         'A sphere object.'
60         def createShape(self):
61                 'Create the shape.'
62                 addSphere(self.elementNode, self.faces, self.radius, self.vertexes)
63
64         def setToElementNode(self, elementNode):
65                 'Set to elementNode.'
66                 attributes = elementNode.attributes
67                 self.elementNode = elementNode
68                 self.radius = SphereDerivation(elementNode).radius
69                 if 'radius' in attributes:
70                         del attributes['radius']
71                 attributes['radius.x'] = self.radius.x
72                 attributes['radius.y'] = self.radius.y
73                 attributes['radius.z'] = self.radius.z
74                 self.createShape()
75                 solid.processArchiveRemoveSolid(elementNode, self.getGeometryOutput())
76
77
78 class SphereDerivation:
79         "Class to hold sphere variables."
80         def __init__(self, elementNode):
81                 'Set defaults.'
82                 self.radius = evaluate.getVector3ByPrefixes(elementNode, ['demisize', 'radius'], Vector3(1.0, 1.0, 1.0))
83                 self.radius = evaluate.getVector3ByMultiplierPrefixes(elementNode, 2.0, ['diameter', 'size'], self.radius)