summaryrefslogtreecommitdiff
path: root/import_tools/pyldraw_STLWriter.py
blob: 6e7f5c418c1f2f4b79a7ad8901d9c9801b0a7ae0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/isr/bin/python
"""
stl.py - STL writer for the ldraw Python package.

Copyright (C) 2009 Bryan Bishop <kanzure@gmail.com>

This file is part of the ldraw Python package.

see pythonOCC/samples/Level2/DataExchange/import_stl.py

./ldr2stl.py /home/kanzure/local/ldraw/ldraw/even_more/LDRAW/parts.lst simple.ldr simple.stl
"""

from ldraw.geometry import Identity, Vector
from ldraw.parts import Parts, Quadrilateral, Triangle
from ldraw.pieces import Piece
import sys
import numpy

class STLWriter:
    def __init__(self, parts, stl_file):
        self.parts = parts
        self.stl_file = stl_file
        self.minimum = Vector(0, 0, 0)
        self.maximum = Vector(0, 0, 0)

    def write(self, model, current_matrix=Identity(), current_position=Vector(0,0,0), level=0):
        for obj in model.objects:
            if isinstance(obj, Piece):
                part = self.parts.part(code=obj.part)
                if part:
                    matrix = obj.matrix
                    self.write(part, current_matrix * matrix, current_position + current_matrix * obj.position, level+1)
                else:
                    sys.stderr.write("Part not found: %s\n" % obj.part)
            elif isinstance(obj, Triangle):
                p1 = current_matrix * obj.p1 + current_position
                p2 = current_matrix * obj.p2 + current_position
                p3 = current_matrix * obj.p3 + current_position
                if abs((p3 - p1).cross(p2-p1)) !=0:
                    self._write_triangle(p1, p2, p3)
            elif isinstance(obj, Quadrilateral):
                p1 = current_matrix * obj.p1 + current_position
                p2 = current_matrix * obj.p2 + current_position
                p3 = current_matrix * obj.p3 + current_position
                p4 = current_matrix * obj.p4 + current_position
                if abs((p3-p1).cross(p2-p1)) != 0:
                    self._write_triangle(p1,p2,p3)
                if abs((p3-p1).cross(p4-p1)) != 0:
                    self._write_triangle(p3, p4, p1)

    def _write_triangle(self, v1, v2, v3):
        self.minimum = Vector(min(self.minimum.x, v1.x, v2.x, v3.x), min(self.minimum.y, -v1.y, -v2.y, -v3.y), min(self.minimum.z, v1.z, v2.z, v3.z))
        self.maximum = Vector(max(self.maximum.x, v1.x, v2.x, v3.x), max(self.maximum.y, -v1.y, -v2.y, -v3.y), max(self.maximum.z, v1.z, v2.z, v3.z))
        #normal vector = cross product of any two of the edges
        #vec1 = p1-p2
        vec1 = numpy.matrix([v1.x-v2.x,v1.y-v2.y,v1.z-v2.z])
        #vec2 = p1-p3
        #vec2 = numpy.matrix([v1.x-v3.x,v1.y-v3.y,v1.z-v3.z])
        vec2 = numpy.matrix([v2.x-v3.x,v2.y-v3.y,v2.z-v3.z])
        #vec2 = numpy.matrix([v3.x-v1.x,v3.y-v1.y,v3.z-v1.z])

        normal_vector = numpy.cross(vec1, vec2)
        self.stl_file.write("facet normal %1.3f %1.3f %1.3f\n"
            "\touter loop\n"
            "\t\tvertex %1.3f %1.3f %1.3f\n"
            "\t\tvertex %1.3f %1.3f %1.3f\n"
            "\t\tvertex %1.3f %1.3f %1.3f\n"
            "\tendloop\n"
            "endfacet\n" % (normal_vector.item(0), normal_vector.item(1), normal_vector.item(2),
                          v1.x, -v1.y, v1.z,
                          v2.x, -v2.y, v2.z,
                          v3.x, -v3.y, v3.z)
                          )