Skip to content

Commit

Permalink
load face-free PLY files
Browse files Browse the repository at this point in the history
  • Loading branch information
mikedh committed Nov 3, 2018
1 parent eb8a286 commit b51069f
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 29 deletions.
7 changes: 7 additions & 0 deletions trimesh/io/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .. import util

from ..base import Trimesh
from ..points import PointCloud
from ..scene.scene import Scene, append_scenes
from ..constants import _log_time, log

Expand Down Expand Up @@ -331,9 +332,15 @@ def handle_scene():
return scene

def handle_trimesh_kwargs():
"""
Load information with vertices and faces into a mesh
or PointCloud object.
"""
if (isinstance(kwargs['vertices'], dict) or
isinstance(kwargs['faces'], dict)):
return Trimesh(**misc.load_dict(kwargs))
elif kwargs['faces'] is None:
return PointCloud(**kwargs)
else:
return Trimesh(**kwargs)

Expand Down
58 changes: 35 additions & 23 deletions trimesh/io/ply.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ def load_ply(file_obj, *args, **kwargs):
Returns
---------
mesh_kwargs : dictionary of mesh info which can be passed to
Trimesh constructor, eg: a = Trimesh(**mesh_kwargs)
mesh_kwargs : dict
Data which can be passed to
Trimesh constructor, eg: a = Trimesh(**mesh_kwargs)
"""

# OrderedDict which is populated from the header
Expand Down Expand Up @@ -237,13 +238,22 @@ def elements_to_kwargs(elements):
kwargs: dict, with keys for Trimesh constructor.
eg: mesh = trimesh.Trimesh(**kwargs)
"""
vertices = np.column_stack([elements['vertex']['data'][i] for i in 'xyz'])
vertices = np.column_stack([elements['vertex']['data'][i]
for i in 'xyz'])
if not util.is_shape(vertices, (-1, 3)):
raise ValueError('Vertices were not (n,3)!')

try:
face_data = elements['face']['data']
except KeyError:
# some PLY files only include vertices
face_data = None
faces = None

# what keys do in-the-wild exporters use for vertices
index_names = ['vertex_index',
'vertex_indices']
face_data = elements['face']['data']

if util.is_shape(face_data, (-1, (3, 4))):
faces = face_data
elif isinstance(face_data, dict):
Expand All @@ -254,8 +264,8 @@ def elements_to_kwargs(elements):
elif isinstance(face_data, np.ndarray):
blob = elements['face']['data']
# some exporters set this name to 'vertex_index'
# and some others use 'vertex_indices', but we really
# don't care about the name unless there are multiple properties
# and some others use 'vertex_indices' but we really
# don't care about the name unless there are multiple
if len(blob.dtype.names) == 1:
name = blob.dtype.names[0]
elif len(blob.dtype.names) > 1:
Expand All @@ -264,33 +274,35 @@ def elements_to_kwargs(elements):
name = i
break
faces = elements['face']['data'][name]['f1']
else:
raise ValueError('Couldn\'t extract face data!')

if not util.is_shape(faces, (-1, (3, 4))):
raise ValueError('Faces weren\'t (n,(3|4))!')

result = {'vertices': vertices,
'faces': faces,
# kwargs for Trimesh or PointCloud
result = {'faces': faces,
'vertices': vertices,
'ply_data': elements}

# if both vertex and face color are defined, pick the one
# if both vertex and face color are defined pick the one
# with the most going on
f_color, f_signal = element_colors(elements['face'])
v_color, v_signal = element_colors(elements['vertex'])
colors = [{'face_colors': f_color},
{'vertex_colors': v_color}]
colors_index = np.argmax([f_signal,
v_signal])
result.update(colors[colors_index])
colors = []
signal = []
if result['faces'] is not None:
f_color, f_signal = element_colors(elements['face'])
colors.append({'face_colors': f_color})
signal.append(f_signal)
if result['vertices'] is not None:
v_color, v_signal = element_colors(elements['vertex'])
colors.append({'vertex_colors': v_color})
signal.append(v_signal)

# add the winning colors to the result
result.update(colors[np.argmax(signal)])

return result


def element_colors(element):
"""
Given an element, try to extract RGBA color from its properties
and return them as an (n,3|4) array.
Given an element, try to extract RGBA color from
properties and return them as an (n,3|4) array.
Parameters
-------------
Expand Down
20 changes: 15 additions & 5 deletions trimesh/ray/ray_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ def contains_points(intersector,
(inside_aabb.sum(), 1))
else:
# if a direction is passed use it
ray_directions = np.tile(np.array(check_direction).reshape(3),
(inside_aabb.sum(), 1))
ray_directions = np.tile(
np.array(check_direction).reshape(3),
(inside_aabb.sum(), 1))

# cast a ray both forwards and backwards
location, index_ray, c = intersector.intersects_location(
Expand Down Expand Up @@ -116,11 +117,20 @@ def contains_points(intersector,

# run a contains check again on the broken points with a
# new random direction but only once and assign it to our results
contains[mask] = contains_points(intersector,
points[inside_aabb][broken],
check_direction=new_direction)
contains[mask] = contains_points(
intersector,
points[inside_aabb][broken],
check_direction=new_direction)

constants.log.debug(
'detected %d broken contains test, attempted to fix',
broken.sum())

# we had unrecoverable points
if broken.any() and check_direction is not None:
constants.log.error(
'ray contains tests had %d unrecoverable!' +
'try loading mesh with use_embree=False!',
broken.sum())

return contains
2 changes: 1 addition & 1 deletion trimesh/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '2.35.17'
__version__ = '2.35.18'

0 comments on commit b51069f

Please sign in to comment.