Saving Draggable Points of Interest from Google Maps V3
This article demonstrates how to create points of interest in Google Maps using the Directions API and save them so they can be viewed in the UI (user interface) at a later time.
Google Maps V3 features a service where we can display directions from a starting point to an arrival point, which can be dragged to alter the itinerary. Using the mouse, the user can modify the route according to their needs. This means changing the standard route directed by Google. The user can then create points of interest along the standard route and display them to differentiate between the current route and the modified one. For development use, Google allows a maximum of eight points of interest.
The final application layout will look as shown below:

Prerequisites: before starting, make sure that the JDK and Glassfish 3.1 are installed and configured on your machine along with the Eclipse IDE.
Run the Eclipse IDE and select a workspace where you want to create the project.
1st Click on File-> New-> Dynamic Web Project . (Figure 2)

2nd Choose a name for the project (GDirections). Figure 3

Keep the settings as shown in Figure 4.

Finish the project using the Finish button. Figure 5

Add all resteasy libraries to the Web-Inf/lib directory. Figure 6

Create the class inside the src folder: br.com.rezende.map.services.DirectionsServices, and add the index.jsp file inside WebContent. Figure 7

Add a script folder in WebContent. Figure 8

Add the json2.js file to the script folder. Figure 9

The map on the left (Figure 1) is where the standard route was created, which allows altering and adding 8 points of interest. To alter this route and add points of interest, move the mouse over the yellow line and wait for the circle to appear. Drag the circle in any direction and release the mouse button. Thus, the user can modify the route simply by dragging the circle with the mouse and creating new points of interest. When clicking the “Save” button, a service stores the “JSON” string in a variable so it can be retrieved later. We are not using a database at this moment, as this article focuses solely on demonstrating how to use the Google Directions API.
Code and Explanation
You can use the same code written in this article.
It is necessary to have some familiarity with Google Maps V3, such as displaying the map inside a <div> and centering it by passing latitude and longitude as parameters to the map object.
See below for an explanation of the workflow performed.
In the web.xml file, add the following lines:
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
In the class created previously, DirectionsServices, add the following code.
@Path("/rest/directionsWS")
public class DirectionsServices {
private static String gMapsJson;
@GET
@Produces("application/json")
@Path("/render")
public String render() {
String resp = gMapsJson;
System.out.println("Foi");
return resp;
}
@GET
@Path("/save/{param}")
@Produces("application/json")
public String save(@PathParam("param") String json) {
this.gMapsJson = json;
return gMapsJson;
}
}
Include the code below in the header section of your index.jsp. The first will include the Google Maps V3 API and the second is used to create a JSON string from an array of objects.
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false"></script>
<script src="json2.js"></script>
This array of objects converts the points of interest into JSON format and will then stop the server and save them to our static variable.
Still inside index.jsp, create a div with the id equal to map_canvas and its styling. Also create a button to call a Javascript function that will save the points of interest. When the page is initialized, it will also call the Javascript initialize() function which will load the default map, on the left side of Figure 1.
<body onload="initialize()">
<form id="form">
<div class="contents" style="width: 90%; margin: 0px auto;">
<div class="maindiv" style="width: 100%;">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="49%" style="padding: 3px; color: #993333;">Click on the yellow route and drag it to another location.</td>
<td width="2%" style="padding: 3px; color: #993333;"> </td>
<td width="49%" style="padding: 3px; color: #993333;">Click the load button to display the saved route.</td>
</tr>
<tr>
<td><div id="map_canvas" style="width: 100%; height: 250px;"></div></td>
<td> </td>
<td><div id="map_ren" style="width: 100%; height: 250px;"></div></td>
</tr>
<tr>
<td style="text-align: center; padding-top: 10px;">
<input type="button" value="Save" id="save" name="save"/>
</td>
<td style="text-align: center;"> </td>
<td style="text-align: center; padding-top: 10px;">
<input type="button" id="render" name="render" value="Render" />
</td>
</tr>
</table>
</div>
</div>
</form>
</body>
Add the Javascript functions and variables to the index.jsp file that will be used to plot the maps and routes.
<script type="text/javascript">
var directionDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var data = {};
var polylineOptionsActual = {
strokeColor : '#FFF000',
strokeOpacity : 1.0,
strokeWeight : 6
};
var directionDisplay2;
var directionsService2 = new google.maps.DirectionsService();
var map2;
var polylineOptionsActual2 = {
strokeColor : '#FF0000',
strokeOpacity : 1.0,
strokeWeight : 6
};
function initialize() {
var blumenau = new google.maps.LatLng(-26.889005, -49.070641);
var florianopolis = new google.maps.LatLng(-27.566721, -48.551537);
directionsDisplay = new google.maps.DirectionsRenderer({
polylineOptions : polylineOptionsActual,
'draggable' : true
});
directionsDisplay2 = new google.maps.DirectionsRenderer({
polylineOptions : polylineOptionsActual2,
'draggable' : false
});
var myOptions = {
zoom : 12,
mapTypeId : google.maps.MapTypeId.HYBRID,
center : blumenau
};
map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
map2 = new google.maps.Map(document.getElementById("map_ren"),
myOptions);
directionsDisplay.setMap(map);
directionsDisplay2.setMap(map2);
directionsService.route({
'origin' : blumenau,
'destination' : florianopolis,
'travelMode' : google.maps.DirectionsTravelMode.DRIVING
}, function(res, sts) {
if (sts == 'OK') {
directionsDisplay.setDirections(res);
}
});
}
function setroute(os) {
var wp = [];
for ( var i = 0; i < os.waypoints.length; i++)
wp[i] = {
'location' : new google.maps.LatLng(os.waypoints[i][0],
os.waypoints[i][1]),
'stopover' : false
};
directionsService2.route({
'origin' : new google.maps.LatLng(os.start.lat, os.start.lng),
'destination' : new google.maps.LatLng(os.end.lat, os.end.lng),
'waypoints' : wp,
'travelMode' : google.maps.DirectionsTravelMode.DRIVING
}, function(res, sts) {
if (sts == 'OK')
directionsDisplay2.setDirections(res);
});
}
$(function() {
$('#save').click(
function() {
var w = [], wp;
var rleg = directionsDisplay.directions.routes[0].legs[0];
data.start = {
'lat' : rleg.start_location.lat(),
'lng' : rleg.start_location.lng()
};
data.end = {
'lat' : rleg.end_location.lat(),
'lng' : rleg.end_location.lng()
};
var wp = rleg.via_waypoints;
for ( var i = 0; i < wp.length; i++) {
w[i] = [ wp[i].lat(), wp[i].lng() ];
}
data.waypoints = w;
var str = JSON.stringify(data);
$.get(
'http://localhost:48080/GDirections/rest/directionsWS/save/'
+ str, function(data) {
});
alert('Route Saved.');
});
$('#render')
.click(
function() {
$.get(
'http://localhost:48080/GDirections/rest/directionsWS/render',
function(data) {
setroute(data);
});
});
});
</script>
The variables declared for Google Maps must contain information about the starting location, arrival location, and points of interest in latitude and longitude. The map must then be initialized by passing the “id” of where it will be displayed, the zoom level, map type, and centering coordinates.
The route function of DirectionsService will plot a route from the starting point to the destination point in “driving” mode. It will send a request to Google’s server and obtain the path as a result, plotting the information. In the callback function, if the response is ok, then setdirections is assigned the function that will draw the route on the Google Map via directionsDisplay.
When clicking the “Save” button, the save function creates a JSON string and sends it to be stored in the Webservice variable.
When the user drags the route, a new point of interest is created in the object, modifying the array of points of interest.
To update this list, a loop was created that stores only the latitude and longitude of the points of interest. Then, the LatLng information of the point of interest is stored in the “locations” property. Finally, the data object will be converted into a JSON string by the stringify method.
The DirectionsServices Webservice will receive the JSON string sent as a parameter via the save method and store the new information in the gMapsJson object.
When the user clicks the Render button, the associated Javascript function will request a JSON string object from the Webservice to draw the previously stored route.
The javascript setroute function will receive the JSON string object from the server.
It will be necessary to create an object containing the latitude and longitude points for departure and arrival, as well as the points of interest.
With these points, we create an object with origin and destination and instruct the map to trace the routes. After mapping this itinerary, it is necessary to display it by calling setDirections inside the callback function.
Conclusion
The Google Maps API is very simple to use and can be utilized for development within a daily access limit. It can be viewed in the online documentation: here.
Working together with the Google Directions API allows you to route itineraries, calculate routes in advance, and style objects that will be drawn on the map. It is an excellent alternative for the Brazilian market. It features a set of 1,397 Brazilian municipalities in an online service, many of them updated with 2012 data.
Because it is an online service, map updates are included.
Another advantage is that local space is not required to store the maps.
Source code and libraries download: The source code can be obtained Here
Andre Meirelles de Rezende
Software Architect

