-
-
Notifications
You must be signed in to change notification settings - Fork 183
/
STLWriter.py
122 lines (102 loc) · 5.37 KB
/
STLWriter.py
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# Copyright (c) 2016 Ultimaker B.V.
# Copyright (c) 2013 David Braam
# Uranium is released under the terms of the LGPLv3 or higher.
import struct
import time
from UM.Logger import Logger
from UM.Mesh.MeshWriter import MeshWriter
from UM.i18n import i18nCatalog
catalog = i18nCatalog("uranium")
class STLWriter(MeshWriter):
def write(self, stream, nodes, mode = MeshWriter.OutputMode.TextMode):
"""Write the specified sequence of nodes to a stream in the STL format.
:param stream: The output stream to write to.
:param nodes: A sequence of scene nodes to write to the output stream.
:param mode: The output mode to use for writing scene nodes. Text mode
causes the writer to write in STL's ASCII format. Binary mode causes the
writer to write in STL's binary format. Any other mode is invalid.
"""
try:
MeshWriter._meshNodes(nodes).__next__()
except StopIteration:
Logger.log("e", "There is no mesh to write.")
self.setInformation(catalog.i18nc("@error:no mesh", "There is no mesh to write."))
return False # Don't try to write a file if there is no mesh.
if mode == MeshWriter.OutputMode.TextMode:
self._writeAscii(stream, MeshWriter._meshNodes(nodes))
elif mode == MeshWriter.OutputMode.BinaryMode:
self._writeBinary(stream, MeshWriter._meshNodes(nodes))
else:
Logger.log("e", "Unsupported output mode writing STL to stream")
self.setInformation(catalog.i18nc("@error:not supported", "Unsupported output mode writing STL to stream."))
return False
return True
def _writeAscii(self, stream, nodes):
name = "Uranium STLWriter {0}".format(time.strftime("%a %d %b %Y %H:%M:%S"))
stream.write("solid {0}\n".format(name))
for node in nodes:
mesh_data = node.getMeshData().getTransformed(node.getWorldTransformation())
verts = mesh_data.getVertices()
if verts is None:
continue # No mesh data, nothing to do.
if mesh_data.hasIndices():
for face in mesh_data.getIndices():
stream.write("facet normal 0.0 0.0 0.0\n")
stream.write(" outer loop\n")
v1 = verts[face[0]]
v2 = verts[face[1]]
v3 = verts[face[2]]
stream.write(" vertex {0} {1} {2}\n".format(v1[0], -v1[2], v1[1]))
stream.write(" vertex {0} {1} {2}\n".format(v2[0], -v2[2], v2[1]))
stream.write(" vertex {0} {1} {2}\n".format(v3[0], -v3[2], v3[1]))
stream.write(" endloop\n")
stream.write("endfacet\n")
else:
num_verts = mesh_data.getVertexCount()
for index in range(0, num_verts - 2, 3):
stream.write("facet normal 0.0 0.0 0.0\n")
stream.write(" outer loop\n")
v1 = verts[index]
v2 = verts[index + 1]
v3 = verts[index + 2]
stream.write(" vertex {0} {1} {2}\n".format(v1[0], -v1[2], v1[1]))
stream.write(" vertex {0} {1} {2}\n".format(v2[0], -v2[2], v2[1]))
stream.write(" vertex {0} {1} {2}\n".format(v3[0], -v3[2], v3[1]))
stream.write(" endloop\n")
stream.write("endfacet\n")
stream.write("endsolid {0}\n".format(name))
def _writeBinary(self, stream, nodes):
stream.write("Uranium STLWriter {0}".format(time.strftime("%a %d %b %Y %H:%M:%S")).encode().ljust(80, b"\000"))
face_count = 0
nodes = list(nodes)
for node in nodes:
if node.getMeshData().hasIndices():
face_count += node.getMeshData().getFaceCount()
else:
face_count += node.getMeshData().getVertexCount() / 3
stream.write(struct.pack("<I", int(face_count))) #Write number of faces to STL
for node in nodes:
mesh_data = node.getMeshData().getTransformed(node.getWorldTransformation())
if mesh_data.hasIndices():
verts = mesh_data.getVertices()
for face in mesh_data.getIndices():
v1 = verts[face[0]]
v2 = verts[face[1]]
v3 = verts[face[2]]
stream.write(struct.pack("<fff", 0.0, 0.0, 0.0))
stream.write(struct.pack("<fff", v1[0], -v1[2], v1[1]))
stream.write(struct.pack("<fff", v2[0], -v2[2], v2[1]))
stream.write(struct.pack("<fff", v3[0], -v3[2], v3[1]))
stream.write(struct.pack("<H", 0))
else:
num_verts = mesh_data.getVertexCount()
verts = mesh_data.getVertices()
for index in range(0, num_verts - 1, 3):
v1 = verts[index]
v2 = verts[index + 1]
v3 = verts[index + 2]
stream.write(struct.pack("<fff", 0.0, 0.0, 0.0))
stream.write(struct.pack("<fff", v1[0], -v1[2], v1[1]))
stream.write(struct.pack("<fff", v2[0], -v2[2], v2[1]))
stream.write(struct.pack("<fff", v3[0], -v3[2], v3[1]))
stream.write(struct.pack("<H", 0))