chiark / gitweb /
Add uppercase STL and HEX to file dialog filters for linux/MacOS
[cura.git] / Cura / fabmetheus_utilities / geometry / geometry_tools / face.py
1 """
2 Face of a triangle mesh.
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.geometry_utilities import evaluate
11 from fabmetheus_utilities.geometry.geometry_utilities import matrix
12 from fabmetheus_utilities.vector3 import Vector3
13 from fabmetheus_utilities.vector3index import Vector3Index
14 from fabmetheus_utilities import euclidean
15 from fabmetheus_utilities import gcodec
16 from fabmetheus_utilities import intercircle
17 from fabmetheus_utilities import xml_simple_reader
18 from fabmetheus_utilities import xml_simple_writer
19 import cStringIO
20 import math
21
22
23 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
24 __credits__ = 'Art of Illusion <http://www.artofillusion.org/>'
25 __date__ = '$Date: 2008/02/05 $'
26 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
27
28
29 def addFaces(geometryOutput, faces):
30         'Add the faces.'
31         if geometryOutput.__class__ == list:
32                 for element in geometryOutput:
33                         addFaces(element, faces)
34                 return
35         if geometryOutput.__class__ != dict:
36                 return
37         for geometryOutputKey in geometryOutput.keys():
38                 geometryOutputValue = geometryOutput[geometryOutputKey]
39                 if geometryOutputKey == 'face':
40                         for face in geometryOutputValue:
41                                 faces.append(face)
42                 else:
43                         addFaces(geometryOutputValue, faces)
44
45 def addGeometryList(elementNode, faces):
46         "Add vertex elements to an xml element."
47         for face in faces:
48                 faceElement = xml_simple_reader.ElementNode()
49                 face.addToAttributes( faceElement.attributes )
50                 faceElement.localName = 'face'
51                 faceElement.parentNode = elementNode
52                 elementNode.childNodes.append( faceElement )
53
54 def getCommonVertexIndex( edgeFirst, edgeSecond ):
55         "Get the vertex index that both edges have in common."
56         for edgeFirstVertexIndex in edgeFirst.vertexIndexes:
57                 if edgeFirstVertexIndex == edgeSecond.vertexIndexes[0] or edgeFirstVertexIndex == edgeSecond.vertexIndexes[1]:
58                         return edgeFirstVertexIndex
59         print("Inconsistent GNU Triangulated Surface")
60         print(edgeFirst)
61         print(edgeSecond)
62         return 0
63
64 def getFaces(geometryOutput):
65         'Get the faces.'
66         faces = []
67         addFaces(geometryOutput, faces)
68         return faces
69
70 def processElementNode(elementNode):
71         "Process the xml element."
72         face = Face()
73         face.index = len(elementNode.parentNode.xmlObject.faces)
74         for vertexIndexIndex in xrange(3):
75                 face.vertexIndexes.append(evaluate.getEvaluatedInt(None, elementNode, 'vertex' + str(vertexIndexIndex)))
76         elementNode.parentNode.xmlObject.faces.append(face)
77
78
79 class Edge:
80         "An edge of a triangle mesh."
81         def __init__(self):
82                 "Set the face indexes to None."
83                 self.faceIndexes = []
84                 self.vertexIndexes = []
85                 self.zMaximum = None
86                 self.zMinimum = None
87         
88         def __repr__(self):
89                 "Get the string representation of this Edge."
90                 return str( self.index ) + ' ' + str( self.faceIndexes ) + ' ' + str(self.vertexIndexes)
91
92         def addFaceIndex( self, faceIndex ):
93                 "Add first None face index to input face index."
94                 self.faceIndexes.append( faceIndex )
95
96         def getFromVertexIndexes( self, edgeIndex, vertexIndexes ):
97                 "Initialize from two vertex indices."
98                 self.index = edgeIndex
99                 self.vertexIndexes = vertexIndexes[:]
100                 self.vertexIndexes.sort()
101                 return self
102
103
104 class Face:
105         "A face of a triangle mesh."
106         def __init__(self):
107                 "Initialize."
108                 self.edgeIndexes = []
109                 self.index = None
110                 self.vertexIndexes = []
111
112         def __repr__(self):
113                 "Get the string representation of this object info."
114                 output = cStringIO.StringIO()
115                 self.addXML( 2, output )
116                 return output.getvalue()
117
118         def addToAttributes(self, attributes):
119                 "Add to the attribute dictionary."
120                 for vertexIndexIndex in xrange(len(self.vertexIndexes)):
121                         vertexIndex = self.vertexIndexes[vertexIndexIndex]
122                         attributes['vertex' + str(vertexIndexIndex)] = str(vertexIndex)
123
124         def addXML(self, depth, output):
125                 "Add the xml for this object."
126                 attributes = {}
127                 self.addToAttributes(attributes)
128                 xml_simple_writer.addClosedXMLTag( attributes, depth, 'face', output )
129
130         def copy(self):
131                 'Get the copy of this face.'
132                 faceCopy = Face()
133                 faceCopy.edgeIndexes = self.edgeIndexes[:]
134                 faceCopy.index = self.index
135                 faceCopy.vertexIndexes = self.vertexIndexes[:]
136                 return faceCopy
137
138         def getFromEdgeIndexes( self, edgeIndexes, edges, faceIndex ):
139                 "Initialize from edge indices."
140                 if len(self.vertexIndexes) > 0:
141                         return
142                 self.index = faceIndex
143                 self.edgeIndexes = edgeIndexes
144                 for edgeIndex in edgeIndexes:
145                         edges[ edgeIndex ].addFaceIndex( faceIndex )
146                 for triangleIndex in xrange(3):
147                         indexFirst = ( 3 - triangleIndex ) % 3
148                         indexSecond = ( 4 - triangleIndex ) % 3
149                         self.vertexIndexes.append( getCommonVertexIndex( edges[ edgeIndexes[ indexFirst ] ], edges[ edgeIndexes[ indexSecond ] ] ) )
150                 return self
151
152         def setEdgeIndexesToVertexIndexes( self, edges, edgeTable ):
153                 "Set the edge indexes to the vertex indexes."
154                 if len(self.edgeIndexes) > 0:
155                         return
156                 for triangleIndex in xrange(3):
157                         indexFirst = ( 3 - triangleIndex ) % 3
158                         indexSecond = ( 4 - triangleIndex ) % 3
159                         vertexIndexFirst = self.vertexIndexes[ indexFirst ]
160                         vertexIndexSecond = self.vertexIndexes[ indexSecond ]
161                         vertexIndexPair = [ vertexIndexFirst, vertexIndexSecond ]
162                         vertexIndexPair.sort()
163                         edgeIndex = len( edges )
164                         if str( vertexIndexPair ) in edgeTable:
165                                 edgeIndex = edgeTable[ str( vertexIndexPair ) ]
166                         else:
167                                 edgeTable[ str( vertexIndexPair ) ] = edgeIndex
168                                 edge = Edge().getFromVertexIndexes( edgeIndex, vertexIndexPair )
169                                 edges.append( edge )
170                         edges[ edgeIndex ].addFaceIndex( self.index )
171                         self.edgeIndexes.append( edgeIndex )