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].
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.
7 The getCarving function takes the file name of an slc file and returns the carving.
12 from __future__ import absolute_import
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
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'
28 def getCarving(fileName=''):
29 "Get the triangle mesh for the slc file."
30 carving = SLCCarving()
31 carving.readFile(fileName)
34 def getLittleEndianFloatGivenFile( file ):
35 "Get little endian float given a file."
36 return unpack('<f', file.read(4) )[0]
38 def getLittleEndianUnsignedLongGivenFile( file ):
39 "Get little endian float given a file."
40 return unpack('<L', file.read(4) )[0]
42 def getPointsFromFile( numPoints, file ):
43 "Process the vertice points for a given boundary."
45 for pointIndex in xrange( numPoints ):
46 x = getLittleEndianFloatGivenFile( file )
47 y = getLittleEndianFloatGivenFile( file )
48 points.append( complex(x, y) )
51 def readHeader( file ):
52 "Read the slc header."
53 while ord( file.read( 1 ) ) != 0x1A:
57 class SampleTableEntry(object):
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 )
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 )
71 class SLCCarving(object):
75 self.layerHeight = None
77 self.maximumZ = - 987654321.0
78 self.minimumZ = 987654321.0
81 "Get the string representation of this carving."
82 return self.getCarvedSVG()
84 def addXML(self, depth, output):
85 "Add xml for this object."
86 xml_simple_writer.addXMLFromObjects(depth, self.loopLayers, output)
88 def getCarveBoundaryLayers(self):
89 "Get the boundary layers."
90 return self.loopLayers
92 def getCarveCornerMaximum(self):
93 "Get the corner maximum of the vertexes."
94 return self.cornerMaximum
96 def getCarveCornerMinimum(self):
97 "Get the corner minimum of the vertexes."
98 return self.cornerMinimum
100 def getCarvedSVG(self):
101 "Get the carved svg text."
102 if len(self.loopLayers) < 1:
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')
108 def getCarveLayerHeight(self):
109 "Get the layer height."
110 return self.layerHeight
112 def getFabmetheusXML(self):
113 "Return the fabmetheus XML."
116 def getInterpretationSuffix(self):
117 "Return the suffix for a carving."
120 def processContourLayers( self, file ):
121 "Process a contour layer at a time until the top of the part."
123 minLayer = getLittleEndianFloatGivenFile( file )
124 numContours = getLittleEndianUnsignedLongGivenFile( file )
125 if numContours == 0xFFFFFFFF:
127 loopLayer = euclidean.LoopLayer( minLayer )
128 self.loopLayers.append( loopLayer )
129 for contourIndex in xrange( numContours ):
130 numPoints = getLittleEndianUnsignedLongGivenFile( file )
131 numGaps = getLittleEndianUnsignedLongGivenFile( file )
133 loopLayer.loops.append( getPointsFromFile( numPoints, file ) )
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 )
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:
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
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!")
162 for index in xrange( tableEntrySize ):
163 sampleTableEntry = SampleTableEntry( file )
164 self.layerHeight = sampleTableEntry.layerHeight
166 def setCarveImportRadius( self, importRadius ):
167 "Set the import radius."
170 def setCarveIsCorrectMesh( self, isCorrectMesh ):
171 "Set the is correct mesh flag."
174 def setCarveLayerHeight( self, layerHeight ):
175 "Set the layer height."
180 "Display the inset dialog."
181 if len(sys.argv) > 1:
182 getCarving(' '.join(sys.argv[1 :]))
184 if __name__ == "__main__":