NAME
    Geo::Google::PolylineEncoder - encode lat/lons to Google Maps Polylines

SYNOPSIS
      use Geo::Google::PolylineEncoder;

      my $points = [
                    # can also take points as [lat, lon]
                    { lat => 38.5, lon => -120.2 },
                    { lat => 40.7, lon => -120.95 },
                    { lat => 43.252, lon => -126.453 },
                   ];
      my $encoder = Geo::Google::PolylineEncoder->new;
      my $eline   = $encoder->encode( $points );
      print $eline->{num_levels};  # 18
      print $eline->{zoom_factor}; # 2
      print $eline->{points};      # _p~iF~ps|U_ulLnnqC_mqNvxq`@
      print $eline->{levels};      # POP

      # in Javascript, assuming eline was encoded as JSON:
      # ... load GMap2 ...
      var opts = {
        points: eline.points,
        levels: eline.levels,
        numLevels: eline.num_levels,
        zoomFactor: eline.zoom_factor,
      };
      var line = GPolyline.fromEncoded( opts );

DESCRIPTION
    This module encodes a list of lat/lon points representing a polyline
    into a format for use with Google Maps. This format is described here:

    <http://code.google.com/apis/maps/documentation/polylinealgorithm.html>

    The module is a port of Mark McClure's "PolylineEncoder.js" with some
    tweaks. The original can be found here:

    <http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/>

CONSTRUCTOR & ACCESSORS
    new( [%args] )
        Create a new encoder. Arguments are optional and correspond to the
        accessor with the same name: "num_levels", "zoom_factor",
        "visible_threshold", "force_endpoints", etc...

        Note: there's nothing stopping you from setting these properties
        each time you "encode" a polyline.

    num_levels
        How many different levels of magnification the polyline has.
        Default: 18.

    zoom_factor
        The change in magnification between those levels (see "num_levels").
        Default: 2.

    visible_threshold
        Indicates the length of a barely visible object at the highest zoom
        level. Default: 0.00001. err.. units.

    force_endpoints
        Indicates whether or not the endpoints should be visible at all zoom
        levels. force_endpoints is. Probably should stay true regardless.
        Default: 1=true.

    escape_encoded_points
        Indicates whether or not the encoded points should have escape
        characters escaped, eg:

          $points =~ s/\\/\\\\/g;

        This is useful if you'll be evalling the resulting strings, or
        copying them into a static document.

        Warning: don't turn this on if you'll be passing the encoded points
        straight on to your application, or you'll get unexpected results
        (ie: lines that start out right, but end up horribly wrong). It may
        even crash your browser.

        Default: 0=false.

    lons_first
        Specifies the order in which coordinates passed as arrayrefs to
        "encode" should be interpreted:

          # false: lat, lon
          $encoder->encode([
             [ 38.5, -120.2 ],
             [ 40.7, -120.95 ],
          ]);

          # true: lon, lat
          $encoder->encode([
             [ -120.2, 38.5 ],
             [ -120.95, 40.7 ],
          ]);

        Default: 0 = lat,lon

        (Yes, the default feels wrong to the mathematician in me, but that's
        how Google Maps do it, so for sake of consistency...)

METHODS
    encode( \@points );
        Encode the points into a string for use with Google Maps
        "GPolyline.fromEncoded" using a variant of the Douglas-Peucker
        algorithm to set levels, and the Polyline encoding algorithm defined
        by Google.

        Expects a reference to a @points array:

          [
           { lat => 38.5, lon => -120.2 },
           { lat => 40.7, lon => -120.95 },
           { lat => 43.252, lon => -126.453 },
          ];

        The individual points can also be given as arrayrefs:

          [
           [ 38.5, -120.2 ],
           [ 40.7, -120.95 ],
           [ 43.252, -126.453 ],
          ];

        *Note:* I tried to avoid this initially, because there's no standard
        for which should come first: *lat*s or *lon*s. But I agree, it's
        more convenient in some cases so I've given you enough rope to hang
        yourself... Of course you can easily unhang yourself: the order for
        arrayrefs defaults to "lat, lon", but you can change that by setting
        "lons_first".

        Returns a hashref containing:

          {
           points => 'encoded points string',
           levels => 'encoded levels string',
           num_levels => int($num_levels),
           zoom_factor => int($zoom_factor),
          };

        You can then use the JSON modules (or XML, or whatever) to pass the
        encoded values to your Javascript application for use there.

    decode_points( $encoded_polyline );
        Given an encoded polyline, returns the points:

          [
           { lat => 38.5, lon => -120.2 },
           { lat => 40.7, lon => -120.95 },
           { lat => 43.252, lon => -126.453 },
          ];

        Note that these will likely be slightly different from the original
        points due to rounding errors during both "encode" & decoding.

    decode_levels( $encoded_levels );
        Given encoded levels, returns the levels:

          [ 17, 16, 17 ]

WHY DO MY LINES LOOK FUNNY?
    Do your lines all go through the north pole? Maybe you have your *lon*s
    & *lat*s mixed up... If so and you're using point arrays, you can set
    "lons_first".

    Do your points not show up at particular zoom levels? That's not a bug,
    it's a feature! Try playing with "visible_threshold".

    Do your encoded lines cause your browser to crash? Sounds like a bug -
    file it!

BUGS
    <https://rt.cpan.org/Dist/Display.html?Queue=Geo-Google-PolylineEncoder>

TODO
    More optimization: encoding big files is *slow*. Maybe XS implementation
    if there's enough demand for it?

AUTHOR
    Steve Purkis <spurkis@cpan.org>

    Ported from Mark McClure's "PolylineEncoder.js" which can be found here:
    <http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/PolylineEnc
    oderClass.html>

    Some encoding ideas borrowed from Geo::Google.

    Bringing distance calcs in-line was Joel Rosenberg's idea:
    <http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/gmap_polyli
    ne_encoder.rb.txt>

COPYRIGHT
    Copyright (c) 2008-2010 Steve Purkis. Released under the same terms as
    Perl itself.

SEE ALSO
    <http://code.google.com/apis/maps/documentation/polylinealgorithm.html>,
    <http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/PolylineEnc
    oderClass.html> (JavaScript implementation),
    <http://www.usnaviguide.com/google-encode.htm> (similar implementation
    in perl), Geo::Google, JSON::Any