Skip to content

Commit

Permalink
Merge branch 'main' into release/0.39
Browse files Browse the repository at this point in the history
  • Loading branch information
akaszynski committed May 5, 2023
2 parents 5b68e16 + be3b560 commit e47a190
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 21 deletions.
8 changes: 4 additions & 4 deletions doc/source/api/core/pointsets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,12 @@ grid from NumPy arrays.
import numpy as np

x = np.arange(-10, 10, 1, dtype=np.float32)
y = np.arange(-10, 10, 1, dtype=np.float32)
z = np.arange(-10, 10, 2, dtype=np.float32)
x, y, z = np.meshgrid(x, y, z)
y = np.arange(-10, 10, 2, dtype=np.float32)
z = np.arange(-10, 10, 5, dtype=np.float32)
x, y, z = np.meshgrid(x, y, z, indexing='ij')

# create the unstructured grid directly from the numpy arrays and plot
grid = pv.StructuredGrid(x[::-1], y[::-1], z[::-1])
grid = pv.StructuredGrid(x, y, z)
grid.plot(show_edges=True)


Expand Down
3 changes: 2 additions & 1 deletion doc/source/getting-started/why.rst
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ field of arrows using :func:`numpy.meshgrid`:
# Make a grid
x, y, z = np.meshgrid(np.linspace(-5, 5, 20),
np.linspace(-5, 5, 20),
np.linspace(-5, 5, 5))
np.linspace(-5, 5, 5),
indexing='ij')

points = np.empty((x.size, 3))
points[:, 0] = x.ravel('F')
Expand Down
7 changes: 6 additions & 1 deletion pyvista/_vtk.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,12 @@
vtkUnstructuredGridToExplicitStructuredGrid,
vtkWindowedSincPolyDataFilter,
)
from vtkmodules.vtkFiltersExtraction import vtkExtractGeometry, vtkExtractGrid, vtkExtractSelection
from vtkmodules.vtkFiltersExtraction import (
vtkExtractCellsByType,
vtkExtractGeometry,
vtkExtractGrid,
vtkExtractSelection,
)
from vtkmodules.vtkFiltersFlowPaths import vtkEvenlySpacedStreamlines2D, vtkStreamTracer
from vtkmodules.vtkFiltersGeneral import (
vtkAxes,
Expand Down
81 changes: 79 additions & 2 deletions pyvista/core/filters/data_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,6 @@ def align(
... source.points, return_closest_point=True
... )
>>> dist = np.linalg.norm(source.points - closest_points, axis=1)
>>> np.abs(dist).mean() # doctest:+SKIP
9.997635192915073e-05
Visualize the source, transformed, and aligned meshes.
Expand All @@ -155,6 +153,12 @@ def align(
... )
>>> pl.show()
Show that the mean distance between the source and the target is
nearly zero.
>>> np.abs(dist).mean() # doctest:+SKIP
9.997635192915073e-05
"""
icp = _vtk.vtkIterativeClosestPointTransform()
icp.SetSource(self)
Expand Down Expand Up @@ -5654,6 +5658,79 @@ def separate_cells(self):
"""
return self.shrink(1.0)

def extract_cells_by_type(self, cell_types, progress_bar=False):
"""Extract cells of a specified type.
Given an input dataset and a list of cell types, produce an output
dataset containing only cells of the specified type(s). Note that if
the input dataset is homogeneous (e.g., all cells are of the same type)
and the cell type is one of the cells specified, then the input dataset
is shallow copied to the output.
The type of output dataset is always the same as the input type. Since
structured types of data (i.e., :class:`pyvista.UniformGrid`,
:class:`pyvista.StructuredGrid`, :class`pyvista.RectilnearGrid`,
:class:`pyvista.UniformGrid`) are all composed of a cell of the same
type, the output is either empty, or a shallow copy of the input.
Unstructured data (:class:`pyvista.UnstructuredGrid`,
:class:`pyvista.PolyData`) input may produce a subset of the input data
(depending on the selected cell types).
Parameters
----------
cell_types : int | sequence[int]
The cell types to extract. Must be a single or list of integer cell
types. See :class:`pyvista.CellType`.
progress_bar : bool, default: False
Display a progress bar to indicate progress.
Returns
-------
pyvista.DataSet
Dataset with the extracted cells. Type is the same as the input.
Notes
-----
Unlike :func:`pyvista.DataSetFilters.extract_cells` which always
produces a :class:`pyvista.UnstructuredGrid` output, this filter
produces the same output type as input type.
Examples
--------
Create an unstructured grid with both hexahedral and tetrahedral
cells and then extract each individual cell type.
>>> import pyvista as pv
>>> from pyvista import examples
>>> beam = examples.load_hexbeam()
>>> beam = beam.translate([1, 0, 0])
>>> ugrid = beam + examples.load_tetbeam()
>>> hex_cells = ugrid.extract_cells_by_type(pv.CellType.HEXAHEDRON)
>>> tet_cells = ugrid.extract_cells_by_type(pv.CellType.TETRA)
>>> pl = pv.Plotter(shape=(1, 2))
>>> _ = pl.add_text('Extracted Hexahedron cells')
>>> _ = pl.add_mesh(hex_cells, show_edges=True)
>>> pl.subplot(0, 1)
>>> _ = pl.add_text('Extracted Tetrahedron cells')
>>> _ = pl.add_mesh(tet_cells, show_edges=True)
>>> pl.show()
"""
alg = _vtk.vtkExtractCellsByType()
alg.SetInputDataObject(self)
if isinstance(cell_types, int):
alg.AddCellType(cell_types)
elif isinstance(cell_types, (np.ndarray, collections.abc.Sequence)):
for cell_type in cell_types:
alg.AddCellType(cell_type)
else:
raise TypeError(
f'Invalid type {type(cell_types)} for `cell_types`. Expecting an int or a sequence.'
)
_update_alg(alg, progress_bar, 'Extracting cell types')
return _get_output(alg)


def _set_threshold_limit(alg, value, method, invert):
"""Set vtkThreshold limits and function.
Expand Down
24 changes: 12 additions & 12 deletions pyvista/core/pointset.py
Original file line number Diff line number Diff line change
Expand Up @@ -2001,18 +2001,18 @@ class StructuredGrid(_vtk.vtkStructuredGrid, PointGrid, StructuredGridFilters):
Create from NumPy arrays.
>>> xrng = np.arange(-10, 10, 2, dtype=np.float32)
>>> yrng = np.arange(-10, 10, 2, dtype=np.float32)
>>> zrng = np.arange(-10, 10, 2, dtype=np.float32)
>>> x, y, z = np.meshgrid(xrng, yrng, zrng)
>>> yrng = np.arange(-10, 10, 5, dtype=np.float32)
>>> zrng = np.arange(-10, 10, 1, dtype=np.float32)
>>> x, y, z = np.meshgrid(xrng, yrng, zrng, indexing='ij')
>>> grid = pyvista.StructuredGrid(x, y, z)
>>> grid # doctest:+SKIP
StructuredGrid (0x7fb18f2a8580)
N Cells: 729
N Points: 1000
N Cells: 513
N Points: 800
X Bounds: -1.000e+01, 8.000e+00
Y Bounds: -1.000e+01, 8.000e+00
Z Bounds: -1.000e+01, 8.000e+00
Dimensions: 10, 10, 10
Y Bounds: -1.000e+01, 5.000e+00
Z Bounds: -1.000e+01, 9.000e+00
Dimensions: 10, 4, 20
N Arrays: 0
"""
Expand Down Expand Up @@ -2117,10 +2117,10 @@ def dimensions(self):
>>> xrng = np.arange(-10, 10, 1, dtype=np.float32)
>>> yrng = np.arange(-10, 10, 2, dtype=np.float32)
>>> zrng = np.arange(-10, 10, 5, dtype=np.float32)
>>> x, y, z = np.meshgrid(xrng, yrng, zrng)
>>> x, y, z = np.meshgrid(xrng, yrng, zrng, indexing='ij')
>>> grid = pyvista.StructuredGrid(x, y, z)
>>> grid.dimensions
(10, 20, 4)
(20, 10, 4)
"""
return tuple(self.GetDimensions())
Expand All @@ -2147,10 +2147,10 @@ def x(self):
>>> xrng = np.arange(-10, 10, 1, dtype=np.float32)
>>> yrng = np.arange(-10, 10, 2, dtype=np.float32)
>>> zrng = np.arange(-10, 10, 5, dtype=np.float32)
>>> x, y, z = np.meshgrid(xrng, yrng, zrng)
>>> x, y, z = np.meshgrid(xrng, yrng, zrng, indexing='ij')
>>> grid = pyvista.StructuredGrid(x, y, z)
>>> grid.x.shape
(10, 20, 4)
(20, 10, 4)
"""
return self._reshape_point_array(self.points[:, 0])
Expand Down
9 changes: 8 additions & 1 deletion pyvista/utilities/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ def voxelize(mesh, density=None, check_surface=True):
pyvista.UnstructuredGrid
Voxelized unstructured grid of the original mesh.
Notes
-----
Prior to version 0.39.0, this method improperly handled the order of
structured coordinates.
Examples
--------
Create an equal density voxelized mesh.
Expand Down Expand Up @@ -68,7 +73,9 @@ def voxelize(mesh, density=None, check_surface=True):
x = np.arange(x_min, x_max, density_x)
y = np.arange(y_min, y_max, density_y)
z = np.arange(z_min, z_max, density_z)
x, y, z = np.meshgrid(x, y, z)
x, y, z = np.meshgrid(x, y, z, indexing='ij')
# indexing='ij' is used here in order to make grid and ugrid with x-y-z ordering, not y-x-z ordering
# see https://github.com/pyvista/pyvista/pull/4365

# Create unstructured grid from the structured grid
grid = pyvista.StructuredGrid(x, y, z)
Expand Down
18 changes: 18 additions & 0 deletions tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -2671,6 +2671,24 @@ def test_subdivide_tetra(tetbeam):
assert grid.n_cells == tetbeam.n_cells * 12


def test_extract_cells_by_type(tetbeam, hexbeam):
combined = tetbeam + hexbeam

hex_cells = combined.extract_cells_by_type(
[pyvista.CellType.HEXAHEDRON, pyvista.CellType.BEZIER_PYRAMID]
)
assert np.alltrue(hex_cells.celltypes == pyvista.CellType.HEXAHEDRON)

tet_cells = combined.extract_cells_by_type(pyvista.CellType.TETRA)
assert np.alltrue(tet_cells.celltypes == pyvista.CellType.TETRA)

should_be_empty = combined.extract_cells_by_type(pyvista.CellType.BEZIER_CURVE)
assert should_be_empty.n_cells == 0

with pytest.raises(TypeError, match='Invalid type'):
combined.extract_cells_by_type(1.0)


def test_merge_points():
cells = [2, 0, 1]
celltypes = [pyvista.CellType.LINE]
Expand Down

0 comments on commit e47a190

Please sign in to comment.