NAME
Geo::Google::PolylineEncoder - encode lat/lons to Google Maps Polylines
SYNOPSIS
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
);
$eline
->{num_levels};
# 18
$eline
->{zoom_factor};
# 2
$eline
->{points};
# _p~iF~ps|U_ulLnnqC_mqNvxq`@
$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: lats or lons. 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 lons & lats 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?
AUTHORS
Robert Rothenberg <rrwo@cpan.org>
Steve Purkis <spurkis@cpan.org>
Ported from Mark McClure's PolylineEncoder.js
which can be found here: http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/PolylineEncoderClass.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_polyline_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/PolylineEncoderClass.html (JavaScript implementation), http://www.usnaviguide.com/google-encode.htm (similar implementation in perl), Geo::Google, JSON::Any