注釈
Go to the end をクリックすると完全なサンプルコードをダウンロードできます.
補間/サンプリング法の比較#
There are two main methods of interpolating or sampling data from a target mesh
in PyVista. pyvista.DataSetFilters.interpolate()
uses a distance weighting
kernel to interpolate point data from nearby points of the target mesh onto
the desired points.
pyvista.DataObjectFilters.sample()
interpolates data using the
interpolation scheme of the enclosing cell from the target mesh.
If the target mesh is a point cloud, i.e. there is no connectivity in the cell
structure, then pyvista.DataSetFilters.interpolate()
is typically
preferred. If interpolation is desired within the cells of the target mesh, then
pyvista.DataObjectFilters.sample()
is typically desired.
ここでは、矩形領域のメッシュからデータをサンプリングする単純な例を用いて、2つの方法を比較対照します。 この例は,上記の主な相違点を示しています. より複雑な使い方については 詳細な補間点 や 詳細なリサンプリング を参照してください。
from __future__ import annotations
import numpy as np
import pyvista as pv
点群からの補間#
A point cloud is a collection of points that have no connectivity in
the mesh, i.e. the mesh contains no cells or the cells are 0D
(vertex or polyvertex). The filter pyvista.DataSetFilters.interpolate()
uses a distance-based weighting methodology to interpolate between the
unconnected points.
First, generate a point cloud mesh in a rectangular domain from
(0, 0)
to (3, 1)
. The data to be sampled is the square of the y position.
rng = np.random.default_rng(seed=0)
points = rng.uniform(low=[0, 0], high=[3, 1], size=(250, 2))
# Make points be z=0
points = np.hstack((points, np.zeros((250, 1))))
point_mesh = pv.PolyData(points)
point_mesh['ysquared'] = points[:, 1] ** 2
点群データはこのようになります。
pl = pv.Plotter()
pl.add_mesh(point_mesh, render_points_as_spheres=True, point_size=10)
pl.view_xy()
pl.show()

Now estimate data on a regular grid from the point data. Note
that the distance parameter radius
determines how far away to
look for point cloud data.
grid = pv.ImageData(dimensions=(11, 11, 1), spacing=[3 / 10, 1 / 10, 1])
output = grid.interpolate(point_mesh, radius=0.1, null_value=-1)
output
When using radius=0.1
, the expected extents of the data are
captured reasonably well over the domain, but there are holes in the
data (represented by the darkest blue colors) caused by no points within
the radius
to interpolate from.
pl = pv.Plotter()
pl.add_mesh(output, clim=[0, 1])
pl.add_mesh(points, render_points_as_spheres=True, point_size=10, color='red')
pl.view_xy()
pl.show()

Now repeat with radius=0.25
.
There are no holes but the extents of the data is much narrower
than [0, 1]
. This is caused by more interior points involved
in the weighting near the lower and upper edges of the domain.
Other parameters such as sharpness
could be tuned to try to
lessen the issue.
grid = pv.ImageData(dimensions=(11, 11, 1), spacing=[3 / 10, 1 / 10, 1])
output = grid.interpolate(point_mesh, radius=0.25, null_value=-1)
pl = pv.Plotter()
pl.add_mesh(output, clim=[0, 1])
pl.add_mesh(points, render_points_as_spheres=True, point_size=10, color='red')
pl.view_xy()
pl.show()

While this filter is very useful for point clouds, it is possible to use
it to interpolate from the points on other mesh types. With
unstuitable choice of radius
the interpolation doesn't look very good.
It is recommended consider using pyvista.DataObjectFilters.sample()
in a
case like this (see next section below). However, there may be cases with
non-point cloud meshes where pyvista.DataSetFilters.interpolate()
is
still preferred.
sphere = pv.SolidSphere(center=(0.5, 0.5, 0), outer_radius=1.0)
sphere['ysquared'] = sphere.points[:, 1] ** 2
output = grid.interpolate(sphere, radius=0.1)
pl = pv.Plotter()
pl.add_mesh(output, clim=[0, 1])
pl.add_mesh(sphere, style='wireframe', color='white')
pl.view_xy()
pl.show()

接続性を持つメッシュからのサンプリング#
This example is in many ways the opposite of the prior one.
A mesh with cell connectivity that spans 2 dimensions is
sampled at discrete points using pyvista.DataObjectFilters.sample()
.
Importantly, the cell connectivity enables direct interpolation
inside the domain without needing distance or weighting parametization.
First, show that sample does not work with point clouds with data.
Either pyvista.DataSetFilters.interpolate()
or the
snap_to_closest_point
parameter must be used.
grid = pv.ImageData(dimensions=(11, 11, 1), spacing=[3 / 10, 1 / 10, 1])
output = grid.sample(point_mesh)
# value of (0, 0) shows that no data was sampled
print(f'(min, max): {output["ysquared"].min()}, {output["ysquared"].min()}')
(min, max): 0.0, 0.0
サンプリング元となる非点群メッシュを作成し、プロットします。
grid = pv.ImageData(dimensions=(11, 11, 1), spacing=[3 / 10, 1 / 10, 1])
grid['ysquared'] = grid.points[:, 1] ** 2
pl = pv.Plotter()
pl.add_mesh(grid, clim=[0, 1])
pl.view_xy()
pl.show()

Now sample it at the discrete points used in the first example.
データにノイズがなく、補間誤差もほとんどないため、これは最初の例の最初のプロットと同じように見えます。
pl = pv.Plotter()
pl.add_mesh(output, render_points_as_spheres=True, point_size=10)
pl.view_xy()
pl.show()

Instead of sampling onto a point cloud, pyvista.DataObjectFilters.sample()
can sample using other mesh types. For example, sampling onto a rotated subset
of the grid.
サブセット (0.7, 0.7, 0) を単位寸法にし、その中心を中心に45度回転させます。
subset = pv.ImageData(dimensions=(8, 8, 1), spacing=[0.1, 0.1, 0], origin=(0.15, 0.15, 0))
rotated_subset = subset.rotate_vector(vector=(0, 0, 1), angle=45, point=(0.5, 0.5, 0))
output = rotated_subset.sample(grid)
output
/home/runner/work/pyvista-docs-dev-ja/pyvista-docs-dev-ja/pyvista-doc-translations/pyvista/pyvista/core/utilities/transformations.py:488: RuntimeWarning: invalid value encountered in divide
K = (SK * (I3 == 0.0)) / S[:, np.newaxis] + I3
/home/runner/work/pyvista-docs-dev-ja/pyvista-docs-dev-ja/pyvista-doc-translations/pyvista/pyvista/core/grid.py:1064: UserWarning: The transformation matrix has a shear component which has been removed.
Shear is not supported when setting `ImageData` `index_to_physical_matrix`.
warnings.warn(
サンプリングされた領域のデータは、データの振る舞いが良く、補間誤差が少ないため、元のグリッドと同じように見えます。
pl = pv.Plotter()
pl.add_mesh(grid, style='wireframe', clim=[0, 1])
pl.add_mesh(output, clim=[0, 1])
pl.view_xy()
pl.show()

Repeat the sphere interpolation example, but using
pyvista.DataObjectFilters.sample()
. This method
is directly able to sample from the mesh in this case without
fiddling with distance weighting parameters.
sphere = pv.SolidSphere(center=(0.5, 0.5, 0), outer_radius=1.0)
sphere['ysquared'] = sphere.points[:, 1] ** 2
output = grid.sample(sphere)
pl = pv.Plotter()
pl.add_mesh(output, clim=[0, 1])
pl.add_mesh(sphere, style='wireframe', color='white')
pl.view_xy()
pl.show()

Total running time of the script: (0 minutes 2.035 seconds)