スライシング#

ボリュームから薄い平面スライスを抽出します.

import matplotlib.pyplot as plt
import numpy as np

import pyvista as pv
from pyvista import examples

PyVistaメッシュには,すべてのデータセットに直接バインドされた複数のスライシングフィルタがあります.これらのフィルタを使用すると,ボリュームデータセットをスライスして,データのボリュームからセクションを抽出して表示できます.

PyVistaで使用される最も一般的なスライシングフィルタの1つは, 3つの直交面に平行なデータセットを通して3つの直交スライスを生成する pyvista.DataSetFilters.slice_orthogonal() フィルタです.たとえば,サンプルの地理統計トレーニングイメージボリュームをスライスしてみましょう.まず,ボリュームをロードしてプレビューします.

mesh = examples.load_channels()
# define a categorical colormap
cmap = plt.cm.get_cmap("viridis", 4)

mesh.plot(cmap=cmap)
slicing
/home/runner/work/pyvista-docs-dev-ja/pyvista-docs-dev-ja/pyvista-doc-translations/pyvista/examples/01-filter/slicing.py:29: MatplotlibDeprecationWarning: The get_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps[name]`` or ``matplotlib.colormaps.get_cmap(obj)`` instead.
  cmap = plt.cm.get_cmap("viridis", 4)

このデータセットは3 Dボリュームであり,このボリューム内に検査したい領域がある場合があります.メッシュを使用してスライスを作成し,ボリュームの内部についてさらに詳しく調べることができます.

slices = mesh.slice_orthogonal()

slices.plot(cmap=cmap)
slicing

直交スライスは,ボリューム全体で簡単に変換できます:

slices = mesh.slice_orthogonal(x=20, y=20, z=30)
slices.plot(cmap=cmap)
slicing

pyvista.DataSetFilters.slice() フィルタでスライス平面の原点と法線を指定することで,ボリュームの単一スライスを追加することもできます.

# Single slice - origin defaults to the center of the mesh
single_slice = mesh.slice(normal=[1, 1, 0])

p = pv.Plotter()
p.add_mesh(mesh.outline(), color="k")
p.add_mesh(single_slice, cmap=cmap)
p.show()
slicing

軸方向に均一にスライス平面を追加することも, pyvista.DataSetFilters.slice_along_axis() フィルタを使用して自動化できます.

slices = mesh.slice_along_axis(n=7, axis="y")

slices.plot(cmap=cmap)
slicing

線分に沿ってスライス#

pyvista.DataSetFilters.slice_along_line() フィルタを用いて pyvista.Spline() または pyvista.Line() に沿ってデータセットをスライスすることもできる.

最初に,対象のデータセットを使用して線のソースを定義します.このタイプのスライスは計算コストが高く,線に多くの点がある場合は時間がかかることに注意してください.線の解像度を低くしてください.

model = examples.load_channels()


def path(y):
    """Equation: x = a(y-h)^2 + k"""
    a = 110.0 / 160.0**2
    x = a * y**2 + 0.0
    return x, y


x, y = path(np.arange(model.bounds[2], model.bounds[3], 15.0))
zo = np.linspace(9.0, 11.0, num=len(y))
points = np.c_[x, y, zo]
spline = pv.Spline(points, 15)
spline
HeaderData Arrays
PolyDataInformation
N Cells1
N Points15
N Strips0
X Bounds0.000e+00, 2.475e+02
Y Bounds0.000e+00, 2.400e+02
Z Bounds9.000e+00, 1.100e+01
N Arrays1
NameFieldTypeN CompMinMax
arc_lengthPointsfloat3210.000e+003.605e+02


次に,フィルタを実行します.

slc = model.slice_along_line(spline)
slc
HeaderData Arrays
PolyDataInformation
N Cells49100
N Points49692
N Strips0
X Bounds0.000e+00, 2.500e+02
Y Bounds0.000e+00, 2.415e+02
Z Bounds0.000e+00, 1.000e+02
N Arrays1
NameFieldTypeN CompMinMax
faciesCellsint6410.000e+004.000e+00


p = pv.Plotter()
p.add_mesh(slc, cmap=cmap)
p.add_mesh(model.outline())
p.show(cpos=[1, -1, 1])
slicing

ベクトル方向の複数のスライス#

ベクトル方向に沿って垂直にメッシュをスライスします.

mesh = examples.download_brain()

# Create vector
vec = np.array([1.0, 2.0, 1.0])
# Normalize the vector
normal = vec / np.linalg.norm(vec)

# Make points along that vector for the extent of your slices
a = mesh.center + normal * mesh.length / 3.0
b = mesh.center - normal * mesh.length / 3.0

# Define the line/points for the slices
n_slices = 5
line = pv.Line(a, b, n_slices)

# Generate all of the slices
slices = pv.MultiBlock()
for point in line.points:
    slices.append(mesh.slice(normal=normal, origin=point))
p = pv.Plotter()
p.add_mesh(mesh.outline(), color="k")
p.add_mesh(slices, opacity=0.75)
p.add_mesh(line, color="red", line_width=5)
p.show()
slicing

異なる軸受でスライス#

pyvista-support#23 から

ユーザーが選択した位置を中心にして,さまざまな方位のスライスを多数作成する方法の例.

スライスを方向付けるポイントの作成

ranges = np.array(model.bounds).reshape(-1, 2).ptp(axis=1)
point = np.array(model.center) - ranges * 0.25

ここで,Z軸を中心にスライスを回転させる法線ベクトルをいくつか生成します.円はZ軸を中心としているため,円の計算式を使用します.

increment = np.pi / 6.0
# use a container to hold all the slices
slices = pv.MultiBlock()  # treat like a dictionary/list
for theta in np.arange(0, np.pi, increment):
    normal = np.array([np.cos(theta), np.sin(theta), 0.0]).dot(np.pi / 2.0)
    name = f'Bearing: {np.rad2deg(theta):.2f}'
    slices[name] = model.slice(origin=point, normal=normal)
slices
InformationBlocks
MultiBlockValues
N Blocks6
X Bounds0.000, 250.000
Y Bounds0.000, 250.000
Z Bounds0.000, 100.000
IndexNameType
0Bearing: 0.00PolyData
1Bearing: 30.00PolyData
2Bearing: 60.00PolyData
3Bearing: 90.00PolyData
4Bearing: 120.00PolyData
5Bearing: 150.00PolyData


これを表示します.

p = pv.Plotter()
p.add_mesh(slices, cmap=cmap)
p.add_mesh(model.outline())
p.show()
slicing

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

Sphinx-Galleryによるギャラリー