<s> """<STR_LIT>""" <EOL> import numpy as np <EOL> import time <EOL> from os import path as op <EOL> from . . ext . gzip_open import gzip_open <EOL> from . . geometry import _calculate_normals <EOL> from . . util import logger <EOL> class WavefrontReader ( object ) : <EOL> def __init__ ( self , f ) : <EOL> self . _f = f <EOL> self . _v = [ ] <EOL> self . _vn = [ ] <EOL> self . _vt = [ ] <EOL> self . _vertices = [ ] <EOL> self . _normals = [ ] <EOL> self . _texcords = [ ] <EOL> self . _faces = [ ] <EOL> self . _facemap = { } <EOL> @ classmethod <EOL> def read ( cls , fname ) : <EOL> """<STR_LIT>""" <EOL> fmt = op . splitext ( fname ) [ <NUM_LIT:1> ] . lower ( ) <EOL> assert fmt in ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> opener = open if fmt == '<STR_LIT>' else gzip_open <EOL> with opener ( fname , '<STR_LIT:rb>' ) as f : <EOL> try : <EOL> reader = WavefrontReader ( f ) <EOL> while True : <EOL> reader . readLine ( ) <EOL> except EOFError : <EOL> pass <EOL> t0 = time . time ( ) <EOL> mesh = reader . finish ( ) <EOL> logger . debug ( '<STR_LIT>' + str ( time . time ( ) - t0 ) + '<STR_LIT>' ) <EOL> return mesh <EOL> def readLine ( self ) : <EOL> """<STR_LIT>""" <EOL> line = self . _f . readline ( ) . decode ( '<STR_LIT:ascii>' , '<STR_LIT:ignore>' ) <EOL> if not line : <EOL> raise EOFError ( ) <EOL> line = line . strip ( ) <EOL> if line . startswith ( '<STR_LIT>' ) : <EOL> self . _v . append ( self . readTuple ( line ) ) <EOL> elif line . startswith ( '<STR_LIT>' ) : <EOL> self . _vt . append ( self . readTuple ( line , <NUM_LIT:3> ) ) <EOL> elif line . startswith ( '<STR_LIT>' ) : <EOL> self . _vn . append ( self . readTuple ( line ) ) <EOL> elif line . startswith ( '<STR_LIT>' ) : <EOL> self . _faces . append ( self . readFace ( line ) ) <EOL> elif line . startswith ( '<STR_LIT:#>' ) : <EOL> pass <EOL> elif line . startswith ( '<STR_LIT>' ) : <EOL> logger . warning ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> elif any ( line . startswith ( x ) for x in ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) ) : <EOL> pass <EOL> elif not line . strip ( ) : <EOL> pass <EOL> else : <EOL> logger . warning ( '<STR_LIT>' <EOL> % line . strip ( ) ) <EOL> def readTuple ( self , line , n = <NUM_LIT:3> ) : <EOL> """<STR_LIT>""" <EOL> numbers = [ num for num in line . split ( '<STR_LIT:U+0020>' ) if num ] <EOL> return [ float ( num ) for num in numbers [ <NUM_LIT:1> : n + <NUM_LIT:1> ] ] <EOL> def readFace ( self , line ) : <EOL> """<STR_LIT>""" <EOL> indexSets = [ num for num in line . split ( '<STR_LIT:U+0020>' ) if num ] [ <NUM_LIT:1> : ] <EOL> final_face = [ ] <EOL> for indexSet in indexSets : <EOL> final_index = self . _facemap . get ( indexSet ) <EOL> if final_index is not None : <EOL> final_face . append ( final_index ) <EOL> continue <EOL> final_index = len ( self . _vertices ) <EOL> final_face . append ( final_index ) <EOL> self . _facemap [ indexSet ] = final_index <EOL> indices = [ i for i in indexSet . split ( '<STR_LIT:/>' ) ] <EOL> if True : <EOL> vertex_index = self . _absint ( indices [ <NUM_LIT:0> ] , len ( self . _v ) ) <EOL> self . _vertices . append ( self . _v [ vertex_index ] ) <EOL> if self . _texcords is not None : <EOL> if len ( indices ) > <NUM_LIT:1> and indices [ <NUM_LIT:1> ] : <EOL> texcord_index = self . _absint ( indices [ <NUM_LIT:1> ] , len ( self . _vt ) ) <EOL> self . _texcords . append ( self . _vt [ texcord_index ] ) <EOL> else : <EOL> if self . _texcords : <EOL> logger . warning ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> self . _texcords = None <EOL> if self . _normals is not None : <EOL> if len ( indices ) > <NUM_LIT:2> and indices [ <NUM_LIT:2> ] : <EOL> normal_index = self . _absint ( indices [ <NUM_LIT:2> ] , len ( self . _vn ) ) <EOL> self . _normals . append ( self . _vn [ normal_index ] ) <EOL> else : <EOL> if self . _normals : <EOL> logger . warning ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> self . _normals = None <EOL> if self . _faces and len ( self . _faces [ <NUM_LIT:0> ] ) != len ( final_face ) : <EOL> raise RuntimeError ( <EOL> '<STR_LIT>' ) <EOL> return final_face <EOL> def _absint ( self , i , ref ) : <EOL> i = int ( i ) <EOL> if i > <NUM_LIT:0> : <EOL> return i - <NUM_LIT:1> <EOL> else : <EOL> return ref + i <EOL> def _calculate_normals ( self ) : <EOL> vertices , faces = self . _vertices , self . _faces <EOL> if faces is None : <EOL> faces = np . arange ( <NUM_LIT:0> , vertices . size , dtype = np . uint32 ) [ : , np . newaxis ] <EOL> normals = _calculate_normals ( vertices , faces ) <EOL> return normals <EOL> def finish ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _vertices = np . array ( self . _vertices , '<STR_LIT>' ) <EOL> if self . _faces : <EOL> self . _faces = np . array ( self . _faces , '<STR_LIT>' ) <EOL> else : <EOL> self . _vertices = np . array ( self . _v , '<STR_LIT>' ) <EOL> self . _faces = None <EOL> if self . _normals : <EOL> self . _normals = np . array ( self . _normals , '<STR_LIT>' ) <EOL> else : <EOL> self . _normals = self . _calculate_normals ( ) <EOL> if self . _texcords : <EOL> self . _texcords = np . array ( self . _texcords , '<STR_LIT>' ) <EOL> else : <EOL> self . _texcords = None <EOL> return self . _vertices , self . _faces , self . _normals , self . _texcords <EOL> class WavefrontWriter ( object ) : <EOL> def __init__ ( self , f ) : <EOL> self . _f = f <EOL> @ classmethod <EOL> def write ( cls , fname , vertices , faces , normals , texcoords , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> fmt = op . splitext ( fname ) [ <NUM_LIT:1> ] . lower ( ) <EOL> if fmt not in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> raise ValueError ( '<STR_LIT>' <EOL> % ( fmt , ) ) <EOL> opener = open if fmt == '<STR_LIT>' else gzip_open <EOL> f = opener ( fname , '<STR_LIT:wb>' ) <EOL> try : <EOL> writer = WavefrontWriter ( f ) <EOL> writer . writeMesh ( vertices , faces , normals , texcoords , name ) <EOL> except EOFError : <EOL> pass <EOL> finally : <EOL> f . close ( ) <EOL> def writeLine ( self , text ) : <EOL> """<STR_LIT>""" <EOL> text += '<STR_LIT:\n>' <EOL> self . _f . write ( text . encode ( '<STR_LIT:ascii>' ) ) <EOL> def writeTuple ( self , val , what ) : <EOL> """<STR_LIT>""" <EOL> val = val [ : <NUM_LIT:3> ] <EOL> val = '<STR_LIT:U+0020>' . join ( [ str ( v ) for v in val ] ) <EOL> self . writeLine ( '<STR_LIT>' % ( what , val ) ) <EOL> def writeFace ( self , val , what = '<STR_LIT:f>' ) : <EOL> """<STR_LIT>""" <EOL> val = [ v + <NUM_LIT:1> for v in val ] <EOL> if self . _hasValues and self . _hasNormals : <EOL> val = '<STR_LIT:U+0020>' . join ( [ '<STR_LIT>' % ( v , v , v ) for v in val ] ) <EOL> elif self . _hasNormals : <EOL> val = '<STR_LIT:U+0020>' . join ( [ '<STR_LIT>' % ( v , v ) for v in val ] ) <EOL> elif self . _hasValues : <EOL> val = '<STR_LIT:U+0020>' . join ( [ '<STR_LIT>' % ( v , v ) for v in val ] ) <EOL> else : <EOL> val = '<STR_LIT:U+0020>' . join ( [ '<STR_LIT>' % v for v in val ] ) <EOL> self . writeLine ( '<STR_LIT>' % ( what , val ) ) <EOL> def writeMesh ( self , vertices , faces , normals , values , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> self . _hasNormals = normals is not None <EOL> self . _hasValues = values is not None <EOL> self . _hasFaces = faces is not None <EOL> if faces is None : <EOL> faces = np . arange ( len ( vertices ) ) <EOL> Nfaces = faces . size // <NUM_LIT:3> <EOL> faces = faces . reshape ( ( Nfaces , <NUM_LIT:3> ) ) <EOL> N = vertices . shape [ <NUM_LIT:0> ] <EOL> stats = [ ] <EOL> stats . append ( '<STR_LIT>' % N ) <EOL> if self . _hasValues : <EOL> stats . append ( '<STR_LIT>' % N ) <EOL> else : <EOL> stats . append ( '<STR_LIT>' ) <EOL> if self . _hasNormals : <EOL> stats . append ( '<STR_LIT>' % N ) <EOL> else : <EOL> stats . append ( '<STR_LIT>' ) <EOL> stats . append ( '<STR_LIT>' % faces . shape [ <NUM_LIT:0> ] ) <EOL> self . writeLine ( '<STR_LIT>' ) <EOL> self . writeLine ( '<STR_LIT>' ) <EOL> self . writeLine ( '<STR_LIT:#>' ) <EOL> if name : <EOL> self . writeLine ( '<STR_LIT>' % name ) <EOL> else : <EOL> self . writeLine ( '<STR_LIT>' ) <EOL> self . writeLine ( '<STR_LIT>' % '<STR_LIT:U+002CU+0020>' . join ( stats ) ) <EOL> self . writeLine ( '<STR_LIT>' ) <EOL> if True : <EOL> for i in range ( N ) : <EOL> self . writeTuple ( vertices [ i ] , '<STR_LIT:v>' ) <EOL> if self . _hasNormals : <EOL> for i in range ( N ) : <EOL> self . writeTuple ( normals [ i ] , '<STR_LIT>' ) <EOL> if self . _hasValues : <EOL> for i in range ( N ) : <EOL> self . writeTuple ( values [ i ] , '<STR_LIT>' ) <EOL> if True : <EOL> for i in range ( faces . shape [ <NUM_LIT:0> ] ) : <EOL> self . writeFace ( faces [ i ] ) </s>
