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: |
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: |