Howto write StL (StereoLithography) Binary Format with python?

Bengt Richter bokr at oz.net
Fri Aug 23 19:55:14 CEST 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