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 / asfamc.py < prev    next >
Encoding:
Python Source  |  2007-01-11  |  13.3 KB  |  445 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: asfamc.py,v 1.3 2005/02/06 22:24:27 mbaas Exp $
  36.  
  37. ## \file asfamc.py
  38. ## Contains the ASFReader and AMCReader class.
  39.  
  40. import string
  41.  
  42. # ReaderBase
  43. class ReaderBase:
  44.     """Base class for the ASFReader and AMCReader classes.
  45.  
  46.     A derived class must implement readXyz() method where Xyz is
  47.     the section name (the keyword in the file is ':xyz').
  48.     If such a read method is not implemented, the corresponding
  49.     section is ignored.
  50.     """
  51.  
  52.     def __init__(self, filename):
  53.  
  54.         self.filename = filename
  55.         # A list of unprocessed tokens (strings)
  56.         self.tokenlist = []
  57.         # The last returned token (string)
  58.         self.lasttok = None
  59.         self.lastline = None
  60.         self.undoline = None
  61.         # The current line number
  62.         self.linenr = 0
  63.  
  64.     # read
  65.     def read(self):
  66.         """Read the entire file.
  67.         """
  68.         self.fhandle = file(self.filename)
  69.  
  70.         while 1:
  71.             try:
  72.                 tok = self.token()
  73.             except StopIteration:
  74.                 break
  75.  
  76.             # Check if the keyword starts with ':' (a new section)
  77.             if tok[0]!=":":
  78.                 raise SyntaxError, "Syntax error in line %d: Invalid keyword '%s'"%(self.linenr, tok)
  79.  
  80.             # Read the current section...
  81.  
  82.             # Determine the method name (only letters and digits allowed,
  83.             # everything else will be removed)
  84.             mn = tok[1:].capitalize()
  85.             methodname = ""
  86.             for c in mn:
  87.                 if c not in string.ascii_letters and c not in string.digits:
  88.                     continue
  89.                 methodname += c
  90.  
  91.             handler = getattr(self, "read"+methodname, None)
  92.             if handler!=None:
  93.                 handler()
  94.             else:
  95.                 try:
  96.                     self.skipSection()
  97.                 except:
  98.                     break        
  99.  
  100.     # intToken
  101.     def intToken(self):
  102.         """Return the next token which must be an int.
  103.         """
  104.  
  105.         tok = self.token()
  106.         try:
  107.             return int(tok)
  108.         except ValueError:
  109.             raise SyntaxError, "Syntax error in line %d: Integer expected, got '%s' instead"%(self.linenr, tok)
  110.  
  111.     # floatToken
  112.     def floatToken(self):
  113.         """Return the next token which must be a float.
  114.         """
  115.  
  116.         tok = self.token()
  117.         try:
  118.             return float(tok)
  119.         except ValueError:
  120.             raise SyntaxError, "Syntax error in line %d: Float expected, got '%s' instead"%(self.linenr, tok)
  121.  
  122.     # token
  123.     def token(self):
  124.         """Return the next token."""
  125.  
  126.         # Are there still some tokens left? then just return the next one
  127.         if self.tokenlist!=[]:
  128.             tok = self.tokenlist[0]
  129.             self.lasttok = tok
  130.             self.tokenlist = self.tokenlist[1:]
  131.             return tok
  132.  
  133.         # Read a new line
  134.         s = self.readLine()
  135.         self.createTokens(s)
  136.         return self.token()
  137.  
  138.     # undoToken
  139.     def undoToken(self):
  140.         """Put back the last token.
  141.         """
  142.         self.tokenlist = [self.lasttok]+self.tokenlist
  143.         self.lasttok = None
  144.  
  145.     # undoLine
  146.     def undoLine(self):
  147.         """Put back the last line.
  148.         """
  149.         self.undoline = self.lastline
  150.         self.lastline = None
  151.         self.tokenlist = []
  152.  
  153.     # skipSection
  154.     def skipSection(self):
  155.         """Read and ignore data until the next section is reached.
  156.  
  157.         The next call of token() will result in a ':' keyword.
  158.         """
  159.         while 1:
  160.             s = self.readLine().strip()
  161.             if s[0]==':':
  162.                 self.createTokens(s)
  163.                 return
  164.         
  165.  
  166.     # readLine
  167.     def readLine(self):
  168.         """Return the next line containing data.
  169.  
  170.         Empty lines and comments are skipped. If the end of the file
  171.         has been reached, a StopIteration exception is thrown.
  172.         The return value is the next line containing data (this will
  173.         never be an empty string).
  174.         """
  175.         # Discard any remaining tokens
  176.         self.tokenlist = []
  177.  
  178.         # Is there a line that was undone?
  179.         if self.undoline!=None:
  180.             self.lastline = self.undoline
  181.             self.undoline = None
  182.             return self.lastline
  183.         
  184.         # Read the next line
  185.         while 1:
  186.             s = self.fhandle.readline()
  187.             self.linenr += 1
  188.             if s=="":
  189.                 raise StopIteration
  190.             if s[0]!="#":
  191.                 self.lastline = s
  192.                 return s
  193.  
  194.     # createTokens
  195.     def createTokens(self, s):
  196.         """Populate the token list from the content of s.
  197.         """
  198.         s = s.strip()
  199.         s = s.replace("(", " ")
  200.         s = s.replace(")", " ")
  201.         s = s.replace(",", " ")
  202.         a = s.split()
  203.         self.tokenlist = a
  204.  
  205. ######################################################################
  206.  
  207. # ASFReader
  208. class ASFReader(ReaderBase):
  209.     """Read Acclaim Skeleton File Definition (ASF) files.
  210.  
  211.     This class serves as base class for reading ASF files.
  212.     Derived classes may implement the following methods:
  213.  
  214.     - onVersion(ver)
  215.     - onName(name)
  216.     - onUnits(units)
  217.     - onDocumentation(doc)
  218.     - onRoot(data)
  219.     - onBonedata(bones)
  220.     - onHierarchy(links)
  221.     """
  222.  
  223.     def __init__(self, filename):
  224.         ReaderBase.__init__(self, filename)
  225.  
  226.     def onVersion(self, ver): pass
  227.     def onName(self, name): pass
  228.     def onUnits(self, units): pass
  229.     def onDocumentation(self, doc): pass
  230.     def onRoot(self, data): pass
  231.     def onBonedata(self, bones): pass
  232.     def onHierarchy(self, links): pass
  233.  
  234.     # readVersion
  235.     def readVersion(self):
  236.         ver = self.floatToken()
  237.         self.onVersion(ver)
  238.  
  239.     # readName
  240.     def readName(self):
  241.         name = self.token()
  242.         self.onName(name)
  243.  
  244.     # readUnits
  245.     def readUnits(self):
  246.         units = {}
  247.         while 1:
  248.             s = self.readLine()
  249.             if s[0]==':':
  250.                 self.undoLine()
  251.                 self.onUnits(units)
  252.                 return
  253.             a = s.strip().split()
  254.             # Get the argument
  255.             if len(a)>1:
  256.                 val = a[1]
  257.             # Try to convert to float. If it doesn't work, use the string value
  258.             try:
  259.                 val = float(val)
  260.             except ValueError:
  261.                 pass
  262.             units[a[0]] = val
  263.  
  264.     # readDocumentation
  265.     def readDocumentation(self):
  266.         lines = []
  267.         while 1:
  268.             s = self.readLine()
  269.             if s[0]==':':
  270.                 self.undoLine()
  271.                 doc = "\n".join(lines)
  272.                 self.onDocumentation(doc)
  273.                 return
  274.             lines += [s[:-1]]
  275.  
  276.     # readRoot
  277.     def readRoot(self):
  278.         data = {}
  279.         while 1:
  280.             s = self.readLine()
  281.             if s[0]==':':
  282.                 self.undoLine()
  283.                 self.onRoot(data)
  284.                 return
  285.             a = s.strip().split()
  286.             val = tuple(a[1:])
  287.             data[a[0]] = val
  288.     
  289.     # readBonedata
  290.     def readBonedata(self):
  291.         bones = []
  292.         while 1:
  293.             stop = False
  294.             try:
  295.                 # Get the next token
  296.                 begintok = self.token()
  297.             except StopIteration:
  298.                 stop = True
  299.  
  300.             # Is it already the begin of the next section?
  301.             if begintok[0]==':':
  302.                 self.undoToken()
  303.                 stop = True
  304.  
  305.             # End of file or next section? -> no more bone data
  306.             if stop:
  307.                 self.onBonedata(bones)
  308.                 return
  309.             
  310.             if begintok!="begin":
  311.                 raise SyntaxError, "Syntax error in line %d: 'begin' expected, got '%s'"%(self.linenr, begintok)
  312.  
  313.             data = {}
  314.  
  315.             while 1:
  316.                 s = self.readLine().strip()
  317.                 if s=='end':
  318.                     break
  319.                 a = s.strip().split()
  320.                 # Check for 'limits' which is a special case as it might
  321.                 # span several lines.
  322.                 if a[0]=="limits":
  323.                     if not data.has_key("dof"):
  324.                         raise ValueError, "Line %d: 'dof' settings must appear before the 'limits' settings"%(self.linenr)
  325.                     dof = data["dof"]
  326.                     # Put back the line and use the token mechanism
  327.                     self.undoLine()
  328.                     # Read the 'limits' token
  329.                     tok = self.token()
  330.                     limits = []
  331.                     for i in range(len(dof)):
  332.                         minval = self.token()
  333.                         maxval = self.token()
  334.                         if minval.lower()!="-inf":
  335.                             try:
  336.                                 minval = float(minval)
  337.                             except ValueError:
  338.                                 raise SyntaxError, "Syntax error in line %d: Float or '-inf' expected, got '%s'"%(self.linenr, minval)
  339.                         if maxval.lower()!="inf":
  340.                             try:
  341.                                 maxval = float(maxval)
  342.                             except ValueError:
  343.                                 raise SyntaxError, "Syntax error in line %d: Float or 'inf' expected, got '%s'"%(self.linenr, maxval)
  344.                         limits.append((minval,maxval))
  345.                     data["limits"] = limits
  346.                 else:
  347.                     val = tuple(a[1:])
  348.                     data[a[0]] = val
  349.  
  350.             bones.append(data)
  351.  
  352.     # readHierarchy
  353.     def readHierarchy(self):
  354.         links = []
  355.         while 1:
  356.             stop = False
  357.             try:
  358.                 # Get the next token
  359.                 begintok = self.token()
  360.             except StopIteration:
  361.                 stop = True
  362.             
  363.             # Is it already the begin of the next section?
  364.             if begintok[0]==':':
  365.                 self.undoToken()
  366.                 stop = True
  367.  
  368.             # End of file or next section? -> no more bone data
  369.             if stop:
  370.                 self.onHierarchy(links)
  371.                 return
  372.  
  373.             if begintok!="begin":
  374.                 raise SyntaxError, "Syntax error in line %d: 'begin' expected, got '%s'"%(self.linenr, begintok)
  375.  
  376.             while 1:
  377.                 s = self.readLine().strip()
  378.                 if s=='end':
  379.                     break
  380.                 a = s.strip().split()
  381.                 links.append((a[0], a[1:]))
  382.  
  383. # AMCReader
  384. class AMCReader(ReaderBase):
  385.     """Read Acclaim Motion Capture Data (AMC) files.
  386.  
  387.     This class serves as base class for reading AMC files.
  388.     Derived classes have to implement the following method:
  389.  
  390.     - onFrame(framenr, data)
  391.  
  392.     """
  393.  
  394.     def __init__(self, filename):
  395.         ReaderBase.__init__(self, filename)
  396.  
  397.     def onFrame(self, framenr, data):
  398.         pass
  399. #        print framenr, data
  400.  
  401.     # read
  402.     def read(self):
  403.         self.fhandle = file(self.filename)
  404.  
  405.         while 1:
  406.             try:
  407.                 tok = self.token()
  408.             except StopIteration:
  409.                 return
  410.  
  411.             # Check if the keyword starts with ':'. If it does, ignore it
  412.             if tok[0]!=":":
  413.                 self.undoToken()
  414.                 break
  415.  
  416.         # Read the motion data...
  417.         while 1:
  418.             try:
  419.                 framenr = self.intToken()
  420.             except StopIteration:
  421.                 return
  422.  
  423.             data = []
  424.             while 1:
  425.                 try:
  426.                     s = self.readLine()
  427.                 except StopIteration:
  428.                     self.onFrame(framenr, data)
  429.                     return
  430.                 
  431.                 a = s.strip().split()
  432.                 # Check if it was a frame number
  433.                 try:
  434.                     int(a[0])
  435.                     self.undoLine()
  436.                     self.onFrame(framenr, data)
  437.                     break
  438.                 except ValueError:
  439.                     pass
  440.                 bone = a[0]
  441.                 values = map(lambda x: float(x), a[1:])
  442.                 data.append((bone, values))
  443.  
  444.  
  445.