Howto write StL (StereoLithography) Binary Format with python?
Bengt Richter
bokr at oz.net
Fri Aug 23 13:55:14 EDT 2002
On 22 Aug 2002 12:16:29 +0200, Axel Koehler <axel.koehler at tu-berlin.de> wrote:
>Hallo,
>
>I'm searching for a python programm to write the binary format
>of the StL, as decribed in
> http://www.ennex.com/fabbers/StL.asp#binary
>
>Has anybody done this before? Google was no help
>
Look at the struct module. It will let you pack C types into a string
which you can then pass to the write method of a file opened for writing
in binary. E.g., you could do something like (not tested beyond what you see):
---< stl.py >----------------------------
import struct
class StLFacet:
def __init__(self, normal, v1, v2, v3, att_bc=0):
self.coords = [normal, v1, v2, v3]
self.att_bc = att_bc
class StL:
def __init__(self, header):
self.header = header
self.facets = []
def add_facet(self, facet):
self.facets.append(facet)
def get_binary(self):
out = ['%-80.80s' % self.header]
out.append(struct.pack('L',len(self.facets)))
for f in self.facets:
for coord in f.coords:
out.append(struct.pack('3f', *coord))
out.append(struct.pack('H', f.att_bc))
return ''.join(out)
def test():
stl=StL('Header ...')
stl.add_facet(StLFacet((1.,2.,3.),(4.,5.,6.),(7.,8.,9.),(10.,11.,12.)))
stl.add_facet(StLFacet((11.,12.,13.),(14.,15.,16.),(17.,18.,19.),(20.,21.,22.)))
return stl.get_binary()
-----------------------------------------
>>> import StL
>>> s = StL.test()
>>> s
'Header ... \x02\x00\
x00\x00\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@\x00\x00\xa0@\x00\x00\xc0@\x00\x00
\xe0@\x00\x00\x00A\x00\x00\x10A\x00\x00 A\x00\x000A\x00\x00 at A\x00\x00\x00\x000A\x00\x00 at A\
x00\x00PA\x00\x00`A\x00\x00pA\x00\x00\x80A\x00\x00\x88A\x00\x00\x90A\x00\x00\x98A\x00\x00\
xa0A\x00\x00\xa8A\x00\x00\xb0A\x00\x00'
>>> map(ord, s)
[72, 101, 97, 100, 101, 114, 32, 46, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 3
2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 3
2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0,
64, 0, 0, 64, 64, 0, 0, 128, 64, 0, 0, 160, 64, 0, 0, 192, 64, 0, 0, 224, 64, 0, 0, 0, 65
, 0, 0, 16, 65, 0, 0, 32, 65, 0, 0, 48, 65, 0, 0, 64, 65, 0, 0, 0, 0, 48, 65, 0, 0, 64, 65
, 0, 0, 80, 65, 0, 0, 96, 65, 0, 0, 112, 65, 0, 0, 128, 65, 0, 0, 136, 65, 0, 0, 144, 65,
0, 0, 152, 65, 0, 0, 160, 65, 0, 0, 168, 65, 0, 0, 176, 65, 0, 0]
If you want to write this to a file, do something like (note 'wb' for binary -- not 'w')
>>> f=file('stl.dat','wb')
>>> f.write(s)
>>> f.close()
Here we'll read it back for a check:
>>> f=file('stl.dat','rb')
>>> f.read()
'Header ... \x02\x00\
x00\x00\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@\x00\x00\xa0@\x00\x00\xc0@\x00\x00
\xe0@\x00\x00\x00A\x00\x00\x10A\x00\x00 A\x00\x000A\x00\x00 at A\x00\x00\x00\x000A\x00\x00 at A\
x00\x00PA\x00\x00`A\x00\x00pA\x00\x00\x80A\x00\x00\x88A\x00\x00\x90A\x00\x00\x98A\x00\x00\
xa0A\x00\x00\xa8A\x00\x00\xb0A\x00\x00'
Here is the header string followed by the 4-byte facet count:
>>> s[:84]
'Header ... \x02\x00\
x00\x00'
Here are the first 3 numbers in the first facet following the above:
>>> s[84:84+12]
'\x00\x00\x80?\x00\x00\x00@\x00\x00@@'
Or in numeric form:
>>> map(ord,s[84:84+12])
[0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64]
Here is the 4-byte facet count again. Note that it is little-endian (default for wintel).
The first byte in the list is the LSB. You can specify another order in the struct.pack format string.
>>> map(ord,s[80:84])
[2, 0, 0, 0]
Here we check the first 3 numbers in the first facet by packing the same numbers interactively:
>>> import struct
>>> map(ord,struct.pack('3f', 1.0, 2.0, 3.0))
[0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64]
This is not necessarily the best way to do what you want, but maybe you'll get a few ideas.
Double check everything ;-) The above is just a quick hack.
Regards,
Bengt Richter
More information about the Python-list
mailing list