Open nidu opened 4 years ago
Hi and welcome! Thanks for posting your first issue in the PyVista project! Someone from @pyvista/developers will chime in before too long. If your question is support related, it may be automatically transferred to https://github.com/pyvista/pyvista-support
The array cannot be maintained/passed through the decimate
filter as the topology of the mesh is dramatically altered in this filter. We also will not add this feature as it is important for the user to realize how drastically the decimate filter affects their mesh.
In the case where you might have custom data arrays that you'd like to preserve them across this filter, you'll have to do something like resampling via the sample
or interpolate
filters which are seeing a big change in https://github.com/pyvista/pyvista/pull/842
Here is an example where we really demonstrate how the original mesh can change and thus any field calculated on the original mesh wouldn't be valid on the decimated mesh:
import pyvista as pv
from pyvista import examples
import numpy as np
mesh = examples.download_face()
# compute some data based on the mesh
qual = mesh.compute_cell_quality()
# decimate and recompute the data on the new mesh
target_reduction = 0.7
decimated = qual.decimate(target_reduction).compute_cell_quality()
# Define a camera potion the shows this mesh properly
cpos = [(0.4, -0.07, -0.31), (0.05, -0.13, -0.06), (-0.1, 1, 0.08)]
dargs = dict(show_edges=True, scalars='CellQuality')
# Compare the two fields and note that an interpolation wouldn't work in this case
p = pv.Plotter(shape=(1,2))
p.add_mesh(qual, **dargs)
p.subplot(0,1)
p.add_mesh(decimated, **dargs)
p.link_views()
p.show(cpos=cpos)
If you really want to do this and don't care about the loss of integrity in your data due to the underlying mesh drastically changing, then using the sample
filter to resample the values onto the new mesh is an option (but it's not great):
mesh['lost_integrity'] = np.arange(mesh.n_points)
decimated_2 = mesh.decimate(target_reduction).sample(mesh, tolerance=0.5)
dargs = dict(show_edges=True, scalars='lost_integrity')
p = pv.Plotter(shape=(1,2))
p.add_mesh(mesh, **dargs)
p.subplot(0,1)
p.add_mesh(decimated_2, **dargs)
p.link_views()
p.show(cpos=cpos)
Coming soon, the interpolate
filter will have much better performance. Using the changes in https://github.com/pyvista/pyvista/pull/842, the interpolate
filter under a nearest neighbor approach yields:
decimated_3 = mesh.decimate(target_reduction).interpolate(mesh, n_points=2)
dargs = dict(show_edges=True, scalars='lost_integrity')
p = pv.Plotter(shape=(1,2))
p.add_mesh(mesh, **dargs)
p.subplot(0,1)
p.add_mesh(decimated_3, **dargs)
p.link_views()
p.show(cpos=cpos)
(note, you straight up can't do this with the current implementation of the interpolate
filter and must use the new changes on the mentioned pull request)
And here is a flashier example to showcase how the new version of the interpolate filter is the bees knees 🐝
import pyvista as pv
from pyvista import examples
mesh = examples.download_st_helens().warp_by_scalar().extract_surface()
topo = mesh.triangulate().decimate(0.9).interpolate(mesh, radius=100, sharpness=10)
cpos = [(567803.5412067451, 5121265.750198333, 6779.117176048584),
(563141.9539970291, 5116029.941437181, 1497.1660619987454),
(-0.4346960441575112, -0.4178048067210862, 0.7977960219721372)]
# Using a colorcet colormap, be sure to pip install colorcet
dargs = dict(scalars='Elevation', cmap='fire',
show_edges=True, line_width=1)
p = pv.Plotter(shape=(1,2), multi_samples=8,
window_size=[1024*3, int(768*1.5)])
p.add_mesh(mesh, **dargs)
p.subplot(0,1)
p.add_mesh(topo, **dargs)
p.link_views()
p.show(cpos=cpos)
Thanks for a great explanation!
New interpolate
examples look extremely good, looking forward to it! I'll see how sample
works on my dataset in the meantime.
Maybe the explanation can be added to decimate
documentation (or to example), because it appeared like a bug to me. Especially taking into account that decimate_pro
kept the arrays, so i kept rereading function docs looking if i missed some argument.
Huh, decimate_pro
does indeed preserve point data (but not cell data) - I did not realize that. You're absolutely right that we should document that the decimate
filter will drop and point/cell arrays and then point the user to the interpolate
filter. Would you be up for such a pull request, @nidu?
Yeap, i can try to come up with a PR, but that will mostly be copying your answer, because it's very detailed.
Describe the bug, what's wrong, and what you expect:
After calling
decimate
on aPolyData
instance -elevation
array is not preserved. I'd really like to keep it.To Reproduce
Output is
Notice how
N Arrays
is 0 after decimation.Screenshots
System Information: