{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Computing Surface Normals {#surface_normal_example}\n\nCompute normals on a surface.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import numpy as np\n\nfrom pyvista import examples"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Computing the normals of a surface is quite easy using\n`pyvista.PolyData`{.interpreted-text role=\"class\"}\\'s\n`pyvista.PolyDataFilters.compute_normals`{.interpreted-text role=\"func\"}\nmethod.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "mesh = examples.download_topo_global()\nmesh.plot(cmap=\"gist_earth\", show_scalar_bar=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Now we have a surface dataset of the globe loaded - unfortunately, the\ndataset shows the globe with a uniform radius which hides topographic\nrelief. Using\n`pyvista.PolyDataFilters.compute_normals`{.interpreted-text\nrole=\"func\"}, we can compute the normal vectors on the globe at all\npoints in the dataset, then use the values given in the dataset to warp\nthe surface in the normals direction to create some exaggerated\ntopographic relief.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Compute the normals in-place and use them to warp the globe\nmesh.compute_normals(inplace=True)  # this activates the normals as well\n\n# Now use those normals to warp the surface\nwarp = mesh.warp_by_scalar(factor=0.5e-5)\n\n# And let's see it\nwarp.plot(cmap=\"gist_earth\", show_scalar_bar=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We could also use face/cell normals to extract all the faces of a mesh\nfacing a general direction. In the following snippet, we take a mesh,\ncompute the normals along its cell faces, and extract the faces that\nface upward.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "mesh = examples.download_nefertiti()\n# Compute normals\nmesh.compute_normals(cell_normals=True, point_normals=False, inplace=True)\n\n# Get list of cell IDs that meet condition\nids = np.arange(mesh.n_cells)[mesh['Normals'][:, 2] > 0.0]\n\n# Extract those cells\ntop = mesh.extract_cells(ids)\n\ncpos = [\n    (-834.3184529757553, -918.4677714398535, 236.5468795300025),\n    (11.03829376004883, -13.642289291587957, -35.91218884207208),\n    (0.19212361465657216, 0.11401076390090074, 0.9747256344254143),\n]\n\ntop.plot(cpos=cpos, 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
}