{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Creating a Spline {#create_spline_example}\n\nCreate a spline/polyline from a numpy array of XYZ vertices using\n`pyvista.Spline`{.interpreted-text role=\"func\"}.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import numpy as np\n\nimport pyvista as pv"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Create a dataset to plot\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "def make_points():\n    \"\"\"Helper to make XYZ points\"\"\"\n    theta = np.linspace(-4 * np.pi, 4 * np.pi, 100)\n    z = np.linspace(-2, 2, 100)\n    r = z**2 + 1\n    x = r * np.sin(theta)\n    y = r * np.cos(theta)\n    return np.column_stack((x, y, z))\n\n\npoints = make_points()\npoints[0:5, :]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Now let\\'s make a function that can create line cells on a\n`pyvista.PolyData`{.interpreted-text role=\"class\"} mesh given that the\npoints are in order for the segments they make.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "def lines_from_points(points):\n    \"\"\"Given an array of points, make a line set\"\"\"\n    poly = pv.PolyData()\n    poly.points = points\n    cells = np.full((len(points) - 1, 3), 2, dtype=np.int_)\n    cells[:, 1] = np.arange(0, len(points) - 1, dtype=np.int_)\n    cells[:, 2] = np.arange(1, len(points), dtype=np.int_)\n    poly.lines = cells\n    return poly\n\n\nline = lines_from_points(points)\nline"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "line[\"scalars\"] = np.arange(line.n_points)\ntube = line.tube(radius=0.1)\ntube.plot(smooth_shading=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "That tube has sharp edges at each line segment. This can be mitigated by\ncreating a single PolyLine cell for all of the points\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "def polyline_from_points(points):\n    poly = pv.PolyData()\n    poly.points = points\n    the_cell = np.arange(0, len(points), dtype=np.int_)\n    the_cell = np.insert(the_cell, 0, len(points))\n    poly.lines = the_cell\n    return poly\n\n\npolyline = polyline_from_points(points)\npolyline[\"scalars\"] = np.arange(polyline.n_points)\ntube = polyline.tube(radius=0.1)\ntube.plot(smooth_shading=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "You could also interpolate those points onto a parametric spline\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Create spline with 1000 interpolation points\nspline = pv.Spline(points, 1000)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Plot spline as a tube\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# add scalars to spline and plot it\nspline[\"scalars\"] = np.arange(spline.n_points)\ntube = spline.tube(radius=0.1)\ntube.plot(smooth_shading=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "The spline can also be plotted as a plain line\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# generate same spline with 400 interpolation points\nspline = pv.Spline(points, 400)\n\n# plot without scalars\nspline.plot(line_width=4, color=\"k\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "The radius of the tube can be modulated with scalars\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "spline[\"theta\"] = 0.4 * np.arange(len(spline.points))\nspline[\"radius\"] = np.abs(np.sin(spline[\"theta\"]))\ntube = spline.tube(scalars=\"radius\", absolute=True)\ntube.plot(scalars=\"theta\", smooth_shading=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Ribbons\n\nAyy of the lines from the examples above can be used to create ribbons.\nTake a look at the `pyvista.PolyDataFilters.ribbon`{.interpreted-text\nrole=\"func\"} filter.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "ribbon = spline.compute_arc_length().ribbon(width=0.75, scalars='arc_length')\nribbon.plot(color=True)"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.2"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}