package Geo::Google::Path; use strict; use warnings; use Data::Dumper; use URI::Escape; use Geo::Google; our $VERSION = '0.04-rc3'; use constant FMT => <<_FMT_; %s _FMT_ # # Head southwest from Venice Blvd # Make a U-turn at Venice Blvd # sub new { my $class = shift; my %arg = @_; my $self = bless \%arg, $class; } sub distance { return shift->{'distance'} } sub polyline { return shift->{'polyline'} } sub segments { my $self = shift; return $self->{'segments'} ? @{ $self->{'segments'} } : () } sub time { return shift->{'time'} } sub locations { my $self = shift; return $self->{'locations'} ? @{ $self->{'locations'} } : () } sub panel { return shift->{'panel'} } sub levels { return shift->{'levels'} } sub toXML { my $self = shift; my $content = join "", map { $_->toXML } @{ $self->{segments} }; return sprintf( FMT, $self->distance(), $self->time(), $content, ); } sub toJSON { my $self = shift; my $json = new JSON (barekey => 1); # Construct the shell of a new perl data structure that we # can pass off to the JSON module for rendering to a string my $preJSON = Geo::Google::_JSONrenderSkeleton(); # Fill the perl data structure with information from this # location my @locations = $self->locations(); $preJSON->{"form"}->{"l"}->{"near"} = $locations[$#locations]->title(); $preJSON->{"form"}->{"q"}->{"q"} = "from:" . $locations[0]->title(); for (my $i=1; $i<=$#locations; $i++) { $preJSON->{"form"}->{"q"}->{"q"} .= " to:" . $locations[$i]->title(); } $preJSON->{"form"}->{"d"}->{"saddr"} = $locations[0]->title(); $preJSON->{"form"}->{"d"}->{"daddr"} = $locations[1]->title(); for (my $i=2; $i<=$#locations; $i++) { $preJSON->{"form"}->{"d"}->{"daddr"} .= " to:" . $locations[$i]->title(); } $preJSON->{"form"}->{"selected"} = "q"; $preJSON->{"panelStyle"} = ""; # Generate the markers for (my $i=0; $i<=$#locations; $i++) { my $image = "/mapfiles/dd-pause.png"; my $id = "pause"; if ($i == 0 ) { $image = "/mapfiles/dd-start.png"; $id = "start"; } elsif ($i == $#locations) { $image = "/mapfiles/dd-stop.png"; $id = "stop"; } push( @{$preJSON->{"overlays"}->{"markers"}}, { "laddr" => "", "svaddr" => "", "lat" => $locations[$i]->latitude(), "lng" => $locations[$i]->longitude(), "id" => $id, "image" => $image, "elms" => [()], "llcid" => "", "fid" => "", "cid" => "", "sig" => "", "infoWindow" => { "type" => "map", "_" => 0 } }); } $preJSON->{"overlays"}->{"polylines"}->[0]->{"levels"} = $self->levels(); $preJSON->{"overlays"}->{"polylines"}->[0]->{"points"} = $self->polyline(); $preJSON->{"overlays"}->{"polylines"}->[0]->{"outline"} = undef; $preJSON->{"overlays"}->{"polylines"}->[0]->{"opacity"} = undef; $preJSON->{"overlays"}->{"polylines"}->[0]->{"color"} = undef; $preJSON->{"overlays"}->{"polylines"}->[0]->{"weight"} = undef; $preJSON->{"overlays"}->{"polylines"}->[0]->{"id"} = "d"; $preJSON->{"overlays"}->{"polylines"}->[0]->{"numLevels"} = 4; $preJSON->{"overlays"}->{"polylines"}->[0]->{"zoomFactor"} = 16; $preJSON->{"printheader"} = sprintf("Directions from %s to %s" . "
Travel time: %s", $locations[0]->title(), $locations[$#locations]->title(), $self->time()); $preJSON->{"modules"} = [(undef, "multiroute")]; $preJSON->{"panelResizeState"} = "open"; # step through all points in the directions and determine # the maximum and minimum lat/longs my $maxlat = -90; my $minlat = 90; my $maxlng = -180; my $minlng = 180; foreach my $segment ($self->segments()) { foreach my $point ($segment->points()) { if ($point->latitude() > $maxlat) { $maxlat = $point->latitude(); } if ($point->latitude() < $minlat) { $minlat = $point->latitude(); } if ($point->longitude() > $maxlng) { $maxlng = $point->longitude(); } if ($point->longitude() < $minlng) { $minlng = $point->longitude(); } } } $preJSON->{"viewport"}->{"span"}->{"lat"} = sprintf("%.6f", ( ($maxlat-$minlat) * 1.1) ); $preJSON->{"viewport"}->{"span"}->{"lng"} = sprintf("%.6f", ( ($maxlng-$minlng) * 1.1) ); $preJSON->{"viewport"}->{"center"}->{"lat"} = sprintf("%.6f", ( ($maxlat+$minlat) / 2) ); $preJSON->{"viewport"}->{"center"}->{"lng"} = sprintf("%.6f", ( ($maxlng+$minlng) / 2) ); $preJSON->{"viewport"}->{"mapType"} = undef; $preJSON->{"url"} = "/maps?v=1&q=" . uri_escape(sprintf("from:%s to:%s", $locations[0]->title(), $preJSON->{"form"}->{"d"}->{"daddr"})) . "&ie=UTF8"; $preJSON->{"title"} = sprintf("From:%s to:%s", $locations[0]->title(), $preJSON->{"form"}->{"d"}->{"daddr"}); $preJSON->{"panel"} = $self->panel(); # Render the data structure to a JSON string and return it return $json->objToJson($preJSON); } 1; __END__ Below is stub documentation for your module. You'd better edit it! =head1 NAME Geo::Google::Path - A path, by automobile, between two loci. =head1 SYNOPSIS use Geo::Google::Path; # you shouldn't need to construct these yourself, # have a Geo::Google object do it for you. =head1 DESCRIPTION Google Maps is able to serve up directions between two points. Directions consist of two types of components: 1. a series of points along a "polyline". 2. a series of annotations, each of which applies to a contiguous range of points. In the Geo::Google object model, directions are available by calling path() on a Geo::Google instance. The return value is a Geo::Google::Path object, which is a composite of Geo::Google::Segment objects, which are in turn composites of Geo::Google::Location objects. =head1 OBJECT METHODS Geo::Google::Path objects provide the following accessor methods Method Description ------ ----------- distance length of the segment, in variable, human friendly units. polyline a string encoding the points in the path. levels a string containing information used for rendering the polyline in an application like Google Maps. panel HTML+JavaScript version of the driving directions for use in an AJAX application. Google Maps uses this data in the left hand panel of a directions search. segments a list of Geo::Google::Segment segments along the path. a segment has 0..1 driving directions associated with it. time a time estimate, in variable, human-friendly units for how long the segment will take to travel by automobile. locations an array of Geo::Google::Location objects containing the start point (element 0 of the array), the final destination (the last element of the array), and any waypoints between them that were used in the directions query. There will always be at least two elements in this array (start point and final destination). toXML a method that renders the path in XML that could be used as part of a Google Earth KML file. toJSON a method that renders the path in JSON that could be used with Google Maps. =head1 SEE ALSO L =head1 AUTHOR Allen Day Eallenday@ucla.eduE, Michael Trowbridge Emichael.a.trowbridge@gmail.comE =head1 COPYRIGHT AND LICENSE Copyright (c) 2004-2007 Allen Day. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut