Section_multiplane issues, fully captured by an example
See original GitHub issueI have tried to define the issue a little better based on the example you included here: https://github.com/mikedh/trimesh/issues/688#issuecomment-572833398_
Here is a slight modification to your example:
import trimesh
import numpy as np
if __name__ == '__main__':
m = trimesh.creation.box()
sx = m.section_multiplane(plane_origin=[-0.5,0,0],
plane_normal=[1,0,0],
heights=np.linspace(0.0, 1.0, 10))
sy = m.section_multiplane(plane_origin=[0,-0.5,0],
plane_normal=[0,1,0],
heights=np.linspace(0.0, 1.0, 10))
sz = m.section_multiplane(plane_origin=[0,0,-0.5],
plane_normal=[0,0,1],
heights=np.linspace(0.0, 1.0, 10))
sr = [m.section(plane_origin=[0,0,-0.5 +h],
plane_normal=[0,0,1])
for h in np.linspace(0.0, 1.0, 10.0)]
If you check for the transforms to 3D on sz, sy, and sx, you see that they do not all correspond to what they should.
sx[0].metadata['to_3D']
sy[0].metadata['to_3D']
sz[0].metadata['to_3D']
the sz transform is as expected, but the sx and sy transforms have -1s in there that probably explain the axis inversion behavior I was witnessing. Example for sx:
array([[ 0. , 0. , 1. , -0.5],
[ 0. , 1. , 0. , 0. ],
[-1. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 1. ]])
Then, if you use m.bounds[0] for the plane origin, section_multiplane will produce a None result for sections up until the positive quadrant, in addition to the inverted axis behavior. The section method does not have this behavior.
import trimesh
import numpy as np
if __name__ == '__main__':
#trimesh.util.attach_to_log()
m = trimesh.creation.box()
#T = [[1,0,0,-m.bounds[0,0]],[0,1,0,-m.bounds[0,1]],[0,0,1,-m.bounds[0,2]],[0,0,0,1]]
#m.vertices = trimesh.transform_points(m.vertices,T,translate=True)
def mesh_sections(mesh,axis,step):
plane_normal = [0,0,0]
plane_normal[axis] = 1
plane_origin = mesh.bounds[0]
extents = [mesh.bounds[0,axis],mesh.bounds[1,axis]]
levels = np.arange(*extents, step=step)
sections = mesh.section_multiplane(plane_origin=plane_origin,plane_normal=plane_normal,heights=levels)
return sections, levels
mx_sections, mx_levels = mesh_sections(m,0,.1)
my_sections, my_levels = mesh_sections(m,1,.1)
mz_sections, mz_levels = mesh_sections(m,2,.1)
srx = [m.section(plane_origin=m.bounds[0],
plane_normal=[1,0,0])
for h in np.arange(m.bounds[0,0],m.bounds[1,0],.1)]
sry = [m.section(plane_origin=m.bounds[0],
plane_normal=[0,1,0])
for h in np.arange(m.bounds[0,1],m.bounds[1,1],.1)]
srz = [m.section(plane_origin=m.bounds[0],
plane_normal=[0,0,1])
for h in np.arange(m.bounds[0,2],m.bounds[1,2],.1)]
the results for mx_sections:
[None,
None,
None,
None,
None,
<trimesh.path.path.Path2D at 0x1d2534926c8>,
<trimesh.path.path.Path2D at 0x1d2531aea48>,
<trimesh.path.path.Path2D at 0x1d2531ae288>,
<trimesh.path.path.Path2D at 0x1d2534c79c8>,
<trimesh.path.path.Path2D at 0x1d2534c7888>]
vs the results for srx:
[<trimesh.path.path.Path3D at 0x1d2534c70c8>,
<trimesh.path.path.Path3D at 0x1d2531aca88>,
<trimesh.path.path.Path3D at 0x1d2531ac1c8>,
<trimesh.path.path.Path3D at 0x1d2531ace88>,
<trimesh.path.path.Path3D at 0x1d2531ac648>,
<trimesh.path.path.Path3D at 0x1d2531ac888>,
<trimesh.path.path.Path3D at 0x1d2531a9388>,
<trimesh.path.path.Path3D at 0x1d2531a9288>,
<trimesh.path.path.Path3D at 0x1d2531a92c8>,
<trimesh.path.path.Path3D at 0x1d2534c7088>]
I hope this helps clarify what the problems are with section_multiplane; I’m pretty sure they are there but I don’t know what specifically is going on.
Issue Analytics
- State:
- Created 4 years ago
- Comments:13 (2 by maintainers)
Top GitHub Comments
Thanks for looking in to this in depth @pmberkeley! Hahah I’m gonna use “There ISN’T an issue with the code, it’s just really, really confusing and under-explained about what it’s giving you” as a product testimonial if we ever make trimesh t-shirts 😆
Section_multiplane uses the origin as the start of the heights. So if your object goes from -5 to 5 on the x axis, you would set an origin at x=-5 (say, [-5,0,0], or whatever the lower bounds are), a normal of normal = [1,0,0], and then the heights array would be measured from that origin, NOT an array of the locations of the new origins. A heights array of heights = [0,2,4,6,8,10] would capture sections at [-5,-3,-1,1,3,5].
Then, the output of the section_multiplane will be 2D paths that have been rotated into the XY plane using the transformation matrices that are output by mesh_multiplane and cached. In order to get the section multiplane back into 3D space (from which you can get a projection onto some other plane, like the YZ plane, if that’s what you want like I did), you have to use the to_3D method on each 2D section output by the section_multiplane method. If you don’t put a specific transform into the method, it will pull the cached transforms to put it back in the original location. (@mikedh, is there some direct way to do this, or do you have to run the output of the section_multiplane method through a for loop like I did?)
This is my heights generator helper function; it’s crude - it only works for major axis directions and it doesn’t have an option for selecting n number of steps instead of setting step size. However, it should clarify which heights to choose for the methods to work.