hub/venv/lib/python3.7/site-packages/trimesh/exchange/misc.py

154 lines
4.4 KiB
Python

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