chiark / gitweb /
Add back the ultimaker platform, and made the platform mesh simpler.
[cura.git] / Cura / slice / cura_sf / fabmetheus_utilities / fabmetheus_tools / interpret_plugins / slc.py
1 """
2 This page is in the table of contents.
3 The slc.py script is an import translator plugin to get a carving from an [http://rapid.lpt.fi/archives/rp-ml-1999/0713.html slc file].
4
5 An import plugin is a script in the interpret_plugins folder which has the function getCarving.  It is meant to be run from the interpret tool.  To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name.
6
7 The getCarving function takes the file name of an slc file and returns the carving.
8
9 """
10
11
12 from __future__ import absolute_import
13
14 from fabmetheus_utilities.vector3 import Vector3
15 from fabmetheus_utilities import euclidean
16 from fabmetheus_utilities import svg_writer
17 from struct import unpack
18 import math
19 import sys
20
21
22 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
23 __credits__ = 'Nophead <http://hydraraptor.blogspot.com/>\nArt of Illusion <http://www.artofillusion.org/>'
24 __date__ = '$Date: 2008/21/04 $'
25 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
26
27
28 def getCarving(fileName=''):
29         "Get the triangle mesh for the slc file."
30         carving = SLCCarving()
31         carving.readFile(fileName)
32         return carving
33
34 def getLittleEndianFloatGivenFile( file ):
35         "Get little endian float given a file."
36         return unpack('<f', file.read(4) )[0]
37
38 def getLittleEndianUnsignedLongGivenFile( file ):
39         "Get little endian float given a file."
40         return unpack('<L', file.read(4) )[0]
41
42 def getPointsFromFile( numPoints, file ):
43         "Process the vertice points for a given boundary."
44         points = []
45         for pointIndex in xrange( numPoints ):
46                 x = getLittleEndianFloatGivenFile( file )
47                 y = getLittleEndianFloatGivenFile( file )
48                 points.append( complex(x, y) )
49         return points
50
51 def readHeader( file ):
52         "Read the slc header."
53         while ord( file.read( 1 ) ) != 0x1A:
54                 pass
55
56
57 class SampleTableEntry(object):
58         "Sample table entry."
59         def __init__( self, file ):
60                 "Read in the sampling table section. It contains a table length (byte) and the table entries."
61                 self.min_z_level = getLittleEndianFloatGivenFile( file )
62                 self.layer_thickness = getLittleEndianFloatGivenFile( file )
63                 self.beam_comp = getLittleEndianFloatGivenFile( file )
64                 getLittleEndianFloatGivenFile( file )
65
66         def __repr__(self):
67                 "Get the string representation of this sample table entry."
68                 return '%s, %s, %s' % ( self.min_z_level, self.layer_thickness, self.beam_comp )
69
70
71 class SLCCarving(object):
72         "An slc carving."
73         def __init__(self):
74                 "Add empty lists."
75                 self.layerHeight = None
76                 self.loopLayers = []
77                 self.maximumZ = - 987654321.0
78                 self.minimumZ = 987654321.0
79         
80         def __repr__(self):
81                 "Get the string representation of this carving."
82                 return self.getCarvedSVG()
83
84         def addXML(self, depth, output):
85                 "Add xml for this object."
86                 xml_simple_writer.addXMLFromObjects(depth, self.loopLayers, output)
87
88         def getCarveBoundaryLayers(self):
89                 "Get the  boundary layers."
90                 return self.loopLayers
91
92         def getCarveCornerMaximum(self):
93                 "Get the corner maximum of the vertexes."
94                 return self.cornerMaximum
95
96         def getCarveCornerMinimum(self):
97                 "Get the corner minimum of the vertexes."
98                 return self.cornerMinimum
99
100         def getCarvedSVG(self):
101                 "Get the carved svg text."
102                 if len(self.loopLayers) < 1:
103                         return ''
104                 decimalPlaces = max(0, 2 - int(math.floor(math.log10(self.layerHeight))))
105                 self.svgWriter = svg_writer.SVGWriter(True, self.cornerMaximum, self.cornerMinimum, decimalPlaces, self.layerHeight)
106                 return self.svgWriter.getReplacedSVGTemplate(self.fileName, self.loopLayers, 'basic')
107
108         def getCarveLayerHeight(self):
109                 "Get the layer height."
110                 return self.layerHeight
111
112         def getFabmetheusXML(self):
113                 "Return the fabmetheus XML."
114                 return None
115
116         def getInterpretationSuffix(self):
117                 "Return the suffix for a carving."
118                 return 'svg'
119
120         def processContourLayers( self, file ):
121                 "Process a contour layer at a time until the top of the part."
122                 while True:
123                         minLayer = getLittleEndianFloatGivenFile( file )
124                         numContours = getLittleEndianUnsignedLongGivenFile( file )
125                         if numContours == 0xFFFFFFFF:
126                                 return
127                         loopLayer = euclidean.LoopLayer( minLayer )
128                         self.loopLayers.append( loopLayer )
129                         for contourIndex in xrange( numContours ):
130                                 numPoints = getLittleEndianUnsignedLongGivenFile( file )
131                                 numGaps = getLittleEndianUnsignedLongGivenFile( file )
132                                 if numPoints > 2:
133                                         loopLayer.loops.append( getPointsFromFile( numPoints, file ) )
134
135         def readFile( self, fileName ):
136                 "Read SLC and store the layers."
137                 self.fileName = fileName
138                 pslcfile = open( fileName, 'rb')
139                 readHeader( pslcfile )
140                 pslcfile.read( 256 ) #Go past the 256 byte 3D Reserved Section.
141                 self.readTableEntry( pslcfile )
142                 self.processContourLayers( pslcfile )
143                 pslcfile.close()
144                 self.cornerMaximum = Vector3(-987654321.0, -987654321.0, self.maximumZ)
145                 self.cornerMinimum = Vector3(987654321.0, 987654321.0, self.minimumZ)
146                 for loopLayer in self.loopLayers:
147                         for loop in loopLayer.loops:
148                                 for point in loop:
149                                         pointVector3 = Vector3(point.real, point.imag, loopLayer.z)
150                                         self.cornerMaximum.maximize(pointVector3)
151                                         self.cornerMinimum.minimize(pointVector3)
152                 halfLayerThickness = 0.5 * self.layerHeight
153                 self.cornerMaximum.z += halfLayerThickness
154                 self.cornerMinimum.z -= halfLayerThickness
155
156         def readTableEntry( self, file ):
157                 "Read in the sampling table section. It contains a table length (byte) and the table entries."
158                 tableEntrySize = ord( file.read( 1 ) )
159                 if tableEntrySize == 0:
160                         print("Sampling table size is zero!")
161                         exit()
162                 for index in xrange( tableEntrySize ):
163                         sampleTableEntry = SampleTableEntry( file )
164                         self.layerHeight = sampleTableEntry.layerHeight
165
166         def setCarveImportRadius( self, importRadius ):
167                 "Set the import radius."
168                 pass
169
170         def setCarveIsCorrectMesh( self, isCorrectMesh ):
171                 "Set the is correct mesh flag."
172                 pass
173
174         def setCarveLayerHeight( self, layerHeight ):
175                 "Set the layer height."
176                 pass
177
178
179 def main():
180         "Display the inset dialog."
181         if len(sys.argv) > 1:
182                 getCarving(' '.join(sys.argv[1 :]))
183
184 if __name__ == "__main__":
185         main()