{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Linear Cells {#linear_cells_example}\n\nThis example extends the `create_unstructured_example`{.interpreted-text\nrole=\"ref\"} example by including an explanation of linear VTK cell types\nand how you can create them in PyVista.\n\nLinear cells are cells where points only occur at the edges of each\ncell. Non-linear cells contain additional points along the edges of the\ncell.\n\nFor more details regarding what a\n`pyvista.UnstructuredGrid`{.interpreted-text role=\"class\"} is, please\nsee `point_sets_api`{.interpreted-text role=\"ref\"}.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import numpy as np\n\nimport pyvista as pv\nfrom pyvista.examples import cells as example_cells, plot_cell\n\n# random generator for examples\nrng = np.random.default_rng(2)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Plot an example cell\n\nPyVista contains a simple utility to plot a single cell, which is the\nfundamental unit of each `pyvista.UnstructuredGrid`{.interpreted-text\nrole=\"class\"}. For example, let\\'s plot a simple\n`Wedge <pyvista.examples.cells.Wedge>`{.interpreted-text role=\"func\"}.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "grid = example_cells.Wedge()\nexample_cells.plot_cell(grid)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "This linear cell is composed of 6 points.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "grid.points"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "The UnstructuredGrid is also composed of a single cell and the point\nindices of that cell are defined in\n`cells <pyvista.UnstructuredGrid.cells>`{.interpreted-text role=\"attr\"}.\n\n::: note\n::: title\nNote\n:::\n\nThe leading `6` is the number of points in the cell.\n:::\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "grid.cells"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Combine two UnstructuredGrids\n\nWe can combine two unstructured grids to create a single unstructured\ngrid using the `+` operator.\n\n::: note\n::: title\nNote\n:::\n\nThis is an inefficient way of creating\n`pyvista.UnstructuredGrid`{.interpreted-text role=\"class\"} objects. To\nsee a more efficient implementation see\n`create_unstructured_example`{.interpreted-text role=\"ref\"}.\n:::\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "grid_a = example_cells.Hexahedron()\ngrid_a.points += [0, 2.5, 0]\n\ngrid_b = example_cells.HexagonalPrism()\n\ncombined = grid_b + grid_a\n\nplot_cell(combined, cpos='iso')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "This example helps to illustrate meaning behind the `cells\n<pyvista.UnstructuredGrid.cells>`{.interpreted-text role=\"attr\"}\nattribute. The first cell, a hexahedron contains 8 points and the\nhexagonal prism contains 12 points. The `cells` attribute shows this\nalong with indices composing each cell.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "combined.cells"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Cell Types\n\nPyVista contains the `pyvista.CellType`{.interpreted-text role=\"class\"}\nenumerator, which contains all the available VTK cell types mapped to a\nPython enumerator. These cell types are used when creating cells and\nalso can be used when checking the\n`celltypes <pyvista.UnstructuredGrid.celltypes>`{.interpreted-text\nrole=\"attr\"} attribute. For example `combined.celltypes` contains both\nthe `pv.CellType.HEXAHEDRON` and `pv.CellType.HEXAGONAL_PRISM` cell\ntypes.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "print(pv.CellType.HEXAHEDRON, pv.CellType.HEXAGONAL_PRISM)\ncombined.celltypes == (pv.CellType.HEXAHEDRON, pv.CellType.HEXAGONAL_PRISM)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Create an UnstructuredGrid with a single linear cell\n\nNow that you know the three main inputs of an\n`pyvista.UnstructuredGrid`{.interpreted-text role=\"class\"}, it\\'s quite\nstraightforward to create an unstructured grid with a one or more cells.\nIf you need to reference point ordering or additional, you can either\nread the source of\n[cells.py](https://github.com/pyvista/pyvista/blob/main/pyvista/examples/cells.py)\nor simply create a cell from the `pyvista.core.cells` module and inspect\nits attributes.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "points = [\n    [1.0, 1.0, 0.0],\n    [-1.0, 1.0, 0.0],\n    [-1.0, -1.0, 0.0],\n    [1.0, -1.0, 0.0],\n    [0.0, 0.0, 1.60803807],\n]\ncells = [len(points), *list(range(len(points)))]\npyrmaid = pv.UnstructuredGrid(cells, [pv.CellType.PYRAMID], points)\nexample_cells.plot_cell(pyrmaid)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Plot all linear cell Types\n\nLet\\'s create a `(4, 4)` `pyvista.Plotter`{.interpreted-text\nrole=\"class\"} and plot all 16 linear cells in a single plot.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "def add_cell_helper(pl, text, grid, subplot, cpos=None):\n    \"\"\"Add a single cell to a plotter with fancy plotting.\"\"\"\n    pl.subplot(*subplot)\n    pl.add_text(text, 'lower_edge', color='k', font_size=8)\n    pl.add_mesh(grid, opacity=0.5, color='lightblue', line_width=5)\n    edges = grid.extract_all_edges()\n    if edges.n_cells:\n        pl.add_mesh(grid.extract_all_edges(), line_width=5, color='k')\n    pl.add_points(grid, render_points_as_spheres=True, point_size=20, color='r')\n    pl.add_point_labels(\n        grid.points,\n        range(grid.n_points),\n        always_visible=True,\n        fill_shape=False,\n        margin=0,\n        shape_opacity=0.0,\n        font_size=20,\n        text_color='k',\n    )\n    if cpos is None:\n        pl.camera.azimuth = 20\n        pl.camera.elevation = -20\n    else:\n        pl.camera_position = cpos\n    pl.camera.zoom(0.8)\n\n\npl = pv.Plotter(shape=(4, 4))\nadd_cell_helper(pl, f'VERTEX ({pv.CellType.VERTEX})', example_cells.Vertex(), (0, 0))\nadd_cell_helper(pl, f'POLY_VERTEX ({pv.CellType.POLY_VERTEX})', example_cells.PolyVertex(), (0, 1))\nadd_cell_helper(pl, f'LINE ({pv.CellType.LINE})', example_cells.Line(), (0, 2))\nadd_cell_helper(pl, f'POLY_LINE ({pv.CellType.POLY_LINE})', example_cells.PolyLine(), (0, 3))\n\nadd_cell_helper(\n    pl,\n    f'TRIANGLE ({pv.CellType.TRIANGLE})',\n    example_cells.Triangle(),\n    (1, 0),\n    cpos='xy',\n)\nadd_cell_helper(\n    pl,\n    f'TRIANGLE_STRIP ({pv.CellType.TRIANGLE_STRIP})',\n    example_cells.TriangleStrip().rotate_z(90, inplace=False),\n    (1, 1),\n    cpos='xy',\n)\nadd_cell_helper(pl, f'POLYGON ({pv.CellType.POLYGON})', example_cells.Polygon(), (1, 2), cpos='xy')\nadd_cell_helper(pl, f'PIXEL ({pv.CellType.PIXEL})', example_cells.Pixel(), (1, 3), cpos='xy')\n\n# make irregular\nquad_grid = example_cells.Quadrilateral()\nquad_grid.points += rng.random((4, 3)) * 0.5\n\nadd_cell_helper(pl, f'QUAD ({pv.CellType.QUAD})', quad_grid, (2, 0))\nadd_cell_helper(pl, f'TETRA ({pv.CellType.TETRA})', example_cells.Tetrahedron(), (2, 1))\nadd_cell_helper(pl, f'VOXEL ({pv.CellType.VOXEL})', example_cells.Voxel(), (2, 2))\n\n# make irregular\nhex_grid = example_cells.Hexahedron()\nhex_grid.points += rng.random((8, 3)) * 0.4\nadd_cell_helper(pl, f'HEXAHEDRON ({pv.CellType.HEXAHEDRON})', hex_grid, (2, 3))\n\nadd_cell_helper(pl, f'WEDGE ({pv.CellType.WEDGE})', example_cells.Wedge(), (3, 0))\nadd_cell_helper(pl, f'PYRAMID ({pv.CellType.PYRAMID})', example_cells.Pyramid(), (3, 1))\nadd_cell_helper(\n    pl,\n    f'PENTAGONAL_PRISM ({pv.CellType.PENTAGONAL_PRISM})',\n    example_cells.PentagonalPrism(),\n    (3, 2),\n)\nadd_cell_helper(\n    pl,\n    f'HEXAGONAL_PRISM ({pv.CellType.HEXAGONAL_PRISM})',\n    example_cells.HexagonalPrism(),\n    (3, 3),\n)\n\npl.background_color = 'w'\npl.show()"
      ]
    }
  ],
  "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
}