package Geo::Coder::Many::Googlev3; use strict; use warnings; use Carp; use Geo::Coder::Many::Util; use base 'Geo::Coder::Many::Generic'; =head1 NAME Geo::Coder::Many::Googlev3 - Plugin for version 3 of the google maps geocoder =head1 VERSION Version 0.02 =cut our $VERSION = '0.02'; # Requires Geo::Coder::Googlev3 0.07 or above sub _MIN_MODULE_VERSION { return '0.07'; } =head1 SYNOPSIS This class wraps Geo::Coder::Googlev3 such that it can be used in Geo::Coder::Many, by converting the results to a standard form. Note: this module supports v3 of the Google geocoder. There is also Geo::Coder::Google (also supported by Geo::Coder::Many) which supports the older version 2. =head1 METHODS =head2 geocode Takes a location string, geocodes it using Geo::Coder::Googlev3, and returns the result in a form understandable to Geo::Coder::Many =cut # see details of Google's response format here: # v3: http://code.google.com/apis/maps/documentation/geocoding/ sub geocode { my $self = shift; my $location = shift; defined $location or croak "Geo::Coder::Many::Googlev3::geocode method must be given a location."; my $raw = $self->{GeoCoder}->geocode( location => $location, raw => 1, ); # was there a response if (!defined($raw)){ carp "no response from googlev3 when requesting $location"; return; } # was response any good? if ($raw->{status} ne 'OK'){ # carp $raw->{status} . " when requesting $location"; return; } my $Response = Geo::Coder::Many::Response->new({ location => $location}); foreach my $raw_reply ( @{$raw->{results}} ){ my $precision = 0; # unknown if (defined($raw_reply->{geometry}) && defined($raw_reply->{geometry}{viewport}) ){ my $box = $raw_reply->{geometry}{viewport}; # lng and lat in decimal degree format $precision = Geo::Coder::Many::Util::determine_precision_from_bbox({ 'lon1' => $box->{southwest}{lng}, 'lat1' => $box->{southwest}{lat}, 'lon2' => $box->{northeast}{lng}, 'lat2' => $box->{northeast}{lat}, }); } # which country? # need to scan the address components my $country = undef; foreach my $rh_address_component (@{$raw_reply->{address_components}}){ my $ra_types = $rh_address_component->{types}; my $p = 0; my $c = 0; foreach my $x (@$ra_types){ $p = 1 if ($x eq 'political'); $c = 1 if ($x eq 'country'); if ($c && $p){ $country = $rh_address_component->{long_name}; } } } my $tmp = { address => $raw_reply->{formatted_address}, country => $country, latitude => $raw_reply->{geometry}{location}{lat}, longitude => $raw_reply->{geometry}{location}{lng}, precision => $precision, }; $Response->add_response( $tmp, $self->get_name()); } return $Response; } =head2 get_name The short name by which Geo::Coder::Many can refer to this geocoder. =cut sub get_name { my $self = shift; return 'googlev3 ' . $self->{GeoCoder}->VERSION; } 1;