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

.. only:: html

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

        :ref:`Go to the end <sphx_glr_download__auto_examples_plot_multivariate.py>`
        to download the full example code.

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

.. _sphx_glr__auto_examples_plot_multivariate.py:


Multivariate splines
====================
This example demonstrates how to create multivariate splines using SplineBox.

.. GENERATED FROM PYTHON SOURCE LINES 6-14

.. code-block:: Python



    import matplotlib.pyplot as plt
    import numpy as np
    import pyvista
    import splinebox
    import splinebox.multivariate








.. GENERATED FROM PYTHON SOURCE LINES 16-19

1. 1D Bivariate surface spline
------------------------------
1D Bivariate surface spline is a spline that takes two parameters and returns a scalar.

.. GENERATED FROM PYTHON SOURCE LINES 19-43

.. code-block:: Python

    M = (4, 5)
    closed = (False, False)
    control_points = splinebox.multivariate.tensor_product([np.sin(np.linspace(0, np.pi, m + 2)) for m in M])

    spline = splinebox.multivariate.MultivariateSpline(
        M=M, basis_functions=splinebox.B3(), closed=closed, control_points=control_points
    )

    t = np.stack(np.meshgrid(*(np.linspace(0, m, 100) for m in M), indexing="ij"), axis=-1)

    vals = spline(t)

    plt.imshow(vals)
    plt.show()

    points, connectivity = spline.mesh()

    # Prepend the number of points in each element (3 for triangles) for PyVista
    connectivity = np.hstack((np.full((connectivity.shape[0], 1), 3), connectivity))

    # Create and plot the PyVista mesh
    mesh = pyvista.PolyData(points, faces=connectivity)
    mesh.plot(show_edges=True)








.. tab-set::



   .. tab-item:: Static Scene



            
     .. image-sg:: /_auto_examples/images/sphx_glr_plot_multivariate_001.png
        :alt: plot multivariate
        :srcset: /_auto_examples/images/sphx_glr_plot_multivariate_001.png
        :class: sphx-glr-single-img
     


   .. tab-item:: Interactive Scene



       .. offlineviewer:: /home/docs/checkouts/readthedocs.org/user_builds/splinebox/checkouts/stable/docs/_auto_examples/images/sphx_glr_plot_multivariate_001.vtksz


.. image-sg:: /_auto_examples/images/sphx_glr_plot_multivariate_002.png
   :alt: plot multivariate
   :srcset: /_auto_examples/images/sphx_glr_plot_multivariate_002.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 44-48

2. 3D Bivariate surface spline
------------------------------
3D Bivariate surface spline is a spline that takes two parameters and returns a 3D vector.
As an example we will create a pipe shaped surface.

.. GENERATED FROM PYTHON SOURCE LINES 48-51

.. code-block:: Python

    M = (4, 3)
    closed = (True, False)








.. GENERATED FROM PYTHON SOURCE LINES 52-55

We want the spline to be circular in one direction and straight in the other.
For the circular direction we choose an exponential basis function and for the straight direction we choose
the B1 basis function.

.. GENERATED FROM PYTHON SOURCE LINES 55-57

.. code-block:: Python

    basis_functions = (splinebox.Exponential(M[0]), splinebox.B1())








.. GENERATED FROM PYTHON SOURCE LINES 58-61

Let's create the control points for the circular direction.
We create four points equally spaced on a circle with radius one in the x-y plane.
Note that we have to set z to one and not zeros because the control points are multiplied in a multivariate spline and not added.

.. GENERATED FROM PYTHON SOURCE LINES 61-66

.. code-block:: Python

    x = np.sin(np.linspace(0, 2 * np.pi, M[0] + 1))[:-1] + 3
    y = np.cos(np.linspace(0, 2 * np.pi, M[0] + 1))[:-1] - 2
    z = np.ones(M[0])
    control_points_circular = np.stack([x, y, z], axis=-1)








.. GENERATED FROM PYTHON SOURCE LINES 67-68

Next, we construct the control points for the straight direction.

.. GENERATED FROM PYTHON SOURCE LINES 68-92

.. code-block:: Python

    x = np.ones(M[1])
    y = np.ones(M[1])
    # x = np.array([0.5, 1, 0.5])
    # y = np.array([1, 0.5, 1])
    # x = np.array([1, 1, 0.5])
    # y = np.array([1, 0.5, 1])
    z = np.array([0, 1, 2]) + 5
    control_points_straight = np.stack([x, y, z], axis=-1)

    control_points = splinebox.multivariate.tensor_product([control_points_circular, control_points_straight])

    spline = splinebox.multivariate.MultivariateSpline(
        M=M, basis_functions=basis_functions, closed=closed, control_points=control_points
    )

    points, connectivity = spline.mesh()

    # Prepend the number of points in each element (3 for triangles) for PyVista
    connectivity = np.hstack((np.full((connectivity.shape[0], 1), 3), connectivity))

    # Create and plot the PyVista mesh
    mesh = pyvista.PolyData(points, faces=connectivity)
    mesh.plot(show_edges=True)








.. tab-set::



   .. tab-item:: Static Scene



            
     .. image-sg:: /_auto_examples/images/sphx_glr_plot_multivariate_003.png
        :alt: plot multivariate
        :srcset: /_auto_examples/images/sphx_glr_plot_multivariate_003.png
        :class: sphx-glr-single-img
     


   .. tab-item:: Interactive Scene



       .. offlineviewer:: /home/docs/checkouts/readthedocs.org/user_builds/splinebox/checkouts/stable/docs/_auto_examples/images/sphx_glr_plot_multivariate_003.vtksz






.. GENERATED FROM PYTHON SOURCE LINES 93-96

Aligning the pipe along one of the z-axis, allowed us to factorize
the element-wise multiplication as follows:
$\vec[x, y, z] = \vec[x, y, 1] * \vec[1, 1, z]$

.. GENERATED FROM PYTHON SOURCE LINES 98-100

3. The torus
------------

.. GENERATED FROM PYTHON SOURCE LINES 100-132

.. code-block:: Python

    M = (10, 4)
    closed = (True, True)
    torus_basis_functions = (splinebox.Exponential(M[0]), splinebox.Exponential(M[1]))

    R = 5
    r = 1
    control_points = []
    x = np.cos(np.linspace(0, 2 * np.pi, M[0] + 1))[:-1]
    y = np.sin(np.linspace(0, 2 * np.pi, M[0] + 1))[:-1]
    z = np.ones(M[0])
    points = np.stack([x, y, z], axis=-1)
    control_points.append(points)
    x = r * np.sin(np.linspace(0, 2 * np.pi, M[1] + 1))[:-1] + R
    y = r * np.sin(np.linspace(0, 2 * np.pi, M[1] + 1))[:-1] + R
    z = r * np.cos(np.linspace(0, 2 * np.pi, M[1] + 1))[:-1]
    points = np.stack([x, y, z], axis=-1)
    control_points.append(points)
    control_points = splinebox.multivariate.tensor_product(control_points)

    spline = splinebox.multivariate.MultivariateSpline(
        M=M, basis_functions=torus_basis_functions, closed=closed, control_points=control_points
    )

    points, connectivity = spline.mesh()

    # Prepend the number of points in each element (3 for triangles) for PyVista
    connectivity = np.hstack((np.full((connectivity.shape[0], 1), 3), connectivity))

    # Create and plot the PyVista mesh
    mesh = pyvista.PolyData(points, faces=connectivity)
    mesh.plot(show_edges=True)








.. tab-set::



   .. tab-item:: Static Scene



            
     .. image-sg:: /_auto_examples/images/sphx_glr_plot_multivariate_004.png
        :alt: plot multivariate
        :srcset: /_auto_examples/images/sphx_glr_plot_multivariate_004.png
        :class: sphx-glr-single-img
     


   .. tab-item:: Interactive Scene



       .. offlineviewer:: /home/docs/checkouts/readthedocs.org/user_builds/splinebox/checkouts/stable/docs/_auto_examples/images/sphx_glr_plot_multivariate_004.vtksz






.. GENERATED FROM PYTHON SOURCE LINES 133-135

Trivariate spline
=================

.. GENERATED FROM PYTHON SOURCE LINES 135-162

.. code-block:: Python

    trivariate_M = (7, 5, 8)
    trivariate_closed = (False, False, False)
    trivariate_basis_functions = splinebox.B3()
    trivariate_control_points = splinebox.multivariate.tensor_product(
        [np.sin(np.linspace(0, np.pi, m + 2)) for m in trivariate_M]
    )

    spline = splinebox.multivariate.MultivariateSpline(
        M=trivariate_M,
        basis_functions=trivariate_basis_functions,
        closed=trivariate_closed,
        control_points=trivariate_control_points,
    )

    t = np.stack(np.meshgrid(*(np.linspace(0, m, 100) for m in trivariate_M), indexing="ij"), axis=-1)

    vals = spline(t)
    vals = np.squeeze(vals)

    grid = pyvista.ImageData(dimensions=np.array(vals.shape) + 1)
    grid.origin = (0, 0, 0)
    grid.spacing = (1, 1, 1)
    grid.cell_data["values"] = vals.flatten(order="F")
    plotter = pyvista.Plotter()
    plotter.add_volume(grid, cmap="bone", clim=(0, 1))
    plotter.camera_position = "yz"
    plotter.show()







.. tab-set::



   .. tab-item:: Static Scene



            
     .. image-sg:: /_auto_examples/images/sphx_glr_plot_multivariate_005.png
        :alt: plot multivariate
        :srcset: /_auto_examples/images/sphx_glr_plot_multivariate_005.png
        :class: sphx-glr-single-img
     


   .. tab-item:: Interactive Scene



       .. offlineviewer:: /home/docs/checkouts/readthedocs.org/user_builds/splinebox/checkouts/stable/docs/_auto_examples/images/sphx_glr_plot_multivariate_005.vtksz







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

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


.. _sphx_glr_download__auto_examples_plot_multivariate.py:

.. only:: html

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

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

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

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

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

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

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


.. only:: html

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

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