
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "tutorial/06_vtk/a_1_transition_vtk.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_tutorial_06_vtk_a_1_transition_vtk.py>`
        to download the full example code. or to run this example in your browser via Binder

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_tutorial_06_vtk_a_1_transition_vtk.py:


Transitioning from VTK to PyVista
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

VTK is primarily developed in C++ and uses chained setter and getter
commands to access data. Instead, PyVista wraps the VTK data types
into numpy arrays so that users can benefit from its bracket syntax
and fancy indexing.  This section demonstrates the difference between
the two approaches in a series of examples.

For example, to hard-code values for a :vtk:`vtkImageData` data
structure using VTK Python's bindings, one would write the following:

.. GENERATED FROM PYTHON SOURCE LINES 15-20

.. code-block:: Python


    from math import cos, sin

    import vtk








.. GENERATED FROM PYTHON SOURCE LINES 21-28

Create values for a 300x300 image dataset

In our example, we want to have values from the function

.. code-block:: python

  127.5 + (1.0 + sin(x/25.0)*cos(y/25.0))

.. GENERATED FROM PYTHON SOURCE LINES 28-37

.. code-block:: Python

    values = vtk.vtkDoubleArray()
    values.SetName("values")
    values.SetNumberOfComponents(1)
    values.SetNumberOfTuples(300 * 300)

    for x in range(300):
        for y in range(300):
            values.SetValue(x * 300 + y, 127.5 + (1.0 + sin(x / 25.0) * cos(y / 25.0)))








.. GENERATED FROM PYTHON SOURCE LINES 38-39

Create the image structure

.. GENERATED FROM PYTHON SOURCE LINES 39-44

.. code-block:: Python

    image_data = vtk.vtkImageData()
    image_data.SetOrigin(0, 0, 0)
    image_data.SetSpacing(1, 1, 1)
    image_data.SetDimensions(300, 300, 1)








.. GENERATED FROM PYTHON SOURCE LINES 45-46

Assign the values to the image

.. GENERATED FROM PYTHON SOURCE LINES 46-48

.. code-block:: Python

    image_data.GetPointData().SetScalars(values)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    0



.. GENERATED FROM PYTHON SOURCE LINES 49-53

As you can see, there is quite a bit of boilerplate that goes into
the creation of a simple :vtk:`vtkImageData` dataset. PyVista provides
much more concise syntax that is more "Pythonic". The equivalent code in
PyVista is:

.. GENERATED FROM PYTHON SOURCE LINES 53-57

.. code-block:: Python


    import numpy as np
    import pyvista as pv








.. GENERATED FROM PYTHON SOURCE LINES 58-60

Use the meshgrid function to create 2D "grids" of the x and y values.
This section effectively replaces the vtkDoubleArray.

.. GENERATED FROM PYTHON SOURCE LINES 60-65

.. code-block:: Python


    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))








.. GENERATED FROM PYTHON SOURCE LINES 66-67

Create the grid.  Note how the values must use Fortran ordering.

.. GENERATED FROM PYTHON SOURCE LINES 67-71

.. code-block:: Python


    grid = pv.ImageData(dimensions=(300, 300, 1))
    grid.point_data["values"] = values.flatten(order="F")








.. GENERATED FROM PYTHON SOURCE LINES 72-130

Here, PyVista has done several things for us:

#. PyVista combines the dimensionality of the data (in the shape of
   the :class:`numpy.ndarray`) with the values of the data in one line. VTK uses
   "tuples" to describe the shape of the data (where it sits in space)
   and "components" to describe the type of data (1 = scalars/scalar
   fields, 2 = vectors/vector fields, n = tensors/tensor
   fields). Here, shape and values are stored concretely in one
   variable.

#. :class:`pyvista.ImageData` wraps :vtk:`vtkImageData`, just with a
   different name; they are both containers of evenly spaced points. Your
   data does not have to be an "image" to use it with
   :vtk:`vtkImageData`; rather, like images, values in the dataset are
   evenly spaced apart like pixels in an image.

   Furthermore, since we know the container is for uniformly spaced data,
   pyvista sets the origin and spacing by default to ``(0, 0, 0)`` and
   ``(1, 1, 1)``. This is another great thing about PyVista and Python!
   Rather than having to know everything about the VTK library up front,
   you can get started very easily! Once you get more familiar with it
   and need to do something more complex, you can dive deeper. For
   example, changing the origin and spacing is as simple as:

   .. code:: python

      grid.origin = (10, 20, 10)
      grid.spacing = (2, 3, 5)

#. The name for the :attr:`point_array <pyvista.point_array>` is given
   directly in dictionary-style fashion. Also, since VTK stores data
   on the heap (linear segments of RAM; a C++ concept), the
   data must be flattened and put in Fortran ordering (which controls
   how multidimensional data is laid out in physically 1d memory; numpy
   uses "C"-style memory layout by default). This is why in our earlier
   example, the first argument to ``SetValue()`` was written as
   ``x*300 + y``. Here, numpy takes care of this for us quite nicely
   and it's made more explicit in the code, following the Python best
   practice of "Explicit is better than implicit".

Finally, with PyVista, each geometry class contains methods that allow
you to immediately plot the mesh without also setting up the plot.
For example, in VTK you would have to do:

.. code:: python

    actor = vtk.vtkImageActor()
    actor.GetMapper().SetInputData(image_data)
    ren = vtk.vtkRenderer()
    renWin = vtk.vtkRenderWindow()
    renWin.AddRenderer(ren)
    renWin.SetWindowName('ReadSTL')
    iren = vtk.vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)
    ren.AddActor(actor)
    iren.Initialize()
    renWin.Render()
    iren.Start()

.. GENERATED FROM PYTHON SOURCE LINES 132-133

However, with PyVista you only need:

.. GENERATED FROM PYTHON SOURCE LINES 133-137

.. code-block:: Python


    grid.plot(cpos="xy", show_scalar_bar=False, cmap="coolwarm")









.. tab-set::



   .. tab-item:: Static Scene



            
     .. image-sg:: /tutorial/06_vtk/images/sphx_glr_a_1_transition_vtk_001.png
        :alt: a 1 transition vtk
        :srcset: /tutorial/06_vtk/images/sphx_glr_a_1_transition_vtk_001.png
        :class: sphx-glr-single-img
     


   .. tab-item:: Interactive Scene



       .. offlineviewer:: /home/runner/work/pyvista-tutorial/pyvista-tutorial/doc/source/tutorial/06_vtk/images/sphx_glr_a_1_transition_vtk_001.vtksz






.. GENERATED FROM PYTHON SOURCE LINES 138-144

PointSet Construction
^^^^^^^^^^^^^^^^^^^^^
PyVista heavily relies on NumPy to efficiently allocate and access
VTK's C arrays.  For example, to create an array of points within VTK
one would normally loop through all the points of a list and supply
that to a  :vtk:`vtkPoints` class.  For example:

.. GENERATED FROM PYTHON SOURCE LINES 144-160

.. code-block:: Python


    vtk_array = vtk.vtkDoubleArray()
    vtk_array.SetNumberOfComponents(3)
    vtk_array.SetNumberOfValues(9)
    vtk_array.SetValue(0, 0)
    vtk_array.SetValue(1, 0)
    vtk_array.SetValue(2, 0)
    vtk_array.SetValue(3, 1)
    vtk_array.SetValue(4, 0)
    vtk_array.SetValue(5, 0)
    vtk_array.SetValue(6, 0.5)
    vtk_array.SetValue(7, 0.667)
    vtk_array.SetValue(8, 0)
    vtk_points = vtk.vtkPoints()
    vtk_points.SetData(vtk_array)








.. GENERATED FROM PYTHON SOURCE LINES 161-162

To do the same within PyVista, you simply need to create a NumPy array:

.. GENERATED FROM PYTHON SOURCE LINES 162-165

.. code-block:: Python


    np_points = np.array([[0, 0, 0], [1, 0, 0], [0.5, 0.667, 0]])








.. GENERATED FROM PYTHON SOURCE LINES 166-173

.. note::
   You can use :func:`pyvista.vtk_points` to construct a :vtk:`vtkPoints`
   object, but this is unnecessary in almost all situations.

Since the end goal is to construct a :class:`pyvista.DataSet
<pyvista.core.dataset.DataSet>`, you would simply pass the
``np_points`` array to the :class:`pyvista.PolyData` constructor:

.. GENERATED FROM PYTHON SOURCE LINES 173-177

.. code-block:: Python



    poly_data = pv.PolyData(np_points)








.. GENERATED FROM PYTHON SOURCE LINES 178-179

Whereas in VTK you would have to do:

.. GENERATED FROM PYTHON SOURCE LINES 179-183

.. code-block:: Python


    vtk_poly_data = vtk.vtkPolyData()
    vtk_poly_data.SetPoints(vtk_points)








.. GENERATED FROM PYTHON SOURCE LINES 184-188

The same goes with assigning face or cell connectivity/topology.  With
VTK you would normally have to loop using :func:`InsertNextCell` and
:func:`InsertCellPoint`.  For example, to create a single cell
(triangle) and then assign it to :vtk:`vtkPolyData`:

.. GENERATED FROM PYTHON SOURCE LINES 188-196

.. code-block:: Python


    cell_arr = vtk.vtkCellArray()
    cell_arr.InsertNextCell(3)
    cell_arr.InsertCellPoint(0)
    cell_arr.InsertCellPoint(1)
    cell_arr.InsertCellPoint(2)
    vtk_poly_data.SetPolys(cell_arr)








.. GENERATED FROM PYTHON SOURCE LINES 197-200

In PyVista, we can assign this directly in the constructor and then
access it (or change it) from the :attr:`faces
<pyvista.PolyData.faces>` attribute.

.. GENERATED FROM PYTHON SOURCE LINES 200-206

.. code-block:: Python


    faces = np.array([3, 0, 1, 2])
    poly_data = pv.PolyData(np_points, faces)
    poly_data.faces






.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    array([3, 0, 1, 2])



.. GENERATED FROM PYTHON SOURCE LINES 207-215

PyVista Tradeoffs
~~~~~~~~~~~~~~~~~
While most features can, not everything can be simplified in PyVista without
losing functionality or performance.

In the :class:`collision <pyvista.PolyDataFilters.collision>` filter,
we demonstrate how to calculate the collision between two meshes.  For
example:

.. GENERATED FROM PYTHON SOURCE LINES 215-221

.. code-block:: Python


    # create a default sphere and a shifted sphere
    mesh_a = pv.Sphere()
    mesh_b = pv.Sphere(center=(-0.4, 0, 0))
    out, n_coll = mesh_a.collision(mesh_b, generate_scalars=True, contact_mode=2)








.. GENERATED FROM PYTHON SOURCE LINES 222-229

.. code-block:: Python


    pl = pv.Plotter()
    pl.add_mesh(out)
    pl.add_mesh(mesh_b, style="wireframe", color="k")
    pl.camera_position = "xy"
    pl.show()








.. tab-set::



   .. tab-item:: Static Scene



            
     .. image-sg:: /tutorial/06_vtk/images/sphx_glr_a_1_transition_vtk_002.png
        :alt: a 1 transition vtk
        :srcset: /tutorial/06_vtk/images/sphx_glr_a_1_transition_vtk_002.png
        :class: sphx-glr-single-img
     


   .. tab-item:: Interactive Scene



       .. offlineviewer:: /home/runner/work/pyvista-tutorial/pyvista-tutorial/doc/source/tutorial/06_vtk/images/sphx_glr_a_1_transition_vtk_002.vtksz






.. GENERATED FROM PYTHON SOURCE LINES 230-239

Under the hood, the collision filter detects mesh collisions using
oriented bounding box (OBB) trees.  For a single collision, this filter
is as performant as the VTK counterpart, but when computing multiple
collisions with the same meshes, as in the `Collision Example <https://docs.pyvista.org/examples/01-filter/collisions.html>`_
example, it is more efficient to use the `vtkCollisionDetectionFilter
<https://vtk.org/doc/nightly/html/classvtkCollisionDetectionFilter.html>`_,
as the OBB tree is computed once for each mesh.  In most cases, pure
PyVista is sufficient for most data science, but there are times when
you may want to use VTK classes directly.

.. GENERATED FROM PYTHON SOURCE LINES 241-248

.. raw:: html

    <center>
      <a target="_blank" href="https://colab.research.google.com/github/pyvista/pyvista-tutorial/blob/gh-pages/notebooks/tutorial/06_vtk/a_1_transition_vtk.ipynb">
        <img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/ width="150px">
      </a>
    </center>


.. rst-class:: sphx-glr-timing

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


.. _sphx_glr_download_tutorial_06_vtk_a_1_transition_vtk.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: binder-badge

      .. image:: images/binder_badge_logo.svg
        :target: https://mybinder.org/v2/gh/pyvista/pyvista-tutorial/gh-pages?urlpath=lab/tree/notebooks/tutorial/06_vtk/a_1_transition_vtk.ipynb
        :alt: Launch binder
        :width: 150 px

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: a_1_transition_vtk.ipynb <a_1_transition_vtk.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: a_1_transition_vtk.py <a_1_transition_vtk.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: a_1_transition_vtk.zip <a_1_transition_vtk.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
