chiark / gitweb /
f157ce3197097d3a1b4416a4ed1eba0879934489
[cura.git] / Cura / util / stl.py
1 import sys, math, re, os, struct, time
2
3 import util3d
4 import mesh
5
6 class stlModel(mesh.mesh):
7         def __init__(self):
8                 super(stlModel, self).__init__()
9
10         def load(self, filename):
11                 f = open(filename, "rb")
12                 if f.read(5).lower() == "solid":
13                         self._loadAscii(f)
14                         if len(self.faces) < 1:
15                                 f.seek(6, os.SEEK_SET)
16                                 self._loadBinary(f)
17                 else:
18                         self._loadBinary(f)
19                 f.close()
20                 
21                 self._postProcessAfterLoad()
22                 return self
23         
24         def _loadAscii(self, f):
25                 cnt = 0
26                 for line in f:
27                         if 'vertex' in line:
28                                 data = line.split()
29                                 if cnt == 0:
30                                         v0 = util3d.Vector3(float(data[1]), float(data[2]), float(data[3]))
31                                         cnt = 1
32                                 elif cnt == 1:
33                                         v1 = util3d.Vector3(float(data[1]), float(data[2]), float(data[3]))
34                                         cnt = 2
35                                 elif cnt == 2:
36                                         v2 = util3d.Vector3(float(data[1]), float(data[2]), float(data[3]))
37                                         self.addFace(v0, v1, v2)
38                                         cnt = 0
39
40         def _loadBinary(self, f):
41                 #Skip the header
42                 f.read(80-6)
43                 faceCount = struct.unpack('<I', f.read(4))[0]
44                 for idx in xrange(0, faceCount):
45                         data = struct.unpack("<ffffffffffffH", f.read(50))
46                         v0 = util3d.Vector3(data[3], data[4], data[5])
47                         v1 = util3d.Vector3(data[6], data[7], data[8])
48                         v2 = util3d.Vector3(data[9], data[10], data[11])
49                         self.addFace(v0, v1, v2)
50
51 def saveAsSTL(mesh, filename):
52         f = open(filename, 'wb')
53         #Write the STL binary header. This can contain any info, except for "SOLID" at the start.
54         f.write(("CURA BINARY STL EXPORT. " + time.strftime('%a %d %b %Y %H:%M:%S')).ljust(80, '\000'))
55         #Next follow 4 binary bytes containing the amount of faces, and then the face information.
56         f.write(struct.pack("<I", len(mesh.faces)))
57         for face in mesh.faces:
58                 v1 = face.v[0]
59                 v2 = face.v[1]
60                 v3 = face.v[2]
61                 normal = (v2 - v1).cross(v3 - v1)
62                 normal.normalize()
63                 f.write(struct.pack("<fff", normal.x, normal.y, normal.z))
64                 f.write(struct.pack("<fff", v1.x, v1.y, v1.z))
65                 f.write(struct.pack("<fff", v2.x, v2.y, v2.z))
66                 f.write(struct.pack("<fff", v3.x, v3.y, v3.z))
67                 f.write(struct.pack("<H", 0))
68         f.close()
69
70 if __name__ == '__main__':
71         for filename in sys.argv[1:]:
72                 m = stlModel().load(filename)
73                 print("Loaded %d faces" % (len(m.faces)))
74                 parts = m.splitToParts()
75                 for p in parts:
76                         saveAsSTL(p, "export_%i.stl" % parts.index(p))
77