{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Attenuation {#attenuation_example}\n\nAttenuation is the phenomenon of light\\'s intensity being gradually\ndampened as it propagates through a medium. In PyVista positional lights\ncan show attenuation. The quadratic attenuation model uses three\nparameters to describe attenuation: a constant, a linear and a quadratic\nparameter. These parameters describe the decrease of the beam intensity\nas a function of the distance, [I(r)]{.title-ref}. In a broad sense the\nconstant, linear and quadratic components correspond to [I(r) =\n1]{.title-ref}, [I(r) = 1/r]{.title-ref} and [I(r) = 1/r\\^2]{.title-ref}\ndecay of the intensity with distance from the point source. In all cases\na larger attenuation value (of a given kind) means stronger dampening\n(weaker light at a given distance).\n\nSo the constant attenuation parameter corresponds roughly to a constant\nintensity component. The linear and the quadratic attenuation parameters\ncorrespond to intensity components that decay with distance from the\nsource. For the same parameter value the quadratic attenuation produces\na beam that is shorter in range than that produced by linear\nattenuation.\n\nThree spotlights with three different attenuation profiles each:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import pyvista as pv\n\nplotter = pv.Plotter(lighting='none')\nbillboard = pv.Plane(direction=(1, 0, 0), i_size=6, j_size=6)\nplotter.add_mesh(billboard, color='white')\n\nall_attenuation_values = [(1, 0, 0), (0, 2, 0), (0, 0, 2)]\noffsets = [-2, 0, 2]\nfor attenuation_values, offset in zip(all_attenuation_values, offsets):\n    light = pv.Light(position=(0.1, offset, 2), focal_point=(0.1, offset, 1), color='cyan')\n    light.positional = True\n    light.cone_angle = 20\n    light.intensity = 15\n    light.attenuation_values = attenuation_values\n    plotter.add_light(light)\n\nplotter.view_yz()\nplotter.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "It\\'s not too obvious but it\\'s visible that the rightmost light with\nquadratic attenuation has a shorter range than the middle one with\nlinear attenuation. Although it seems that even the leftmost light with\nconstant attenuation loses its brightness gradually, this partly has to\ndo with the fact that we sliced the light beams very close to their\nrespective axes, meaning that light hits the surface in a very small\nangle. Altering the scene such that the lights are further away from the\nplane changes this:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "plotter = pv.Plotter(lighting='none')\nbillboard = pv.Plane(direction=(1, 0, 0), i_size=6, j_size=6)\nplotter.add_mesh(billboard, color='white')\n\nall_attenuation_values = [(1, 0, 0), (0, 2, 0), (0, 0, 2)]\noffsets = [-2, 0, 2]\nfor attenuation_values, offset in zip(all_attenuation_values, offsets):\n    light = pv.Light(position=(0.5, offset, 3), focal_point=(0.5, offset, 1), color='cyan')\n    light.positional = True\n    light.cone_angle = 20\n    light.intensity = 15\n    light.attenuation_values = attenuation_values\n    plotter.add_light(light)\n\nplotter.view_yz()\nplotter.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Now the relationship of the three kinds of attenuation seems clearer.\n\nFor a more practical comparison, let\\'s look at planes that are\nperpendicular to the axis of each light (making use of the fact that\nshadowing between objects is not handled by default):\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "plotter = pv.Plotter(lighting='none')\n\n# loop over three lights with three kinds of attenuation\nall_attenuation_values = [(2, 0, 0), (0, 2, 0), (0, 0, 2)]\nlight_offsets = [-6, 0, 6]\nfor attenuation_values, light_x in zip(all_attenuation_values, light_offsets):\n    # loop over three perpendicular planes for each light\n    for plane_y in [2, 5, 10]:\n        screen = pv.Plane(center=(light_x, plane_y, 0), direction=(0, 1, 0), i_size=5, j_size=5)\n        plotter.add_mesh(screen, color='white')\n\n    light = pv.Light(position=(light_x, 0, 0), focal_point=(light_x, 1, 0), color='cyan')\n    light.positional = True\n    light.cone_angle = 15\n    light.intensity = 5\n    light.attenuation_values = attenuation_values\n    light.show_actor()\n    plotter.add_light(light)\n\nplotter.view_vector((1, -2, 2))\nplotter.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
}