Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Claims point is in mesh when it's clearly not #3

Open
clbarnes opened this issue May 19, 2020 · 5 comments
Open

Claims point is in mesh when it's clearly not #3

clbarnes opened this issue May 19, 2020 · 5 comments
Labels

Comments

@clbarnes
Copy link
Owner

Point: [28355.6, 51807.3, 47050]

SEZ_right.stl.zip

Jittering the point by a tiny amount generally bumps it "out" of the mesh (that it isn't in). The mesh is contiguous, and valid according to trimesh.

@clbarnes
Copy link
Owner Author

clbarnes commented Jun 1, 2020

Due to dimforge/ncollide#335

ncollpyde now has rust tests for this (currently ignored), and has mitigated the issue by firing multiple rays. Leaving open for informational purposes. The original example is no longer valid due to the way rays are generated now.

@clbarnes clbarnes added the info label Jun 1, 2020
@schlegelp
Copy link

Hi Chris. Someone recently reported some strange, possibly related behaviour when trying to use ncollpyde via navis in a voxelisation workflow:

import trimesh as tm 
import numpy as np
import pandas as pd

import navis

# Load mesh 
layer_mesh = navis.Volume.from_file('LO_layer_7.obj')

# Minimal smoothing
trimesh.smoothing.filter_humphrey(layer_mesh)

# Some clean-up just in case 
layer_mesh.fix_normals()
layer_mesh.remove_degenerate_faces()
layer_mesh.remove_unreferenced_vertices()

# Generate points on a grid
scale = 6
samp = 2**scale
xm = 0.9*layer_mesh.vertices[:,0].min()
ym = 0.9*layer_mesh.vertices[:,1].min()
zm = 0.9*layer_mesh.vertices[:,2].min()
xM = 1.1*layer_mesh.vertices[:,0].max()
yM = 1.1*layer_mesh.vertices[:,1].max()
zM = 1.1*layer_mesh.vertices[:,2].max()
zv, yv, xv = np.meshgrid(np.arange(np.floor(zm/samp)*samp, (np.ceil(zM/samp)+1)*samp, samp),\
                         np.arange(np.floor(ym/samp)*samp, (np.ceil(yM/samp)+1)*samp, samp), \
                         np.arange(np.floor(xm/samp)*samp, (np.ceil(xM/samp)+1)*samp, samp), indexing='ij')
roi_xyz = np.concatenate((xv.reshape((-1,1)), yv.reshape((-1,1)), zv.reshape((-1,1))),axis=1)
roi_df = pd.DataFrame(roi_xyz, columns=['x','y','z'] )

# Check which of the points are inside the mesh
# Note I'm using more rays than normal 
roi_df['in_vol'] = navis.in_volume(roi_df, layer_mesh, n_rays=20)
roi_chop_df = roi_df[roi_df.in_vol]

# Plot a corner of the points
navis.plot3d([roi_chop_df.loc[(roi_chop_df2.y < 23_000) & (roi_chop_df.x > 28_000),
                              ['x', 'y', 'z']].values,
              layer_mesh],
             scatter_kws=dict(color='r', opacity=.2))

Screenshot 2023-03-17 at 20 04 39

As you can see there are these odd grooves in the points cloud that seem emanate from certain mesh edges.

Oddly, if I use n_rays=1 this goes away (at least in this part of the point cloud):

Screenshot 2023-03-17 at 20 07 13

Any ideas?

lo_layer_7.obj.zip

@clbarnes
Copy link
Owner Author

It makes sense for the problem to get worse as more rays are added - in order for a point to return that it is contained in a mesh, all rays must hit the inside of the mesh

.all(|v| mesh_contains_point_ray(mesh, point, v))
. So, the more rays, the more likely that one will erroneously fail to do so. I implemented it this way in order to short circuit when the first ray misses, but I suspect that this optimisation doesn't do much for most users. Instead, we could take the majority view of an odd number of rays; might be more robust.

@clbarnes
Copy link
Owner Author

clbarnes commented Mar 17, 2023

I've pushed a branch with that change (unfortunately a lot of cruft relating to build stuff in there so the diff isn't very clean). If your user has a rust compiler, they should be able to install the branch with

pip install -U git+https://github.com/clbarnes/ncollpyde.git@ray-consensus

In future the consensus level could be tweaked (currently >0.5 with a warning if you use an even number of rays).

@schlegelp
Copy link

Thanks for the quick turnaround! The consensus approach sounds great! I recommended the user to use trimeshs voxelisation instead anyway - so no pressure on that end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants