NAME
    Geo::H3::FFI - Perl FFI binding to H3 library functions

SYNOPSIS
      use Geo::H3::FFI;

DESCRIPTION
    Perl FFI binding to H3 library functions

CONSTRUCTORS
  new
      my $gh3 = Geo::H3::FFI->new;

  geo
    Returns a GeoCoord struct

      my $geo = $gh3->geo; #empty struct                 #isa Geo::H3::FFI::Struct::GeoCoord
      my $geo = $gh3->geo(lat=>$lat_rad, lon=>$lon_rad); #isa Geo::H3::FFI::Struct::GeoCoord

  gb
    Returns a GeoBoundary struct

      my $gb = $gh3->gb; #empty struct      #isa Geo::H3::FFI::Struct::GeoBoundary

Indexing Functions
    These function are used for finding the H3 index containing coordinates,
    and for finding the center and boundary of H3 indexes.

  geoToH3
    Indexes the location at the specified resolution, returning the index of
    the cell containing the location.

      my $geo        = $gh3->geo(lat=>$lat_rad, lon=>$lon_rad);   #isa Geo::H3::FFI::Struct::GeoCoord
      my $resolution = 8;                                         #isa Int in (0 .. 15)
      my $index      = $gh3->geoToH3($geo, $resolution);          #isa Int64

    Returns 0 on error.

  geoToH3Wrapper
      my $index = $gh3->geoToH3Wrapper(lat=>$lat_rad, lon=>$lon_rad, resolution=>$resolution);
      my $index = $gh3->geoToH3Wrapper(lat=>$lat,     lon=>$lon,     resolution=>$resolution, uom=>"deg");

  h3ToGeo
    Finds the centroid of the index.

      my $geo = $gh3->geo;          #isa Geo::H3::FFI::Struct::GeoCoord
      $gh3->h3ToGeo($index, $geo);
      my $lat = $geo->lat;          #isa Float in radians
      my $lon = $geo->lon;          #isa Float in radians

  h3ToGeoWrapper
      my $geo = h3ToGeoWrapper($index); #isa Geo::H3::FFI::Struct::GeoCoord
      my $lat = $geo->lat;          #isa Float in radians
      my $lon = $geo->lon;          #isa Float in radians

  h3ToGeoBoundary
    Finds the boundary of the index.

      my $gb        = $gh3->gb;           #isa empty Geo::H3::FFI::Struct::GeoBoundary
      $gh3->h3ToGeoBoundary($index, $gb); #populates $gb
      my $num_verts = $gb->num_verts;     #isa Int
      my $vert0     = $gb->verts->[0];    #isa Geo::H3::FFI::Struct::GeoCord

  h3ToGeoBoundaryWrapper
      my $GeoBoundary = $gh3->h3ToGeoBoundaryWrapper($index); #isa Geo::H3::FFI::Struct::GeoBoundary

Index Inspection Functions
    These functions provide metadata about an H3 index, such as its
    resolution or base cell, and provide utilities for converting into and
    out of the 64-bit representation of an H3 index.

  h3GetResolution
    Returns the resolution of the index.

      my $resolution = $gh3->h3GetResolution($index); #isa Int

  h3GetBaseCell
    Returns the base cell number of the index.

      my $baseCell = h3GetBaseCell($index);

  stringToH3
    Converts the string representation to H3Index (uint64_t) representation.

    Returns 0 on error.

      my $index  = $gh3->stringToH3($string, length($string));

  stringToH3Wrapper
      my $index = $gh3->stringToH3Wrapper($string);

  h3ToString
    Converts the H3Index representation of the index to the string
    representation. str must be at least of length 17.

      my $size   = 17; #Must be 17 for API to work
      my $string = "\000" x $size;
      $gh3->h3ToString($index, $string, $size);
      $string    =~ s/\000+\Z//;

  h3ToStringWrapper
      my $string = $gh3->h3ToStringWrapper($index);

  h3IsValid
    Returns non-zero if this is a valid H3 index.

      my isValid = $gh3->h3IsValid($index);

  h3IsResClassIII
    Returns non-zero if this index has a resolution with Class III
    orientation.

      my $isRC3 = $gh3->h3IsResClassIII($index);

  h3IsPentagon
    Returns non-zero if this index represents a pentagonal cell.

      my $isPentagon = $gh3->h3IsPentagon($index);

  h3GetFaces
    Find all icosahedron faces intersected by a given H3 index and places
    them in the array out. out must be at least of length maxFaceCount(h).

    Faces are represented as integers from 0-19, inclusive. The array is
    sparse, and empty (no intersection) array values are represented by -1.

      my @array = (-1,-1,-1,-1,-1);
      $gh3->h3GetFaces($index, \@array); #sets values into initialized array

  h3GetFacesWrapper
      my $array_ref = $gh3->h3GetFacesWrapper($index);

  maxFaceCount
    Returns the maximum number of icosahedron faces the given H3 index may
    intersect.

      my $count = $gh3->maxFaceCount($index);

Grid traversal functions
    Grid traversal allows finding cells in the vicinity of an origin cell,
    and determining how to traverse the grid from one cell to another.

  kRing
    k-rings produces indices within k distance of the origin index.

    k-ring 0 is defined as the origin index, k-ring 1 is defined as k-ring 0
    and all neighboring indices, and so on.

    Output is placed in the provided array in no particular order. Elements
    of the output array may be left zero, as can happen when crossing a
    pentagon.

      my $size  = $gh3->maxKringSize($k);
      my @array = (-1) x $size;
      $self->kRing($index, $k, \@array);

  kRingWrapper
    Returns an array reference of H3 indices with the k distance of the
    origin index.

      my $aref = $gh3->kRingWrapper($index, $k); #ias ARRAY of H3 Indexes

  maxKringSize
    Maximum number of indices that result from the kRing algorithm with the
    given k.

      my $size  = $gh3->maxKringSize($k);

  kRingDistances
    k-rings produces indices within k distance of the origin index.

    k-ring 0 is defined as the origin index, k-ring 1 is defined as k-ring 0
    and all neighboring indices, and so on.

    Output is placed in the provided array in no particular order. Elements
    of the output array may be left zero, as can happen when crossing a
    pentagon.

      my $size  = $gh3->maxKringSize($k);
      my @array = (-1) x $size;
      my @dist  = (-1) x $size;
      my %hash  = ();
      $gh3->kRingDistances($index, $k, \@array, \@dist);

  kRingDistancesWrapper
    Returns a hash reference where the keys are the H3 index and values are
    the k distance for the given index and k value.

      my $href = $gh3->kRingDistancesWrapper($index, $k); #isa HASH

  hexRange
    hexRange produces indexes within k distance of the origin index. Output
    behavior is undefined when one of the indexes returned by this function
    is a pentagon or is in the pentagon distortion area.

    k-ring 0 is defined as the origin index, k-ring 1 is defined as k-ring 0
    and all neighboring indexes, and so on.

    Output is placed in the provided array in order of increasing distance
    from the origin.

    Returns 0 if no pentagonal distortion is encountered.

      my $return = $gh3->hexRange($index, $k, \@out);

  hexRangeWrapper
      my @indexes = $gh3->hexRangeWrapper($index, $k);

  maxHexRangeSize
      my $size = $gh3->maxHexRangeSize($k);

  hexRangeDistances
    hexRange produces indexes within k distance of the origin index. Output
    behavior is undefined when one of the indexes returned by this function
    is a pentagon or is in the pentagon distortion area.

    k-ring 0 is defined as the origin index, k-ring 1 is defined as k-ring 0
    and all neighboring indexes, and so on.

    Output is placed in the provided array in order of increasing distance
    from the origin. The distances in hexagons is placed in the distances
    array at the same offset.

    Returns 0 if no pentagonal distortion is encountered.

      my $return = $gh3->hexRangeDistances($index, $k, \@indexes, \@distances);

  hexRanges
    hexRanges takes an array of input hex IDs and a max k-ring and returns
    an array of hexagon IDs sorted first by the original hex IDs and then by
    the k-ring (0 to max), with no guaranteed sorting within each k-ring
    group.

    Returns 0 if no pentagonal distortion was encountered. Otherwise, output
    is undefined

  hexRing
    Produces the hollow hexagonal ring centered at origin with sides of
    length k.

    Returns 0 if no pentagonal distortion was encountered.

      my $distortion = $gh3->hexRing($index, $k, \@ring);

  hexRingWrapper
      my $aref = $gh3->hexRingWrapper($index, $k);

  maxHexRingSize
      my $size = $gh3->maxHexRingSize($k);

  h3Line
    Given two H3 indexes, return the line of indexes between them
    (inclusive).

    This function may fail to find the line between two indexes, for example
    if they are very far apart. It may also fail when finding distances for
    indexes on opposite sides of a pentagon.

    Notes:

     - The specific output of this function should not be considered stable across library versions. The only guarantees the library provides are that the line length will be h3Distance(start, end) + 1 and that every index in the line will be a neighbor of the preceding index.

     - Lines are drawn in grid space, and may not correspond exactly to either Cartesian lines or great arcs.

  h3LineWrapper
      my $aref = $gh3->h3LineWrapper($start, $end);

  h3LineSize
    Number of indexes in a line from the start index to the end index, to be
    used for allocating memory. Returns a negative number if the line cannot
    be computed.

  h3Distance
    Returns the distance in grid cells between the two indexes.

    Returns a negative number if finding the distance failed. Finding the
    distance can fail because the two indexes are not comparable (different
    resolutions), too far apart, or are separated by pentagonal distortion.
    This is the same set of limitations as the local IJ coordinate space
    functions.

  experimentalH3ToLocalIj
    Produces local IJ coordinates for an H3 index anchored by an origin.

    This function is experimental, and its output is not guaranteed to be
    compatible across different versions of H3.

  experimentalLocalIjToH3
    Produces an H3 index from local IJ coordinates anchored by an origin.

    This function is experimental, and its output is not guaranteed to be
    compatible across different versions of H3.

Hierarchical grid functions
    These functions permit moving between resolutions in the H3 grid system.
    The functions produce parent (coarser) or children (finer) cells.

  h3ToParent
    Returns the parent (coarser) index containing h.

      my $parent = $gh3->h3ToParent($index, $resolution);

  h3ToChildren
    Populates children with the indexes contained by h at resolution
    childRes. children must be an array of at least size
    maxH3ToChildrenSize(h, childRes).

      my $size  = $gh3->maxH3ToChildrenSize($index, $res);
      my @array = (-1) x $size;
      $gh3->h3ToChildren($index, $res, \@array);

  h3ToChildrenWrapper
      my $aref = $gh3->h3ToChildrenWrapper($index, $resoultion);

  maxH3ToChildrenSize
      my $size  = $gh3->maxH3ToChildrenSize($index, $res);

  h3ToCenterChild
    Returns the center child (finer) index contained by h at resolution
    childRes.

  compact
    Compacts the set h3Set of indexes as best as possible, into the array
    compactedSet. compactedSet must be at least the size of h3Set in case
    the set cannot be compacted.

    Returns 0 on success.

  compactWrapper
      my $aref = $gh3->compactWrapper(\@indexes);

  uncompact
    Uncompacts the set compactedSet of indexes to the resolution res. h3Set
    must be at least of size maxUncompactSize(compactedSet, numHexes, res).

    Returns 0 on success.

  maxUncompactSize
    Returns the size of the array needed by uncompact.

Region functions
    These functions convert H3 indexes to and from polygonal areas.

  polyfill
    polyfill takes a given GeoJSON-like data structure and preallocated,
    zeroed memory, and fills it with the hexagons that are contained by the
    GeoJSON-like data structure.

    Containment is determined by the cells' centroids. A partioning using
    the GeoJSON-like data structure, where polygons cover an area without
    overlap, will result in a partitioning in the H3 grid, where cells cover
    the same area without overlap.

  maxPolyfillSize
    maxPolyfillSize returns the number of hexagons to allocate space for
    when performing a polyfill on the given GeoJSON-like data structure.

  h3SetToLinkedGeo
    Create a LinkedGeoPolygon describing the outline(s) of a set of
    hexagons. Polygon outlines will follow GeoJSON MultiPolygon order: Each
    polygon will have one outer loop, which is first in the list, followed
    by any holes.

    It is the responsibility of the caller to call destroyLinkedPolygon on
    the populated linked geo structure, or the memory for that structure
    will not be freed.

    It is expected that all hexagons in the set have the same resolution and
    that the set contains no duplicates. Behavior is undefined if duplicates
    or multiple resolutions are present, and the algorithm may produce
    unexpected or invalid output.

  h3SetToMultiPolygon
  destroyLinkedPolygon
    Free all allocated memory for a linked geo structure. The caller is
    responsible for freeing memory allocated to the input polygon struct.

Unidirectional edge functions
    Unidirectional edges allow encoding the directed edge from one cell to a
    neighboring cell.

  h3IndexesAreNeighbors
    Returns whether or not the provided H3Indexes are neighbors.

    Returns 1 if the indexes are neighbors, 0 otherwise.

  getH3UnidirectionalEdge
    Returns a unidirectional edge H3 index based on the provided origin and
    destination.

    Returns 0 on error.

  h3UnidirectionalEdgeIsValid
    Determines if the provided H3Index is a valid unidirectional edge index.

    Returns 1 if it is a unidirectional edge H3Index, otherwise 0.

  getOriginH3IndexFromUnidirectionalEdge
    Returns the origin hexagon from the unidirectional edge H3Index.

  getDestinationH3IndexFromUnidirectionalEdge
    Returns the destination hexagon from the unidirectional edge H3Index.

  getH3IndexesFromUnidirectionalEdge
    Returns the origin, destination pair of hexagon IDs for the given edge
    ID, which are placed at originDestination[0] and originDestination[1]
    respectively.

  getH3UnidirectionalEdgesFromHexagon
    Provides all of the unidirectional edges from the current H3Index. edges
    must be of length 6, and the number of undirectional edges placed in the
    array may be less than 6.

  getH3UnidirectionalEdgeBoundary
    Provides the coordinates defining the unidirectional edge.

Miscellaneous H3 functions
    These functions include descriptions of the H3 grid system.

  degsToRads
    Converts degrees to radians.

  radsToDegs
    Converts radians to degrees.

  hexAreaKm2
    Average hexagon area in square kilometers at the given resolution.

  hexAreaM2
    Average hexagon area in square meters at the given resolution.

  cellAreaM2
    Exact area of specific cell in square meters.

  cellAreaRads2
    Exact area of specific cell in square radians.

  edgeLengthKm
    Average hexagon edge length in kilometers at the given resolution.

  edgeLengthM
    Average hexagon edge length in meters at the given resolution.

  exactEdgeLengthKm
    Exact edge length of specific unidirectional edge in kilometers.

  exactEdgeLengthM
    Exact edge length of specific unidirectional edge in meters.

  exactEdgeLengthRads
    Exact edge length of specific unidirectional edge in radians.

  numHexagons
    Number of unique H3 indexes at the given resolution.

  getRes0Indexes
    All the resolution 0 H3 indexes. out must be an array of at least size
    res0IndexCount().

  res0IndexCount
    Number of resolution 0 H3 indexes.

  getPentagonIndexes
    All the pentagon H3 indexes at the specified resolution. out must be an
    array of at least size pentagonIndexCount().

  pentagonIndexCount
    Number of pentagon H3 indexes per resolution. This is always 12, but
    provided as a convenience.

  pointDistKm
    Gives the "great circle" or "haversine" distance between pairs of
    GeoCoord points (lat/lon pairs) in kilometers.

  pointDistM
    Gives the "great circle" or "haversine" distance between pairs of
    GeoCoord points (lat/lon pairs) in meters.

  pointDistRads
    Gives the "great circle" or "haversine" distance between pairs of
    GeoCoord points (lat/lon pairs) in radians.

SEE ALSO
    <https://h3geo.org/docs/api/indexing>,
    <https://h3geo.org/docs/community/bindings>, FFI::CheckLib,
    FFI::Platypus, FFI::C

AUTHOR
    Michael R. Davis

COPYRIGHT AND LICENSE
    MIT License

    Copyright (c) 2020 Michael R. Davis

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the
    "Software"), to deal in the Software without restriction, including
    without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to
    the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

