Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Project: New Julia
Views: 239
1
# File: stlwrite.py
2
# Purpose: Export 3D objects built of faces with 3 or 4 vertices, as
3
# an ASCII or Binary STL file.
4
# License: MIT License
5
#
6
# Original source from http://code.activestate.com/recipes/578246-stl-writer/
7
# Modified by David Touretzky, November 2014, to compute surface normals.
8
9
import math
10
import struct
11
12
ASCII_FACET = """facet normal {normal[0]:.4f} {normal[1]:.4f} {normal[2]:.4f}
13
outer loop
14
vertex {face[0][0]:.4f} {face[0][1]:.4f} {face[0][2]:.4f}
15
vertex {face[1][0]:.4f} {face[1][1]:.4f} {face[1][2]:.4f}
16
vertex {face[2][0]:.4f} {face[2][1]:.4f} {face[2][2]:.4f}
17
endloop
18
endfacet
19
"""
20
21
BINARY_HEADER ="80sI"
22
BINARY_FACET = "12fH"
23
24
def crossproduct(u,v):
25
s1 = u[1]*v[2] - u[2]*v[1]
26
s2 = u[2]*v[0] - u[0]*v[2]
27
s3 = u[0]*v[1] - u[1]*v[0]
28
return [s1, s2, s3]
29
30
def norm(v):
31
return math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
32
33
def normalize(v):
34
m = norm(v)
35
if m == 0:
36
m = 1
37
return [v[0]/m, v[1]/m, v[2]/m]
38
39
def normalto(u,v):
40
return normalize(crossproduct(u,v))
41
42
def diff(u,v):
43
return [u[0]-v[0], u[1]-v[1], u[2]-v[2]]
44
45
class ASCII_STL_Writer:
46
""" Export 3D objects build of 3 or 4 vertices as ASCII STL file.
47
"""
48
def __init__(self, stream):
49
self.fp = stream
50
self._write_header()
51
52
def _write_header(self):
53
self.fp.write("solid python\n")
54
55
def close(self):
56
self.fp.write("endsolid python\n")
57
58
def _write(self, face):
59
n = normalto(diff(face[0],face[1]),diff(face[1],face[2]))
60
self.fp.write(ASCII_FACET.format(normal=n,face=face))
61
62
def _split(self, face):
63
p1, p2, p3, p4 = face
64
return (p2, p1, p3), (p3, p1, p4)
65
66
def add_face(self, face):
67
""" Add one face with 3 or 4 vertices. """
68
if len(face) == 4:
69
face1, face2 = self._split(face)
70
self._write(face1)
71
self._write(face2)
72
elif len(face) == 3:
73
self._write(face)
74
else:
75
raise ValueError('only 3 or 4 vertices for each face')
76
77
def add_faces(self, faces):
78
""" Add many faces. """
79
for face in faces:
80
self.add_face(face)
81
82
class Binary_STL_Writer(ASCII_STL_Writer):
83
""" Export 3D objects build of 3 or 4 vertices as binary STL file.
84
"""
85
def __init__(self, stream):
86
self.counter = 0
87
ASCII_STL_Writer.__init__(self,stream)
88
89
def close(self):
90
self._write_header()
91
92
def _write_header(self):
93
self.fp.seek(0)
94
self.fp.write(struct.pack(BINARY_HEADER, b'Python Binary STL Writer', self.counter))
95
96
def _write(self, face):
97
self.counter += 1
98
n = normalto(diff(face[0],face[1]),diff(face[1],face[2]))
99
data = [
100
n[0], n[1], n[2],
101
face[0][0], face[0][1], face[0][2],
102
face[1][0], face[1][1], face[1][2],
103
face[2][0], face[2][1], face[2][2],
104
0
105
]
106
self.fp.write(struct.pack(BINARY_FACET, *data))
107
108
def example():
109
def get_triangles():
110
p1 = (0, 0, 0)
111
p2 = (1, 2, 3)
112
p3 = (-5, -7, 4)
113
p4 = (3, -2, 6)
114
return [ [p1, p3, p2], [p2, p3, p4], [p4, p3, p1], [p4, p1, p2] ]
115
filename = 'triangles.stl'
116
with open(filename, 'wb') as fp:
117
writer = ASCII_STL_Writer(fp)
118
writer.add_faces(get_triangles())
119
writer.close()
120
print 'Wrote ' + filename
121
122