.. _filters.hag_delaunay:

filters.hag_delaunay
===============================================================================

The **Height Above Ground Delaunay filter** takes as input a point cloud with
``Classification`` set to 2 for ground points.  It creates a new dimension,
``HeightAboveGround``, that contains the normalized height values.

.. note::

   We expect ground returns to have the classification value of 2 in keeping
   with the `ASPRS Standard LIDAR Point Classes
   <http://www.asprs.org/a/society/committees/standards/LAS_1_4_r13.pdf>`_.

Ground points may be generated by :ref:`filters.pmf` or :ref:`filters.smrf`,
but you can use any method you choose, as long as the ground returns are
marked.

Normalized heights are a commonly used attribute of point cloud data. This can
also be referred to as *height above ground* (HAG) or *above ground level*
(AGL) heights. In the end, it is simply a measure of a point's relative height
as opposed to its raw elevation value.

The filter creates a delaunay triangulation of the `count`_ ground points
closest to the non-ground point in question.  If the non-ground point is within
the triangulated area, the assigned ``HeightAboveGround`` is the difference
between its ``Z`` value and a ground height interpolated from the three
vertices of the containing triangle.  If the non-ground point is outside of the
triangulated area, its ``HeightAboveGround`` is calculated as the difference
between its ``Z`` value and the ``Z`` value of the nearest ground point.

Choosing a value for `count`_ is difficult, as placing the non-ground point in
the triangulated area depends on the layout of the nearby points.  If, for
example, all the ground points near a non-ground point lay on one side of that
non-ground point, finding a containing triangle will fail.

.. embed::

Example #1
----------

Using the autzen dataset (here shown colored by elevation), which already has
points classified as ground

.. image:: ./images/autzen-elevation.png
   :height: 400px

we execute the following pipeline

.. code-block:: json

  [
      "autzen.laz",
      {
          "type":"filters.hag_delaunay"
      },
      {
          "type":"writers.laz",
          "filename":"autzen_hag_delaunay.laz",
          "extra_dims":"HeightAboveGround=float32"
      }
  ]

which is equivalent to the ``pdal translate`` command

::

    $ pdal translate autzen.laz autzen_hag_delaunay.laz hag_delaunay \
        --writers.las.extra_dims="HeightAboveGround=float32"

In either case, the result, when colored by the normalized height instead of
elevation is

.. image:: ./images/autzen-hag-delaunay.png
   :height: 400px

Options
-------------------------------------------------------------------------------

_`count`
    The number of ground neighbors to consider when determining the height
    above ground for a non-ground point.  [Default: 10]

allow_extrapolation
    If false and a non-ground point lies outside of the bounding box of
    all ground points, its ``HeightAboveGround`` is set to 0.  If true
    and ``delaunay`` is set, the ``HeightAboveGround`` is set to the
    difference between the heights of the non-ground point and nearest
    ground point.  [Default: false]

.. include:: filter_opts.rst

