import re import numpy as np from .. import util def load_off(file_obj, **kwargs): """ Load an OFF file into the kwargs for a Trimesh constructor Parameters ---------- file_obj : file object Contains an OFF file Returns ---------- loaded : dict kwargs for Trimesh constructor """ text = file_obj.read() # will magically survive weird encoding sometimes # comment strip will handle all cases of commenting text = util.comment_strip( util.decode_text(text)).strip() # split the first key _, header, raw = re.split('(COFF|OFF)', text, 1) if header.upper() not in ['OFF', 'COFF']: raise NameError( 'Not an OFF file! Header was: `{}`'.format(header)) # split into lines and remove whitespace splits = [i.strip() for i in str.splitlines(str(raw))] # remove empty lines splits = [i for i in splits if len(i) > 0] # the first non-comment line should be the counts header = np.array(splits[0].split(), dtype=np.int64) vertex_count, face_count = header[:2] vertices = np.array([ i.split()[:3] for i in splits[1: vertex_count + 1]], dtype=np.float64) # will fail if incorrect number of vertices loaded vertices = vertices.reshape((vertex_count, 3)) # get lines with face data faces = [i.split() for i in splits[vertex_count + 1:vertex_count + face_count + 1]] # the first value is count faces = [line[1:int(line[0]) + 1] for line in faces] # convert faces to numpy array # will fail on mixed garbage as FSM intended -_- faces = np.array(faces, dtype=np.int64) # save data as kwargs for a trimesh.Trimesh kwargs = {'vertices': vertices, 'faces': faces} return kwargs def export_off(mesh, digits=10): """ Export a mesh as an OFF file, a simple text format Parameters ----------- mesh : trimesh.Trimesh Geometry to export digits : int Number of digits to include on floats Returns ----------- export : str OFF format output """ # make sure specified digits is an int digits = int(digits) # prepend a 3 (face count) to each face faces_stacked = np.column_stack((np.ones(len(mesh.faces)) * 3, mesh.faces)).astype(np.int64) export = 'OFF\n' # the header is vertex count, face count, another number export += str(len(mesh.vertices)) + ' ' + str(len(mesh.faces)) + ' 0\n' export += util.array_to_string( mesh.vertices, col_delim=' ', row_delim='\n', digits=digits) + '\n' export += util.array_to_string( faces_stacked, col_delim=' ', row_delim='\n') return export _off_loaders = {'off': load_off} _off_exporters = {'off': export_off}