We definitely think that maps are the today’s cooler topic, as told in another post (Play with Google maps and Twitter api), and Google Maps API exposes so many functionalities so that I and Alberto Mancini decided to explore deeper some related features via a little toy (Hello Kitty Lost in Milan), which can be downloaded here. When you open the application, what you see is Hello Kitty that has lost the way and comes around looking for the way to home and asking you to click on the map in order to show the right destination.
How it works
Hello Kitty is lost in Milan and is waiting that someone clicks on the map to suggest the home position. In the while Hello Kitty randomly turns around its initial position, catching some gift whose position is randomly chosen to let the character to move around the map. The virtually infinite loop is started in the initialize function (triggered by the body’s onLoad event) that, calling the loadFromWaypoints method of a GDriections object, finds the first position of Kitty and then a callback function on the load event of GDirections lets the animation to proceed (recursively) from a random point to another until the user do selects a home-point on the map. This simple example shows a couple of interesting steps:
1. How to find a path between two points using GDirections.
2. How to use inverse geocoding with GClientGeocoder.
Finding the path
The construction of the path from the actual position of Kitty to the gift position is realized using the GDirections object which can be used to retrieve directions using either a query strings (i.e. addresses) or a couple of coordinates. In the sample to retrieve the path we use GDirections’s method:
loadFromWaypoints(waypoints:Array, queryOpts?:GDirectionsOptions)that supports multi-point directions in spite of the more common:
load(query:String, queryOpts?:GDirectionsOptions)being the latter most suited for human readable query strings than to programmatically generated queries as in the sample.
loadFromWaypoints method takes an array of textual input addresses or textual lat/lon points; each separate waypoint is computed as a separate route and returned in a separate GRoute object, each of which contains a series of GStep objects. We use loadFromWaypoints in two variants for different purposes:
1. to get a position “admissible” for a given (randomly chosen) point as:
dirn.loadFromWaypoints([point.toUrlValue(6), point.toUrlValue(6)],
{getPolyline:true ...}); i.e. specifying twice the same point and then using the first point in the returned polyline to place the marker.
2. to get a path between two points (the caracter at point p0 and the ‘gift’ at point p1) as:
dirn.loadFromWaypoints([p0.toUrlValue(6),p1.toUrlValue(6)],
{getPolyline:true,getSteps:true,travelMode:G_TRAVEL_MODE_WALKING});that loads the path between the points specified in the first argument; between the others, we specified the travelMode as G_TRAVEL_MODE_WALKING (Kitty has no car;).
Let us note that this is possible if the GDirections constructor is called specifying a <div> container that will hold the textual directions associated with the result (and required to display a warning message to the user when walking directions are in use; the container actually has a display:none;style in the sample code):
var dirn = new GDirections(null,document.getElementById("route"));where we pass “null” as first argument to avoid the automatic creation of an overlay over the map showing the route. When the function is called, the GDirections object fires three events that can be catched:
1. load
2. add overlay
3. error
In our example we’re mainly interested on the “load event” that, with the help of a global variable, manages all the phases of the game:
1. initial walk
2. random walk towards the gift
3. walk to home
and relative transitions and computations. Most notably when a gift is reached (or at the beginning actually) a new gift position should be computed randomly on the visible map and approximated to the nearest street (using loadFromWayPoints) and if the user clicked somewhere on the map the home position should be retrieved and the path-to-home followed. Once the position of a gift is known (or the position of the home, it is irrilevant here), the call to the loadFromWaypoints method give us the polyline to reach the target and the animate function can proceed to modify the position of the character producing the animation. The function “animate” is realized starting from an idea of Mike Williams.
What’s Geocoding?
Geocoding is the process of converting a human readable address (like “Galleria del Corso, 2, Milano Italy”) into coordinates (latitude 45.465266 and longitude 9.195042) that are needed, for example, to place a marker into the Google map; this service can be accessed via the GClientGeocoder object:
var geocoder = new GClientGeocoder();
geocoder.getLocations(address:String, callback:function) .where as usual the callback function is the function that will be called asyncronously when the server will give a response. In our case, the random location of the HelloKitty’s home (that will be the final destination of the character) is defined as the nearest street to the user click on the map. The handler of the click event give us the coordinates of the click (which may not lie on a street). In order to compute the address of the nearest street in a human readable way from coordinates, we use a feature that is called “reverse geocoding”. This stuff is suppported by the same GClientGeocoder.getLocations() method, simply passing as argument the GLatLng object instead of a String address. The following line calls the geocoder, passing the position (as the last point of the polyline) and the callback function that will use the retrieved values:
geocoder.getLocations(poly.getVertex(poly.getVertexCount()-1), showAddress);The callback function is necessary since geocoding involves sending a request to Google’s servers and can take some time. In our example, the callback function handles eventual errors and, for a successful response, opens the info window on the final destination and print the address, using the response class given by the Google server:
function showAddress(response) {
if (!response || response.Status.code != 200) {
alert("Status Code:" + response.Status.code);
} else {
place = response.Placemark[0];
point = new GLatLng(place.Point.coordinates[1],place.Point.coordinates[0]);
map.openInfoWindowHtml(point,
'<div>Thank you, I am back !! :-)' +
'<strong>----</strong>' +
place.address +
'</div>');
}
}This work is realized jointly with Alberto Mancini.
by 
I am a researcher and co-founder of KeyChain and my current project is JooinK.
I am one of the founders of the firenze-GTUG.
I am an italian mathematician (Msc Univ. Camerino, PhD Univ. Firenze) and I worked on the development of a CFD code for numerical simulation (Numidia jointly with Ferrari - Rome; ANSYS Germany on the meshing Team - Hannover).

