=head1 NAME

Geo::Geos::Algorithm - Fundamental computational geometry algorithms.

=head1 SYNOPSIS

    # imports constants: TYPE_TURN_CLOCKWISE, TYPE_TURN_COLLINEAR, TYPE_TURN_COUNTERCLOCKWISE
    # TYPE_ORIENT_RIGHT, TYPE_ORIENT_LEFT, TYPE_ORIENT_STRAIGHT
    use Geo::Geos::Algorithm;

    use Geo::Geos::Algorithm qw/toRadians toDegrees angle isAcute isObtuse angleBetween getTurn
                           angleBetweenOriented interiorAngle normalize normalizePositive diff
                           centroid centroidArea centroidLine centroidPoint/;
    use Geo::Geos::Algorithm qw/isPointInRing locatePointInRing isOnLine isCCW computeOrientation
                           orientationIndex distancePointLine distancePointLinePerpendicular
                           distanceLineLine signedArea getIntersection convexHull
                           interiorPointArea interiorPointLine interiorPointPoint
                           locate intersects signOfDet2x2
                           locateIndexedPointInArea locateSimplePointInArea/;

    use Geo::Geos::Coordinate;
    use Geo::Geos::GeometryFactory;

    # Angle
    my $c01 = Geo::Geos::Coordinate->new(0,2);
    my $c02 = Geo::Geos::Coordinate->new(0,0);
    my $c03 = Geo::Geos::Coordinate->new(1,1);

    toDegrees(toRadians(90));                      # => 90
    angle(Geo::Geos::Coordinate->new(1,0));        # => 0
    isAcute($c01, $c02, $c03);                     # => success
    isObtuse($c01, $c02, $c03);                    # => ''

    my $a1 = angleBetween($c01, $c02, $c03);
    toDegrees($a1);                                # => 45

    my $a2 = angleBetweenOriented($c01, $c02, $c03);
    toDegrees($a2);                                # => -45

    my $a3 = interiorAngle($c01, $c02, $c03);
    toDegrees($a3);                                # => 45

    my $a4 = normalize(toRadians(90) * 3);
    toDegrees($a4);                                # => -90

    my $a5 = normalizePositive(toRadians(90) * 3);
    toDegrees($a5);                                # => 270

    my $a6 = diff($a2, $a3);
    toDegrees($a6);                                # => 90

    getTurn($a1, $a2);                             # => TYPE_TURN_CLOCKWISE;


    # Computational Geometric algorithms.
    my $c1 = Geo::Geos::Coordinate->new(1,2);
    my $c2 = Geo::Geos::Coordinate->new(5,2);
    my $c3 = Geo::Geos::Coordinate->new(5,0);
    my $c4 = Geo::Geos::Coordinate->new(1,0);

    my $coords_ring = [$c1, $c2, $c3, $c4, $c1];

    isPointInRing($c1, $coords_ring);      # => success
    locatePointInRing($c1, $coords_ring);  # => is 1
    isOnLine($c3, [$c1, $c2]);             # => ''
    isCCW($coords_ring);                   # => ''
    computeOrientation($c1, $c2, $c3);     # => TYPE_TURN_CLOCKWISE
    orientationIndex($c1, $c2, $c3);       # => TYPE_TURN_CLOCKWISE

    distancePointLine($c3, $c1, $c2);                  # => 2
    distancePointLinePerpendicular($c3, $c1, $c2);     # => 2
    distanceLineLine($c1, $c2, $c3, $c4);              # => 2

    signedArea($coords_ring);                           # => 8
    Geo::Geos::Algorithm::length([$c1, $c2, $c3, $c4]);      # => 8

    # CentralEndpointIntersector
    getIntersection($c1, $c2, $c3, $c4); # => isa 'Geo::Geos::Coordinate'

    # ConvexHull
    my $gf = Geo::Geos::GeometryFactory::create();
    my $lr = $gf->createLinearRing($coords_ring, 2);
    convexHull($lr);  # => isa 'Geo::Geos::Geometry'

    # InteriorPoint
    my $p = $gf->createPolygon($lr);
    interiorPointArea($p);     # => isa 'Geo::Geos::Coordinate'

    my $ls = $gf->createLineString([$c1, $c2], 2);
    interiorPointLine($ls);    # => isa 'Geo::Geos::Coordinate'

    my $point = $gf->createPoint($c2);
    interiorPointPoint($point);    # => isa 'Geo::Geos::Coordinate'

    # PointLocator
    locate($c2, $lr);      # => is 0
    intersects($c1, $lr);  # => success

    # RobustDeterminant
    signOfDet2x2(1,2,3,4);     # => -1

    # Locate
    locateIndexedPointInArea($c2, $p);     # => 1;
    locateSimplePointInArea($c2, $p);      # => 0;

=head1 EXPORTS CONSTANTS

=over 2

=item TYPE_TURN_CLOCKWISE

=item TYPE_TURN_COLLINEAR

=item TYPE_TURN_COUNTERCLOCKWISE

=item TYPE_ORIENT_RIGHT

=item TYPE_ORIENT_LEFT

=item TYPE_ORIENT_STRAIGHT

=back


=head1 SEE ALSO (C++ classes docs)

L<GEOS C++ Library|https://trac.osgeo.org/geos>

geos::algorithm::Angle

geos::algorithm::Centroid

geos::algorithm::CentroidArea

geos::algorithm::CentroidLine

geos::algorithm::CentroidPoint

geos::algorithm::CGAlgorithms

geos::algorithm::CentralEndpointIntersector

geos::algorithm::ConvexHull

geos::algorithm::InteriorPointArea

geos::algorithm::InteriorPointLine

geos::algorithm::InteriorPointPoint

geos::algorithm::PointLocator

geos::algorithm::RobustDeterminant

geos::algorithm::locate::IndexedPointInAreaLocator

geos::algorithm::locate::SimplePointInAreaLocator

=head1 SEE ALSO

L<Geo::Geos>

L<Geo::Geos::Algorithm::HCoordinate>

L<Geo::Geos::Algorithm::LineIntersector>

L<Geo::Geos::Algorithm::MinimumDiameter>

L<Geo::Geos::Coordinate>

=head1 AUTHOR

Ivan Baidakou <i.baydakov@crazypanda.ru>, Crazy Panda, CP Decision LTD

=head1 LICENSE

You may distribute this code under the same terms as Perl itself.

=cut
