home *** CD-ROM | disk | FTP | other *** search
- # ***** BEGIN LICENSE BLOCK *****
- # Version: MPL 1.1/GPL 2.0/LGPL 2.1
- #
- # The contents of this file are subject to the Mozilla Public License Version
- # 1.1 (the "License"); you may not use this file except in compliance with
- # the License. You may obtain a copy of the License at
- # http://www.mozilla.org/MPL/
- #
- # Software distributed under the License is distributed on an "AS IS" basis,
- # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- # for the specific language governing rights and limitations under the
- # License.
- #
- # The Original Code is the Python Computer Graphics Kit.
- #
- # The Initial Developer of the Original Code is Matthias Baas.
- # Portions created by the Initial Developer are Copyright (C) 2004
- # the Initial Developer. All Rights Reserved.
- #
- # Contributor(s):
- #
- # Alternatively, the contents of this file may be used under the terms of
- # either the GNU General Public License Version 2 or later (the "GPL"), or
- # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- # in which case the provisions of the GPL or the LGPL are applicable instead
- # of those above. If you wish to allow use of your version of this file only
- # under the terms of either the GPL or the LGPL, and not to allow others to
- # use your version of this file under the terms of the MPL, indicate your
- # decision by deleting the provisions above and replace them with the notice
- # and other provisions required by the GPL or the LGPL. If you do not delete
- # the provisions above, a recipient may use your version of this file under
- # the terms of any one of the MPL, the GPL or the LGPL.
- #
- # ***** END LICENSE BLOCK *****
- # $Id: stlimport.py,v 1.1 2005/01/09 20:13:06 mbaas Exp $
-
- import os.path, sys, struct
- from cgtypes import *
- from trimesh import TriMesh
- import pluginmanager
-
- # STLReader
- class STLReader:
-
- def __init__(self, filename):
- self.filename = filename
-
- # read
- def read(self):
- if self.isASCII():
- self.read_ascii()
- else:
- self.read_bin()
-
- # read_bin
- def read_bin(self):
- """Read a binary STL file.
- """
- f = file(self.filename, "rb")
-
- s = f.read(80)
- objname = s.split("\000")[0]
- s = f.read(4)
- numfaces = struct.unpack("<i", s)[0]
-
- self.begin(objname)
-
- for i in range(numfaces):
- s = f.read(50)
- normal = vec3(struct.unpack("<fff", s[:12]))
- v = struct.unpack("<fffffffff", s[12:48])
- verts = [vec3(v[0:3]), vec3(v[3:6]), vec3(v[6:9])]
- self.triangle(normal, verts)
-
- self.end(objname)
-
- # read_ascii
- def read_ascii(self):
- """Read a ASCII STL file.
- """
-
- f = file(self.filename)
-
- objname = "unnamed"
- normal = vec3()
- verts = []
-
- state = 0
- linenr = 0
- for s in f:
- linenr+=1
- a = s.split()
- if len(a)==0:
- continue
-
- # Begin of file
- if state==0:
- if a[0]=="solid":
- if len(a)>1:
- objname = a[1]
- self.begin(objname)
- state = 1
- else:
- raise SyntaxError, 'Keyword "solid" expected in line %d'%linenr
- # Begin of a triangle ("facet") or end of file ("endsolid")
- elif state==1:
- if a[0]=="facet":
- if len(a)!=5 or a[1]!="normal":
- raise SyntaxError, 'Syntax error in line %d'%linenr
- normal = vec3(float(a[2]), float(a[3]), float(a[4]))
- verts = []
- state = 2
- elif a[0]=="endsolid":
- self.end(objname)
- state = 0
- else:
- raise SyntaxError, 'Syntax error in line %d. Facet or end of solid expected.'%linenr
- # "outer loop"
- elif state==2:
- if len(a)!=2 or a[0]!="outer" or a[1]!="loop":
- raise SyntaxError, 'Keyword "outer loop" expected in line %d.'%linenr
- state = 3
- # A vertex definition
- elif state==3:
- if len(a)!=4 or a[0]!="vertex":
- raise SyntaxError, 'Syntax error in line %d: Vertex expected'%linenr
- v = vec3(float(a[1]), float(a[2]), float(a[3]))
- verts.append(v)
- if len(verts)==3:
- state = 4
- # "endloop"
- elif state==4:
- if a[0]!="endloop":
- raise SyntaxError, 'Keyword "endloop" expected in line %d.'%linenr
- state = 5
- # "endfacet"
- elif state==5:
- if a[0]!="endfacet":
- raise SyntaxError, 'Keyword "endfacet" expected in line %d.'%linenr
- self.triangle(normal, verts)
- state = 1
-
- # isASCII
- def isASCII(self):
- f = file(self.filename)
- s1 = f.readline().strip()
- s2 = f.readline().strip()
- f.close()
- if s1[:5]!="solid":
- return False
- if s2[:5]!="facet":
- return False
- return True
-
- # begin
- def begin(self, name):
- """Solid begin callback.
-
- This callback is called before the triangles are read.
- """
- pass
-
- # end
- def end(self, name):
- """Solid begin callback.
-
- This callback is called after the triangles were read.
- """
- pass
-
- # triangle
- def triangle(self, normal, verts):
- """Triangle callback.
-
- normal is the normal vector as vec3 and verts is a list with the
- three vertices (vec3s).
- """
- pass
-
-
- # STLImport
- class STLImport(STLReader):
-
- def __init__(self, filename):
- STLReader.__init__(self, filename)
- self.verts = []
- self.numfaces = 0
-
- # begin
- def begin(self, name):
- pass
-
- # end
- def end(self, name):
- faces = []
- for i in range(self.numfaces):
- faces.append(range(i*3, i*3+3))
- TriMesh(name=name, verts=self.verts, faces=faces)
-
- # triangle
- def triangle(self, normal, verts):
- """Triangle callback.
-
- normal is the normal vector as vec3 and verts is a list with the
- three vertices (vec3s).
- """
- self.numfaces += 1
- self.verts += verts
-
- # STLImporter
- class STLImporter:
-
- _protocols = ["Import"]
-
- # extension
- def extension():
- """Return the file extensions for this format."""
- return ["stl"]
- extension = staticmethod(extension)
-
- # description
- def description(self):
- """Return a short description for the file dialog."""
- return "StereoLithography"
- description = staticmethod(description)
-
- # importFile
- def importFile(self, filename):
- """Import a STL file."""
-
- reader = STLImport(filename)
- reader.read()
-
-
- ######################################################################
-
- # Register the Importer class as a plugin class
- pluginmanager.register(STLImporter)
-