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
123 | # STL saver plug-in, written in Python
import lx
import lxifc
# We're going to use a visitor to examine the polygons in the meshes. The Evaluate()
# method is called for each polygon, and we read the vertex count from the accessor.
# The result is just a count of triangles and non-triangles.
#
class TriangleVisitor(lxifc.Visitor):
def __init__(self):
self.n_tri = 0
self.n_not = 0
def set_mesh(self, mesh):
self.poly = mesh.PolygonAccessor()
def vis_Evaluate(self):
if (self.poly.VertexCount() == 3):
self.n_tri += 1
else:
self.n_not += 1
# Another visitor does the actual output. We need a point accessor to read out the
# point positions for the polygon vertices. The lines will contain the output lines
# if all is successful.
#
class OutputVisitor(lxifc.Visitor):
def __init__(self, mon, n):
self.lines = []
self.mon = lx.object.Monitor(mon)
self.mon.Initialize(n)
def set_mesh(self, mesh):
self.poly = mesh.PolygonAccessor()
self.point = mesh.PointAccessor()
def vis_Evaluate(self):
if (self.poly.VertexCount() != 3):
return
norm = self.poly.Normal()
self.lines.append("facet {0:.8f} {1:.8f} {2:.8f}".format(-norm[0], norm[1], norm[2]))
self.lines.append(" outer loop")
for i in range(3):
self.point.Select(self.poly.VertexByIndex(i))
pos = self.point.Pos()
self.lines.append(" vertex {0} {1} {2}".format (-pos[0], -pos[1], -pos[2]))
self.lines.append(" end loop")
self.lines.append("end facet")
# Our STL saver class, with verify and save methods.
#
class STLSaver(lxifc.Saver):
def __init__(self):
self.scene_svc = lx.service.Scene()
# Mesh item type. We could look it up but don't have a symbol for that at the mo
#
self.mesh_type = 4 # shoud be: scene_svc.LookupType(lx.symbol.sITYPE_MESH)
# Enumeration scans the mesh items and enumerates the polygons for each.
#
def enum(self, scene, vis):
cread = scene.Channels(lx.symbol.s_ACTIONLAYER_SETUP, 0.0)
for i in range(scene.ItemCount(self.mesh_type)):
item = scene.ItemByIndex(self.mesh_type, i)
k = item.ChannelLookup('mesh') # should be: lx.symbol.sICHAN_MESH_MESH
mesh = lx.object.Mesh(cread.ValueObj(item, k))
vis.set_mesh(mesh)
vis.poly.Enumerate(lx.symbol.iMARK_ANY, vis, 0)
# Verify presents errors for no triangles and warnings for a mix of triangles and not.
#
def sav_Verify(self, source, message):
scene = lx.object.Scene(source)
msg = lx.object.Message(message)
vis = TriangleVisitor()
self.enum(scene, vis)
self.n_tri = vis.n_tri
if vis.n_tri == 0:
msg.SetCode(lx.result.NOTFOUND)
msg.SetMessage('common', '', 99)
msg.SetArgumentString(1, "Scene contains no triangles.")
elif vis.n_not:
msg.SetCode(lx.result.WARNING)
msg.SetMessage('common', '', 99)
msg.SetArgumentString(1, "Faces with more than 3 sides will be skipped.")
# Saving counts the triangles, and then scans them a second time to write
# them to the line buffer. Finally that's output to the STL text file.
#
def sav_Save(self, source, filename, monitor):
scene = lx.object.Scene(source)
cread = scene.Channels(lx.symbol.s_ACTIONLAYER_SETUP, 0.0)
vis = TriangleVisitor()
self.enum(scene, vis)
vis = OutputVisitor(monitor, vis.n_tri)
self.enum(scene, vis)
file = open(filename, 'w')
file.writelines( [x + '\n' for x in vis.lines] )
file.close()
# Bless the class to make it a first-class saver.
#
tags = {
lx.symbol.sSRV_USERNAME: "Stereolithograhpy STL",
lx.symbol.sSAV_OUTCLASS: lx.symbol.a_SCENE,
lx.symbol.sSAV_DOSTYPE : "STL"
}
lx.bless(STLSaver, "pySTLScene", tags)
|