Remote Debug example

From The Foundry MODO SDK wiki
Jump to: navigation, search
# 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)