Algorithm-GooglePolylineEncoding
view release on metacpan or search on metacpan
GooglePolylineEncoding.pm view on Meta::CPAN
$number &= 0xffffffff; # to assure 32 bit
# 5. If the original decimal value is negative, invert this encoding:
# 00000010 00100101 01000011 11100001
if ($is_negative) {
$number = (~$number);
$number &= 0xffffffff;
}
# 6. Break the binary value out into 5-bit chunks (starting from the right hand side):
# 00001 00010 01010 10000 11111 00001
my $bin = sprintf '%b', $number;
$bin = '0'x(5-length($bin)%5) . $bin if length($bin)%5 != 0; # pad
my @chunks;
my $revbin = reverse $bin;
push @chunks, scalar reverse($1) while $revbin =~ m{(.....)}g;
# 7. Place the 5-bit chunks into reverse order:
# 00001 11111 10000 01010 00010 00001
# It's already reversed
# 8. OR each value with 0x20 if another bit chunk follows:
# 100001 111111 110000 101010 100010 000001
@chunks = ((map { oct("0b$_") | 0x20 } @chunks[0 .. $#chunks-1]), oct("0b".$chunks[-1])); # and also decode to decimal on the fly
# 9. Convert each value to decimal:
GooglePolylineEncoding.pm view on Meta::CPAN
if ($number > ~0) {
# sprintf '%b' works only for integers
require Math::BigInt;
$bin = Math::BigInt->new($number)->as_bin;
$bin =~ s{^0b}{};
} else {
$bin = sprintf '%b', $number;
}
# 3. Break the binary value out into 5-bit chunks (starting from the right hand side):
# 101 01110
$bin = '0'x(5-length($bin)%5) . $bin if length($bin)%5 != 0; # pad
my @chunks;
my $revbin = reverse $bin;
push @chunks, scalar reverse($1) while $revbin =~ m{(.....)}g;
# 4. Place the 5-bit chunks into reverse order:
# 01110 101
# It's already reversed
# 5. OR each value with 0x20 if another bit chunk follows:
# 101110 00101
@chunks = ((map { oct("0b$_") | 0x20 } @chunks[0 .. $#chunks-1]), oct("0b".$chunks[-1])); # and also decode to decimal on the fly
# 6. Convert each value to decimal:
GooglePolylineEncoding.pm view on Meta::CPAN
@chunks = map { chr } @chunks;
join '', @chunks;
}
# Translated this php script
# <http://unitstep.net/blog/2008/08/02/decoding-google-maps-encoded-polylines-using-php/>
# to perl
sub decode_polyline {
my($encoded) = @_;
my $length = length $encoded;
my $index = 0;
my @points;
my $lat = 0;
my $lng = 0;
while ($index < $length) {
# The encoded polyline consists of a latitude value followed
# by a longitude value. They should always come in pairs. Read
# the latitude value first.
for my $val (\$lat, \$lng) {
my $shift = 0;
my $result = 0;
# Temporary variable to hold each ASCII byte.
my $b;
do {
# The `ord(substr($encoded, $index++))` statement returns
( run in 0.746 second using v1.01-cache-2.11-cpan-65fba6d93b7 )