printrun-src/printrun/stltool.py

changeset 46
cce0af6351f0
parent 15
0bbb006204fc
equal deleted inserted replaced
45:c82943fb205f 46:cce0af6351f0
40 40
41 def homogeneous(v, w = 1): 41 def homogeneous(v, w = 1):
42 return numpy.append(v, w) 42 return numpy.append(v, w)
43 43
44 def applymatrix(facet, matrix = I): 44 def applymatrix(facet, matrix = I):
45 return genfacet(map(lambda x: matrix.dot(homogeneous(x))[:3], facet[1])) 45 return genfacet([matrix.dot(homogeneous(x))[:3] for x in facet[1]])
46 46
47 def ray_triangle_intersection(ray_near, ray_dir, (v1, v2, v3)): 47 def ray_triangle_intersection(ray_near, ray_dir, v123):
48 """ 48 """
49 Möller–Trumbore intersection algorithm in pure python 49 Möller–Trumbore intersection algorithm in pure python
50 Based on http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm 50 Based on http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
51 """ 51 """
52 v1, v2, v3 = v123
52 eps = 0.000001 53 eps = 0.000001
53 edge1 = v2 - v1 54 edge1 = v2 - v1
54 edge2 = v3 - v1 55 edge2 = v3 - v1
55 pvec = numpy.cross(ray_dir, edge2) 56 pvec = numpy.cross(ray_dir, edge2)
56 det = edge1.dot(pvec) 57 det = edge1.dot(pvec)
97 def emitstl(filename, facets = [], objname = "stltool_export", binary = True): 98 def emitstl(filename, facets = [], objname = "stltool_export", binary = True):
98 if filename is None: 99 if filename is None:
99 return 100 return
100 if binary: 101 if binary:
101 with open(filename, "wb") as f: 102 with open(filename, "wb") as f:
102 buf = "".join(["\0"] * 80) 103 buf = b"".join([b"\0"] * 80)
103 buf += struct.pack("<I", len(facets)) 104 buf += struct.pack("<I", len(facets))
104 facetformat = struct.Struct("<ffffffffffffH") 105 facetformat = struct.Struct("<ffffffffffffH")
105 for facet in facets: 106 for facet in facets:
106 l = list(facet[0][:]) 107 l = list(facet[0][:])
107 for vertex in facet[1]: 108 for vertex in facet[1]:
118 f.write(" vertex " + " ".join(map(str, j)) + "\n") 119 f.write(" vertex " + " ".join(map(str, j)) + "\n")
119 f.write(" endloop" + "\n") 120 f.write(" endloop" + "\n")
120 f.write(" endfacet" + "\n") 121 f.write(" endfacet" + "\n")
121 f.write("endsolid " + objname + "\n") 122 f.write("endsolid " + objname + "\n")
122 123
123 class stl(object): 124 class stl:
124 125
125 _dims = None 126 _dims = None
126 127
127 def _get_dims(self): 128 def _get_dims(self):
128 if self._dims is None: 129 if self._dims is None:
161 self.infacet = 0 162 self.infacet = 0
162 self.inloop = 0 163 self.inloop = 0
163 self.facetloc = 0 164 self.facetloc = 0
164 if filename is None: 165 if filename is None:
165 return 166 return
166 with open(filename) as f: 167 with open(filename,encoding="ascii",errors="ignore") as f:
167 data = f.read() 168 data = f.read()
168 if "facet normal" in data[1:300] and "outer loop" in data[1:300]: 169 if "facet normal" in data[1:300] and "outer loop" in data[1:300]:
169 lines = data.split("\n") 170 lines = data.split("\n")
170 for line in lines: 171 for line in lines:
171 if not self.parseline(line): 172 if not self.parseline(line):
179 if not len(newdata): 180 if not len(newdata):
180 break 181 break
181 buf += newdata 182 buf += newdata
182 facetcount = struct.unpack_from("<I", buf, 80) 183 facetcount = struct.unpack_from("<I", buf, 80)
183 facetformat = struct.Struct("<ffffffffffffH") 184 facetformat = struct.Struct("<ffffffffffffH")
184 for i in xrange(facetcount[0]): 185 for i in range(facetcount[0]):
185 buf = f.read(50) 186 buf = f.read(50)
186 while len(buf) < 50: 187 while len(buf) < 50:
187 newdata = f.read(50 - len(buf)) 188 newdata = f.read(50 - len(buf))
188 if not len(newdata): 189 if not len(newdata):
189 break 190 break
190 buf += newdata 191 buf += newdata
191 fd = list(facetformat.unpack(buf)) 192 fd = list(facetformat.unpack(buf))
192 self.name = "binary soloid" 193 self.name = "binary soloid"
193 facet = [fd[:3], [fd[3:6], fd[6:9], fd[9:12]]] 194 facet = [fd[:3], [fd[3:6], fd[6:9], fd[9:12]]]
194 self.facets.append(facet) 195 self.facets.append(facet)
195 self.facetsminz.append((min(map(lambda x: x[2], facet[1])), facet)) 196 self.facetsminz.append((min(x[2] for x in facet[1]), facet))
196 self.facetsmaxz.append((max(map(lambda x: x[2], facet[1])), facet)) 197 self.facetsmaxz.append((max(x[2] for x in facet[1]), facet))
197 f.close() 198 f.close()
198 return 199 return
199 200
200 def intersect_box(self, ray_near, ray_far): 201 def intersect_box(self, ray_near, ray_far):
201 ray_near = numpy.array(ray_near) 202 ray_near = numpy.array(ray_near)
264 s.infacet = 0 265 s.infacet = 0
265 s.inloop = 0 266 s.inloop = 0
266 s.facetloc = 0 267 s.facetloc = 0
267 s.name = self.name 268 s.name = self.name
268 for facet in s.facets: 269 for facet in s.facets:
269 s.facetsminz += [(min(map(lambda x:x[2], facet[1])), facet)] 270 s.facetsminz += [(min(x[2] for x in facet[1]), facet)]
270 s.facetsmaxz += [(max(map(lambda x:x[2], facet[1])), facet)] 271 s.facetsmaxz += [(max(x[2] for x in facet[1]), facet)]
271 return s 272 return s
272 273
273 def translation_matrix(self, v): 274 def translation_matrix(self, v):
274 matrix = [[1, 0, 0, v[0]], 275 matrix = [[1, 0, 0, v[0]],
275 [0, 1, 0, v[1]], 276 [0, 1, 0, v[1]],
326 s.infacet = 0 327 s.infacet = 0
327 s.inloop = 0 328 s.inloop = 0
328 s.facetloc = 0 329 s.facetloc = 0
329 s.name = self.name 330 s.name = self.name
330 for facet in s.facets: 331 for facet in s.facets:
331 s.facetsminz += [(min(map(lambda x:x[2], facet[1])), facet)] 332 s.facetsminz += [(min(x[2] for x in facet[1]), facet)]
332 s.facetsmaxz += [(max(map(lambda x:x[2], facet[1])), facet)] 333 s.facetsmaxz += [(max(x[2] for x in facet[1]), facet)]
333 return s 334 return s
334 335
335 def export(self, f = sys.stdout): 336 def export(self, f = sys.stdout):
336 f.write("solid " + self.name + "\n") 337 f.write("solid " + self.name + "\n")
337 for i in self.facets: 338 for i in self.facets:
354 return 0 355 return 0
355 elif l.startswith("facet normal"): 356 elif l.startswith("facet normal"):
356 l = l.replace(", ", ".") 357 l = l.replace(", ", ".")
357 self.infacet = 1 358 self.infacet = 1
358 self.facetloc = 0 359 self.facetloc = 0
359 normal = numpy.array(map(float, l.split()[2:])) 360 normal = numpy.array([float(f) for f in l.split()[2:]])
360 self.facet = (normal, (numpy.zeros(3), numpy.zeros(3), numpy.zeros(3))) 361 self.facet = (normal, (numpy.zeros(3), numpy.zeros(3), numpy.zeros(3)))
361 elif l.startswith("endfacet"): 362 elif l.startswith("endfacet"):
362 self.infacet = 0 363 self.infacet = 0
363 self.facets.append(self.facet) 364 self.facets.append(self.facet)
364 facet = self.facet 365 facet = self.facet
365 self.facetsminz += [(min(map(lambda x:x[2], facet[1])), facet)] 366 self.facetsminz += [(min(x[2] for x in facet[1]), facet)]
366 self.facetsmaxz += [(max(map(lambda x:x[2], facet[1])), facet)] 367 self.facetsmaxz += [(max(x[2] for x in facet[1]), facet)]
367 elif l.startswith("vertex"): 368 elif l.startswith("vertex"):
368 l = l.replace(", ", ".") 369 l = l.replace(", ", ".")
369 self.facet[1][self.facetloc][:] = numpy.array(map(float, l.split()[1:])) 370 self.facet[1][self.facetloc][:] = numpy.array([float(f) for f in l.split()[1:]])
370 self.facetloc += 1 371 self.facetloc += 1
371 return 1 372 return 1
372 373
373 if __name__ == "__main__": 374 if __name__ == "__main__":
374 s = stl("../../Downloads/frame-vertex-neo-foot-x4.stl") 375 s = stl("../../Downloads/frame-vertex-neo-foot-x4.stl")
375 for i in xrange(11, 11): 376 for i in range(11, 11):
376 working = s.facets[:] 377 working = s.facets[:]
377 for j in reversed(sorted(s.facetsminz)): 378 for j in reversed(sorted(s.facetsminz)):
378 if j[0] > i: 379 if j[0] > i:
379 working.remove(j[1]) 380 working.remove(j[1])
380 else: 381 else:
383 if j[0] < i: 384 if j[0] < i:
384 working.remove(j[1]) 385 working.remove(j[1])
385 else: 386 else:
386 break 387 break
387 388
388 print i, len(working) 389 print(i, len(working))
389 emitstl("../../Downloads/frame-vertex-neo-foot-x4-a.stl", s.facets, "emitted_object") 390 emitstl("../../Downloads/frame-vertex-neo-foot-x4-a.stl", s.facets, "emitted_object")
390 # stl("../prusamendel/stl/mendelplate.stl") 391 # stl("../prusamendel/stl/mendelplate.stl")

mercurial