Skip to content

Commit

Permalink
Add make uniform grid class init more explicit (#1783)
Browse files Browse the repository at this point in the history
  • Loading branch information
akaszynski committed Dec 22, 2021
1 parent 596394b commit 06b1ac0
Show file tree
Hide file tree
Showing 14 changed files with 378 additions and 78 deletions.
4 changes: 2 additions & 2 deletions doc/user-guide/data_model.rst
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ a simple mesh containing four isometric cells by starting with a

.. jupyter-execute::

>>> grid = pyvista.UniformGrid((3, 3, 1))
>>> grid = pyvista.UniformGrid(dims=(3, 3, 1))
>>> ugrid = grid.cast_to_unstructured_grid()
>>> ugrid

Expand All @@ -393,7 +393,7 @@ Let's also plot this basic mesh:
:context:
:include-source: False

>>> grid = pyvista.UniformGrid((3, 3, 1))
>>> grid = pyvista.UniformGrid(dims=(3, 3, 1))
>>> ugrid = grid.cast_to_unstructured_grid()

.. pyvista-plot::
Expand Down
4 changes: 2 additions & 2 deletions doc/user-guide/vtk_to_pyvista.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ equivalent code in pyvista is:
Create the grid. Note how the values must use Fortran ordering.
>>> grid = pyvista.UniformGrid((300, 300, 1))
>>> grid = pyvista.UniformGrid(dims=(300, 300, 1))
>>> grid.point_data["values"] = values.flatten(order="F")
Here, PyVista has done several things for us:
Expand Down Expand Up @@ -142,7 +142,7 @@ However, with PyVista you simply need:
xi = np.arange(300)
x, y = np.meshgrid(xi, xi)
values = 127.5 + (1.0 + np.sin(x/25.0)*np.cos(y/25.0))
grid = pv.UniformGrid((300, 300, 1))
grid = pv.UniformGrid(dims=(300, 300, 1))
grid.point_data["values"] = values.flatten(order="F")
grid.plot(cpos='xy', show_scalar_bar=False, cmap='coolwarm')

Expand Down
127 changes: 127 additions & 0 deletions examples/01-filter/flying_edges.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
"""
.. _marching_cubes_example:
Marching Cubes
~~~~~~~~~~~~~~
Generate a surface from a scalar field using the flying edges and
marching cubes filters as provided by the `contour
<pyvista.core.filters.data_set.DataSetFilters.contour>` filter.
Special thanks to GitHub user `stla <https://gist.github.com/stla>`
for providing examples.
"""
import numpy as np

import pyvista as pv

###############################################################################
# Spider Cage
# ~~~~~~~~~~~
# Use the marching cubes algorithm to extract the isosurface
# generated from the spider cage function.

a = 0.9
def spider_cage(x, y, z):
x2 = x * x
y2 = y * y
x2_y2 = x2 + y2
return (
np.sqrt((x2 - y2)**2 / x2_y2 + 3 * (z * np.sin(a))**2) - 3)**2 + 6 * (
np.sqrt((x * y)**2 / x2_y2 + (z * np.cos(a))**2) - 1.5
)**2


# create a uniform grid to sample the function with
n = 100
x_min, y_min, z_min = -5, -5, -3
grid = pv.UniformGrid(
dims=(n, n, n),
spacing=(abs(x_min)/n*2, abs(y_min)/n*2, abs(z_min)/n*2),
origin=(x_min, y_min, z_min),
)
x, y, z = grid.points.T

# sample and plot
values = spider_cage(x, y, z)
mesh = grid.contour(1, values, method='marching_cubes', rng=[1, 0])
dist = np.linalg.norm(mesh.points, axis=1)
mesh.plot(
scalars=dist, smooth_shading=True, specular=5,
cmap="plasma", show_scalar_bar=False
)


###############################################################################
# Barth Sextic
# ~~~~~~~~~~~~
# Use the flying edges algorithm to extract the isosurface
# generated from the barth sextic function.


phi = (1 + np.sqrt(5)) / 2
phi2 = phi * phi
def barth_sextic(x, y, z):
x2 = x * x
y2 = y * y
z2 = z * z
arr = (
3 * (phi2 * x2 - y2) * (phi2 * y2 - z2) * (phi2 * z2 - x2)
- (1 + 2 * phi) * (x2 + y2 + z2 - 1)**2
)
nan_mask = x2 + y2 + z2 > 3.1
arr[nan_mask] = np.nan
return arr

# create a uniform grid to sample the function with
n = 100
k = 2.0
x_min, y_min, z_min = -k, -k, -k
grid = pv.UniformGrid(
dims=(n, n, n),
spacing=(abs(x_min)/n*2, abs(y_min)/n*2, abs(z_min)/n*2),
origin=(x_min, y_min, z_min),
)
x, y, z = grid.points.T

# sample and plot
values = barth_sextic(x, y, z)
mesh = grid.contour(1, values, method='marching_cubes', rng=[-0.0, 0])
dist = np.linalg.norm(mesh.points, axis=1)
mesh.plot(
scalars=dist, smooth_shading=True, specular=5,
cmap="plasma", show_scalar_bar=False
)


###############################################################################
# Animate Barth Sextic
# ~~~~~~~~~~~~~~~~~~~~
# Show 15 frames of various isocurves extracted from the barth sextic
# function.

def angle_to_range(angle):
return -2*np.sin(angle)

mesh = grid.contour(
1, values, method='marching_cubes', rng=[angle_to_range(0), 0]
)
dist = np.linalg.norm(mesh.points, axis=1)

pl = pv.Plotter()
pl.add_mesh(
mesh, scalars=dist, smooth_shading=True, specular=5, rng=[0.5, 1.5],
cmap="plasma", show_scalar_bar=False,
)
pl.open_gif('barth_sextic.gif')

for angle in np.linspace(0, np.pi, 15)[:-1]:
new_mesh = grid.contour(
1, values, method='marching_cubes', rng=[angle_to_range(angle), 0]
)
mesh.overwrite(new_mesh)
pl.update_scalars(np.linalg.norm(new_mesh.points, axis=1), render=False)
pl.write_frame()

pl.show()
6 changes: 5 additions & 1 deletion examples/01-filter/streamlines.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@
nz = 5

origin = (-(nx - 1)*0.1/2, -(ny - 1)*0.1/2, -(nz - 1)*0.1/2)
mesh = pv.UniformGrid((nx, ny, nz), (.1, .1, .1), origin)
mesh = pv.UniformGrid(
dims=(nx, ny, nz),
spacing=(.1, .1, .1),
origin=origin
)
x = mesh.points[:, 0]
y = mesh.points[:, 1]
z = mesh.points[:, 2]
Expand Down
8 changes: 4 additions & 4 deletions pyvista/core/dataobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ def add_field_data(self, array: np.ndarray, name: str, deep=True):
Add field data to a UniformGrid dataset.
>>> mesh = pyvista.UniformGrid((2, 2, 1))
>>> mesh = pyvista.UniformGrid(dims=(2, 2, 1))
>>> mesh.add_field_data(['I could', 'write', 'notes', 'here'],
... 'my-field-data')
>>> mesh['my-field-data']
Expand Down Expand Up @@ -462,7 +462,7 @@ def copy_structure(self, dataset: _vtk.vtkDataSet):
Examples
--------
>>> import pyvista as pv
>>> source = pv.UniformGrid((10, 10, 5))
>>> source = pv.UniformGrid(dims=(10, 10, 5))
>>> target = pv.UniformGrid()
>>> target.copy_structure(source)
>>> target.plot(show_edges=True)
Expand All @@ -481,9 +481,9 @@ def copy_attributes(self, dataset: _vtk.vtkDataSet):
Examples
--------
>>> import pyvista as pv
>>> source = pv.UniformGrid((10, 10, 5))
>>> source = pv.UniformGrid(dims=(10, 10, 5))
>>> source = source.compute_cell_sizes()
>>> target = pv.UniformGrid((10, 10, 5))
>>> target = pv.UniformGrid(dims=(10, 10, 5))
>>> target.copy_attributes(source)
>>> target.plot(scalars='Volume', show_edges=True)
Expand Down
53 changes: 48 additions & 5 deletions pyvista/core/filters/data_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -1244,9 +1244,9 @@ def contour(self, isosurfaces=10, scalars=None, compute_normals=False,
Number of isosurfaces to compute across valid data range or a
sequence of float values to explicitly use as the isosurfaces.
scalars : str, optional
Name of scalars to threshold on. Defaults to currently
active scalars.
scalars : str, numpy.ndarray, optional
Name or array of scalars to threshold on. Defaults to
currently active scalars.
compute_normals : bool, optional
Compute normals for the dataset.
Expand Down Expand Up @@ -1289,7 +1289,41 @@ def contour(self, isosurfaces=10, scalars=None, compute_normals=False,
>>> contours = hills.contour()
>>> contours.plot(line_width=5)
See :ref:`common_filter_example` for more examples using this filter.
Generate the surface of a mobius strip using flying edges.
>>> import pyvista as pv
>>> a = 0.4
>>> b = 0.1
>>> def f(x, y, z):
... xx = x*x
... yy = y*y
... zz = z*z
... xyz = x*y*z
... xx_yy = xx + yy
... a_xx = a*xx
... b_yy = b*yy
... return (
... (xx_yy + 1) * (a_xx + b_yy)
... + zz * (b * xx + a * yy) - 2 * (a - b) * xyz
... - a * b * xx_yy
... )**2 - 4 * (xx + yy) * (a_xx + b_yy - xyz * (a - b))**2
>>> n = 100
>>> x_min, y_min, z_min = -1.35, -1.7, -0.65
>>> grid = pv.UniformGrid(
... dims=(n, n, n),
... spacing=(abs(x_min)/n*2, abs(y_min)/n*2, abs(z_min)/n*2),
... origin=(x_min, y_min, z_min),
... )
>>> x, y, z = grid.points.T
>>> values = f(x, y, z)
>>> out = grid.contour(
... 1, scalars=values, rng=[0, 0], method='flying_edges'
... )
>>> out.plot(color='tan', smooth_shading=True)
See :ref:`common_filter_example` or
:ref:`marching_cubes_example` for more examples using this
filter.
"""
if method is None or method == 'contour':
Expand All @@ -1300,9 +1334,18 @@ def contour(self, isosurfaces=10, scalars=None, compute_normals=False,
alg = _vtk.vtkFlyingEdges3D()
else:
raise ValueError(f"Method '{method}' is not supported")

if isinstance(scalars, np.ndarray):
scalars_name = 'Contour Input'
self[scalars_name] = scalars
scalars = scalars_name

# Make sure the input has scalars to contour on
if self.n_arrays < 1:
raise ValueError('Input dataset for the contour filter must have scalar data.')
raise ValueError(
'Input dataset for the contour filter must have scalar.'
)

alg.SetInputDataObject(self)
alg.SetComputeNormals(compute_normals)
alg.SetComputeGradients(compute_gradients)
Expand Down

0 comments on commit 06b1ac0

Please sign in to comment.