home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / lib / site-packages / cgkit / stlimport.py < prev    next >
Encoding:
Python Source  |  2007-01-11  |  7.1 KB  |  239 lines

  1. # ***** BEGIN LICENSE BLOCK *****
  2. # Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. #
  4. # The contents of this file are subject to the Mozilla Public License Version
  5. # 1.1 (the "License"); you may not use this file except in compliance with
  6. # the License. You may obtain a copy of the License at
  7. # http://www.mozilla.org/MPL/
  8. #
  9. # Software distributed under the License is distributed on an "AS IS" basis,
  10. # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. # for the specific language governing rights and limitations under the
  12. # License.
  13. #
  14. # The Original Code is the Python Computer Graphics Kit.
  15. #
  16. # The Initial Developer of the Original Code is Matthias Baas.
  17. # Portions created by the Initial Developer are Copyright (C) 2004
  18. # the Initial Developer. All Rights Reserved.
  19. #
  20. # Contributor(s):
  21. #
  22. # Alternatively, the contents of this file may be used under the terms of
  23. # either the GNU General Public License Version 2 or later (the "GPL"), or
  24. # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  25. # in which case the provisions of the GPL or the LGPL are applicable instead
  26. # of those above. If you wish to allow use of your version of this file only
  27. # under the terms of either the GPL or the LGPL, and not to allow others to
  28. # use your version of this file under the terms of the MPL, indicate your
  29. # decision by deleting the provisions above and replace them with the notice
  30. # and other provisions required by the GPL or the LGPL. If you do not delete
  31. # the provisions above, a recipient may use your version of this file under
  32. # the terms of any one of the MPL, the GPL or the LGPL.
  33. #
  34. # ***** END LICENSE BLOCK *****
  35. # $Id: stlimport.py,v 1.1 2005/01/09 20:13:06 mbaas Exp $
  36.  
  37. import os.path, sys, struct
  38. from cgtypes import *
  39. from trimesh import TriMesh
  40. import pluginmanager
  41.  
  42. # STLReader
  43. class STLReader:
  44.     
  45.     def __init__(self, filename):
  46.         self.filename = filename
  47.  
  48.     # read
  49.     def read(self):
  50.         if self.isASCII():
  51.             self.read_ascii()
  52.         else:
  53.             self.read_bin()
  54.  
  55.     # read_bin
  56.     def read_bin(self):
  57.         """Read a binary STL file.
  58.         """
  59.         f = file(self.filename, "rb")
  60.  
  61.         s = f.read(80)
  62.         objname = s.split("\000")[0]
  63.         s = f.read(4)
  64.         numfaces = struct.unpack("<i", s)[0]
  65.  
  66.         self.begin(objname)
  67.  
  68.         for i in range(numfaces):
  69.             s = f.read(50)
  70.             normal = vec3(struct.unpack("<fff", s[:12]))
  71.             v = struct.unpack("<fffffffff", s[12:48])
  72.             verts = [vec3(v[0:3]), vec3(v[3:6]), vec3(v[6:9])]
  73.             self.triangle(normal, verts)
  74.  
  75.         self.end(objname)
  76.  
  77.     # read_ascii
  78.     def read_ascii(self):
  79.         """Read a ASCII STL file.
  80.         """
  81.         
  82.         f = file(self.filename)
  83.         
  84.         objname = "unnamed"
  85.         normal = vec3()
  86.         verts = []
  87.  
  88.         state = 0
  89.         linenr = 0
  90.         for s in f:
  91.             linenr+=1
  92.             a = s.split()
  93.             if len(a)==0:
  94.                 continue
  95.             
  96.             # Begin of file
  97.             if state==0:
  98.                 if a[0]=="solid":
  99.                     if len(a)>1:
  100.                         objname = a[1]
  101.                     self.begin(objname)
  102.                     state = 1
  103.                 else:
  104.                     raise SyntaxError, 'Keyword "solid" expected in line %d'%linenr
  105.             # Begin of a triangle ("facet") or end of file ("endsolid")
  106.             elif state==1:
  107.                 if a[0]=="facet":
  108.                     if len(a)!=5 or a[1]!="normal":
  109.                         raise SyntaxError, 'Syntax error in line %d'%linenr
  110.                     normal = vec3(float(a[2]), float(a[3]), float(a[4]))
  111.                     verts = []
  112.                     state = 2
  113.                 elif a[0]=="endsolid":
  114.                     self.end(objname)
  115.                     state = 0
  116.                 else:
  117.                     raise SyntaxError, 'Syntax error in line %d. Facet or end of solid expected.'%linenr
  118.             # "outer loop"
  119.             elif state==2:
  120.                 if len(a)!=2 or a[0]!="outer" or a[1]!="loop":
  121.                     raise SyntaxError, 'Keyword "outer loop" expected in line %d.'%linenr
  122.                 state = 3
  123.             # A vertex definition
  124.             elif state==3:
  125.                 if len(a)!=4 or a[0]!="vertex":
  126.                     raise SyntaxError, 'Syntax error in line %d: Vertex expected'%linenr
  127.                 v = vec3(float(a[1]), float(a[2]), float(a[3]))
  128.                 verts.append(v)
  129.                 if len(verts)==3:
  130.                     state = 4
  131.             # "endloop"
  132.             elif state==4:
  133.                 if a[0]!="endloop":
  134.                     raise SyntaxError, 'Keyword "endloop" expected in line %d.'%linenr
  135.                 state = 5
  136.             # "endfacet"
  137.             elif state==5:
  138.                 if a[0]!="endfacet":
  139.                     raise SyntaxError, 'Keyword "endfacet" expected in line %d.'%linenr
  140.                 self.triangle(normal, verts)
  141.                 state = 1
  142.  
  143.     # isASCII
  144.     def isASCII(self):
  145.         f = file(self.filename)
  146.         s1 = f.readline().strip()
  147.         s2 = f.readline().strip()
  148.         f.close()
  149.         if s1[:5]!="solid":
  150.             return False
  151.         if s2[:5]!="facet":
  152.             return False
  153.         return True
  154.  
  155.     # begin
  156.     def begin(self, name):
  157.         """Solid begin callback.
  158.  
  159.         This callback is called before the triangles are read.
  160.         """
  161.         pass
  162.  
  163.     # end
  164.     def end(self, name):
  165.         """Solid begin callback.
  166.  
  167.         This callback is called after the triangles were read.
  168.         """
  169.         pass
  170.  
  171.     # triangle
  172.     def triangle(self, normal, verts):
  173.         """Triangle callback.
  174.  
  175.         normal is the normal vector as vec3 and verts is a list with the
  176.         three vertices (vec3s).
  177.         """
  178.         pass
  179.  
  180.  
  181. # STLImport
  182. class STLImport(STLReader):
  183.     
  184.     def __init__(self, filename):
  185.         STLReader.__init__(self, filename)
  186.         self.verts = []
  187.         self.numfaces = 0
  188.  
  189.     # begin
  190.     def begin(self, name):
  191.         pass
  192.  
  193.     # end
  194.     def end(self, name):
  195.         faces = []
  196.         for i in range(self.numfaces):
  197.             faces.append(range(i*3, i*3+3))
  198.         TriMesh(name=name, verts=self.verts, faces=faces)
  199.  
  200.     # triangle
  201.     def triangle(self, normal, verts):
  202.         """Triangle callback.
  203.  
  204.         normal is the normal vector as vec3 and verts is a list with the
  205.         three vertices (vec3s).
  206.         """
  207.         self.numfaces += 1
  208.         self.verts += verts
  209.  
  210. # STLImporter
  211. class STLImporter:
  212.  
  213.     _protocols = ["Import"]
  214.  
  215.     # extension
  216.     def extension():
  217.         """Return the file extensions for this format."""
  218.         return ["stl"]
  219.     extension = staticmethod(extension)
  220.  
  221.     # description
  222.     def description(self):
  223.         """Return a short description for the file dialog."""
  224.         return "StereoLithography"
  225.     description = staticmethod(description)
  226.  
  227.     # importFile
  228.     def importFile(self, filename):
  229.         """Import a STL file."""
  230.  
  231.         reader = STLImport(filename)
  232.         reader.read()
  233.  
  234.  
  235. ######################################################################
  236.  
  237. # Register the Importer class as a plugin class
  238. pluginmanager.register(STLImporter)
  239.