import json from .. import util def load_msgpack(blob, **kwargs): """ Load a dict packed with msgpack into kwargs for a Trimesh constructor Parameters ---------- blob : bytes msgpack packed dict containing keys 'vertices' and 'faces' Returns ---------- loaded : dict Keyword args for Trimesh constructor, aka mesh=trimesh.Trimesh(**loaded) """ import msgpack if hasattr(blob, 'read'): data = msgpack.load(blob) else: data = msgpack.loads(blob) loaded = load_dict(data) return loaded def load_dict(data, **kwargs): """ Load multiple input types into kwargs for a Trimesh constructor. Tries to extract keys: 'faces' 'vertices' 'face_normals' 'vertex_normals' Parameters ---------- data: accepts multiple forms -dict: has keys for vertices and faces as (n,3) numpy arrays -dict: has keys for vertices/faces (n,3) arrays encoded as dicts/base64 with trimesh.util.array_to_encoded/trimesh.util.encoded_to_array -str: json blob as dict with either straight array or base64 values -file object: json blob of dict file_type: not used Returns ----------- loaded: dict with keys -vertices: (n,3) float -faces: (n,3) int -face_normals: (n,3) float (optional) """ if data is None: raise ValueError('data passed to load_dict was None!') if util.is_instance_named(data, 'Trimesh'): return data if util.is_string(data): if '{' not in data: raise ValueError('Object is not a JSON encoded dictionary!') data = json.loads(data.decode('utf-8')) elif util.is_file(data): data = json.load(data) # what shape should the data be to be usable mesh_data = {'vertices': (-1, 3), 'faces': (-1, (3, 4)), 'face_normals': (-1, 3), 'face_colors': (-1, (3, 4)), 'vertex_normals': (-1, 3), 'vertex_colors': (-1, (3, 4))} # now go through data structure and if anything is encoded as base64 # pull it back into numpy arrays if isinstance(data, dict): loaded = {} data = util.decode_keys(data, 'utf-8') for key, shape in mesh_data.items(): if key in data: loaded[key] = util.encoded_to_array(data[key]) if not util.is_shape(loaded[key], shape): raise ValueError('Shape of %s is %s, not %s!', key, str(loaded[key].shape), str(shape)) if len(key) == 0: raise ValueError('Unable to extract any mesh data!') return loaded else: raise ValueError('%s object passed to dict loader!', data.__class__.__name__) def load_meshio(file_obj, file_type=None, **kwargs): """ Load a meshio-supported file into the kwargs for a Trimesh constructor. Parameters ---------- file_obj : file object Contains a meshio file file_type : str File extension, aka 'vtk' Returns ---------- loaded : dict kwargs for Trimesh constructor """ # trimesh "file types" are really filename extensions file_format = meshio.extension_to_filetype["." + file_type] # load_meshio gets passed and io.BufferedReader # not all readers can cope with that # e.g., the ones that use h5m underneath # in that case use the associated file name instead mesh = meshio.read(file_obj.name, file_format=file_format) # save data as kwargs for a trimesh.Trimesh result = {} # pass kwargs to mesh constructor result.update(kwargs) # add vertices result['vertices'] = mesh.points try: # add faces result['faces'] = mesh.get_cells_type("triangle") except BaseException: util.log.warning('unable to get faces', exc_info=True) result['faces'] = [] return result _misc_loaders = {'dict': load_dict, 'dict64': load_dict, 'json': load_dict, 'msgpack': load_msgpack} try: import meshio # add meshio loaders here _misc_loaders.update( {k[1:]: load_meshio for k in meshio.extension_to_filetype.keys()}) except BaseException: pass