pyvista / pyvista-support

[moved] Please head over to the Discussions tab of the PyVista repository
https://github.com/pyvista/pyvista/discussions
60 stars 4 forks source link

Get image depth when camera parallel projection enabled #328

Closed 109021017 closed 3 years ago

109021017 commented 3 years ago

image depth value not as expected when parallel projection enabled.

mesh = examples.load_random_hills()
bounds = np.array(mesh.bounds).reshape([3, 2])
print('z range:', bounds[2])

p = pv.Plotter()
p.enable_parallel_projection()
actor = p.add_mesh(mesh)
print('cpos:', p.show(cpos='xy')[0])
zval = p.get_image_depth()
print('depth range: ', np.min(zval[np.invert(np.isnan(zval))]), np.max(zval[np.invert(np.isnan(zval))]))

output:

z range: [0.14158222 7.4830904 ]
cpos: (0.0, 9.99999977567765, 60.26399550614782)
depth range:  -2.7123802 -2.6565497

output exepcted:

z range: [0.14158222 7.4830904 ]
cpos: (0.0, 9.99999977567765, 60.26399550614782)
depth range:  -60.122413306 -55.780905106
banesullivan commented 3 years ago

Depth mapping is invalid with a parallel projection. You won't be able to get meaningful results doing this as the image is the same regardless of the camera's distance away from the mesh... a feature of parallel projection.

See also: https://github.com/pyvista/pyvista-support/issues/207#issuecomment-658499093

109021017 commented 3 years ago

I want to get heightest z value of every x, y sample point in certain sample resolution. Currently I project_points_to_plane then use the smaple function to implement this. But it has trouble getting values when the cells overlap to each other as the image showing below.

Is there a better way in order to doing so?

here's my code:

def height_map(mesh, resolution=0.1):
    mesh = mesh.elevation()
    bounds = np.array(mesh.bounds).reshape([3, 2])
    center = (bounds[:, 0] + bounds[:, 1])/2
    center[2] = 0
    mesh = mesh.project_points_to_plane(center)
    x = np.arange(bounds[0, 0], bounds[0, 1], resolution)
    y = np.arange(bounds[1, 0], bounds[1, 1], resolution)
    z = np.array([0])
    x, y, z = np.meshgrid(x, y, z)
    points = np.stack([x, y, z], axis=3)
    points = points.reshape([-1, 3])
    points = pv.PolyData(points)
    points = points.sample(mesh)
    height_map = points.point_arrays['Elevation'].reshape([x.shape[0], x.shape[1]])
    return height_map
if __name__ == '__main__':
    mesh = pv.Sphere(20, (0, 0, 10))
    mesh = extract_visible_cells(mesh)
    hm = height_map(mesh)
    plt.figure()
    plt.imshow(hm)
    plt.show()

Result:

result
banesullivan commented 3 years ago

Is there a better way in order to doing so?

I think what you are doing here is more or less the way to go.

Apologies for the slow response, I am trying to go through and resolve stale issues.

This issue seems to have gone off topic, please open a new issue for further help