Created
March 3, 2014 16:55
-
-
Save ryansturmer/9329299 to your computer and use it in GitHub Desktop.
STL Writer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
#coding:utf-8 | |
# Purpose: Export 3D objects, build of faces with 3 or 4 vertices, as ASCII or Binary STL file. | |
# License: MIT License | |
import struct | |
ASCII_FACET = """facet normal 0 0 0 | |
outer loop | |
vertex {face[0][0]:.4f} {face[0][1]:.4f} {face[0][2]:.4f} | |
vertex {face[1][0]:.4f} {face[1][1]:.4f} {face[1][2]:.4f} | |
vertex {face[2][0]:.4f} {face[2][1]:.4f} {face[2][2]:.4f} | |
endloop | |
endfacet | |
""" | |
BINARY_HEADER ="80sI" | |
BINARY_FACET = "12fH" | |
class ASCII_STL_Writer: | |
""" Export 3D objects build of 3 or 4 vertices as ASCII STL file. | |
""" | |
def __init__(self, stream): | |
self.fp = stream | |
self._write_header() | |
def _write_header(self): | |
self.fp.write("solid python\n") | |
def close(self): | |
self.fp.write("endsolid python\n") | |
def _write(self, face): | |
self.fp.write(ASCII_FACET.format(face=face)) | |
def _split(self, face): | |
p1, p2, p3, p4 = face | |
return (p1, p2, p3), (p3, p4, p1) | |
def add_face(self, face): | |
""" Add one face with 3 or 4 vertices. """ | |
if len(face) == 4: | |
face1, face2 = self._split(face) | |
self._write(face1) | |
self._write(face2) | |
elif len(face) == 3: | |
self._write(face) | |
else: | |
raise ValueError('only 3 or 4 vertices for each face') | |
def add_faces(self, faces): | |
""" Add many faces. """ | |
for face in faces: | |
self.add_face(face) | |
class Binary_STL_Writer(ASCII_STL_Writer): | |
""" Export 3D objects build of 3 or 4 vertices as binary STL file. | |
""" | |
def __init__(self, stream): | |
self.counter = 0 | |
super(Binary_STL_Writer, self).__init__(stream) | |
def close(self): | |
self._write_header() | |
def _write_header(self): | |
self.fp.seek(0) | |
self.fp.write(struct.pack(BINARY_HEADER, b'Python Binary STL Writer', self.counter)) | |
def _write(self, face): | |
self.counter += 1 | |
data = [ | |
0., 0., 0., | |
face[0][0], face[0][1], face[0][2], | |
face[1][0], face[1][1], face[1][2], | |
face[2][0], face[2][1], face[2][2], | |
0 | |
] | |
self.fp.write(struct.pack(BINARY_FACET, *data)) | |
def example(): | |
def get_cube(): | |
# cube corner points | |
s = 3. | |
p1 = (0, 0, 0) | |
p2 = (0, 0, s) | |
p3 = (0, s, 0) | |
p4 = (0, s, s) | |
p5 = (s, 0, 0) | |
p6 = (s, 0, s) | |
p7 = (s, s, 0) | |
p8 = (s, s, s) | |
# define the 6 cube faces | |
# faces just lists of 3 or 4 vertices | |
return [ | |
[p1, p5, p7, p3], | |
[p1, p5, p6, p2], | |
[p5, p7, p8, p6], | |
[p7, p8, p4, p3], | |
[p1, p3, p4, p2], | |
[p2, p6, p8, p4], | |
] | |
with open('cube.stl', 'wb') as fp: | |
writer = Binary_STL_Writer(fp) | |
writer.add_faces(get_cube()) | |
writer.close() | |
if __name__ == '__main__': | |
example() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just a recipe from activestate.