I am working on a project where i need to track the salesperson's route of movement for a certain period (may span n days). I get locations stored from mobile device which i save in database using web service.
Now i have a multi-select drop-down for selecting salesperson(s). i pass the salesperson ids as comma separated values and get the latitude and longitude for selected salesperson(s) from database.
Code is below.
IList<RadComboBoxItem> Values = rcbSalesPersons.CheckedItems;
string Ids = String.Join(",", rcbSalesPersons.Items.Where(i => i.Checked).Select(i => i.Value).ToList());
List<SalespersonSpatialInfo> lstSpatialInfo = SalespersonSpatialInfo.getSpatialInfo(Ids, Session["StoreID"].ToString(),RadDatePickerFrom.SelectedDate.Value, RadDatePickerTo.SelectedDate.Value);
string jsonString;
if (lstSpatialInfo.Count > 0)
{
jsonString = JsonSerializer<List<SalespersonSpatialInfo>>(lstSpatialInfo);
ScriptManager.RegisterArrayDeclaration(Page, "markers", jsonString);
ScriptManager.RegisterStartupScript(Page, Page.GetType(), Guid.NewGuid().ToString(), "GoogleMap();", true);
}
As i registered the javascript Markers array in source of the page, now i use following javascript function to plot the points on map and join them
function GoogleMap() {
var mapOptions = {
center: new google.maps.LatLng(markers[0][0].Latitude, markers[0][0].Longitude),
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var infoWindow = new google.maps.InfoWindow();
var lat_lng = new Array();
var latlngbounds = new google.maps.LatLngBounds();
for (i = 0; i < markers[0].length; i++) {
var data = markers[0][i];
var myLatlng = new google.maps.LatLng(data.Latitude, data.Longitude);
lat_lng.push(myLatlng);
var marker = new google.maps.Marker({
position: myLatlng,
map: map
});
latlngbounds.extend(marker.position);
(function (marker, data) {
google.maps.event.addListener(marker, "click", function (e) {
infoWindow.setContent(data.description);
infoWindow.open(map, marker);
});
})(marker, data);
}
map.setCenter(latlngbounds.getCenter());
map.fitBounds(latlngbounds);
//***********ROUTING****************//
//Initialize the Path Array
var path = new google.maps.MVCArray();
debugger;
//Initialize the Direction Service
var service = new google.maps.DirectionsService();
//Set the Path Stroke Color
var poly = new google.maps.Polyline({ map: map, strokeColor: '#489615' });
//Loop and Draw Path Route between the Points on MAP
for (var i = 0; i < lat_lng.length; i++) {
if ((i + 1) <= lat_lng.length) {
var src = lat_lng[i];
var des = lat_lng[i + 1];
path.push(src);
poly.setPath(path);
service.route({
origin: src,
destination: des,
travelMode: google.maps.DirectionsTravelMode.TRANSIT
}, function (result, status) {
if (status == google.maps.DirectionsStatus.OK) {
for (var i = 0, len = result.routes[0].overview_path.length; i < len; i++) {
path.push(result.routes[0].overview_path[i]);
}
}
});
}
}
}
i get following json
[
{
"DeviceID": null,
"ID_SalesRep": 58,
"Latitude": 22.693519,
"LocationID": 1,
"Longitude": 75.919796,
"StoreID": "xyz",
"TrackingTime": "/Date(1418246100000+0530)/"
},
{
"DeviceID": null,
"ID_SalesRep": 58,
"Latitude": 22.701211,
"LocationID": 2,
"Longitude": 75.926846,
"StoreID": "xyz",
"TrackingTime": "/Date(1418246100000+0530)/"
},
{
"DeviceID": null,
"ID_SalesRep": 59,
"Latitude": 22.750948,
"LocationID": 3,
"Longitude": 75.895411,
"StoreID": "xyz",
"TrackingTime": "/Date(1418246100000+0530)/"
},
{
"DeviceID": null,
"ID_SalesRep": 58,
"Latitude": 22.705804,
"LocationID": 4,
"Longitude": 75.905024,
"StoreID": "xyz",
"TrackingTime": "/Date(1418246100000+0530)/"
},
{
"DeviceID": null,
"ID_SalesRep": 58,
"Latitude": 22.711267,
"LocationID": 5,
"Longitude": 75.883073,
"StoreID": "xyz",
"TrackingTime": "/Date(1418246100000+0530)/"
},
{
"DeviceID": null,
"ID_SalesRep": 58,
"Latitude": 22.718155,
"LocationID": 6,
"Longitude": 75.883802,
"StoreID": "xyz",
"TrackingTime": "/Date(1418246100000+0530)/"
},
{
"DeviceID": null,
"ID_SalesRep": 59,
"Latitude": 22.747032,
"LocationID": 7,
"Longitude": 75.883727,
"StoreID": "xyz",
"TrackingTime": "/Date(1418246100000+0530)/"
},
{
"DeviceID": null,
"ID_SalesRep": 58,
"Latitude": 22.726512,
"LocationID": 8,
"Longitude": 75.880881,
"StoreID": "xyz",
"TrackingTime": "/Date(1418246100000+0530)/"
},
{
"DeviceID": null,
"ID_SalesRep": 59,
"Latitude": 22.718927,
"LocationID": 9,
"Longitude": 75.856036,
"StoreID": "xyz",
"TrackingTime": "/Date(1418246100000+0530)/"
}
]
I also need to change the color of the marker and Polylines for different salespersons later when this is done.
Now the problem is, I need to show different routes for different salespersons but it shows the single route joining the locations for both the salespersons. please ask for clarification if needed.
finally i get it working using the following server and client side logic
On server side i made n multiple arrays of locations belonging to each salesperson in resultset
c#
IList<RadComboBoxItem> Values = rcbSalesPersons.CheckedItems;
string Ids = String.Join(",", rcbSalesPersons.Items.Where(i => i.Checked).Select(i => i.Value).ToList());
//List<SalespersonSpatialInfo> lstSpatialInfo = SalespersonSpatialInfo.getSpatialInfo(Ids, Session["StoreID"].ToString(), new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1), DateTime.Now);
List<SalespersonSpatialInfo> lstSpatialInfo = SalespersonSpatialInfo.getSpatialInfo(Ids, Session["StoreID"].ToString(), RadDatePickerFrom.SelectedDate.Value, RadDatePickerTo.SelectedDate.Value);
var distinctSalespersons = lstSpatialInfo.Select(t => t.ID_SalesRep).Distinct().ToList();
string jsonString;
hdnMarkerArraySuffix.Value = "";
if (lstSpatialInfo.Count > 0)
{
for (int i = 0; i < distinctSalespersons.Count; i++)
{
List<SalespersonSpatialInfo> lstMarkers = lstSpatialInfo.Where(o => o.ID_SalesRep == distinctSalespersons[i]).ToList();
jsonString = JsonSerializer<List<SalespersonSpatialInfo>>(lstMarkers);
ScriptManager.RegisterArrayDeclaration(Page, "markers"+distinctSalespersons[i].ToString(), jsonString);
hdnMarkerArraySuffix.Value += distinctSalespersons[i] + ",";
}
ScriptManager.RegisterStartupScript(Page, Page.GetType(), Guid.NewGuid().ToString(), "GoogleMap();", true);
}
Note i use salesperson id suffix to diffrentiate the salesperson location arrays, i stored these ID suffix in hiddenfield to process them later when plotting markers and polylines.
the client side code to place markers and join them when multiple salespersons are selected from the multiselect dropdown Javascript
function GoogleMap() {
var MarkerArrayNamesCSV = $('#<%=hdnMarkerArraySuffix.ClientID%>').val();
if (MarkerArrayNamesCSV.charAt(MarkerArrayNamesCSV.length - 1) == ",") {
MarkerArrayNamesCSV = MarkerArrayNamesCSV.slice(0, -1);
}
var MarkerArrayNames;
if (MarkerArrayNamesCSV.indexOf(',') > 0) {
MarkerArrayNames = MarkerArrayNamesCSV.split(',');
}
else {
MarkerArrayNames = new Array();
MarkerArrayNames.push(MarkerArrayNamesCSV);
}
var map;
for (k = 0; k < MarkerArrayNames.length; k++) {
var mapOptions = {
center: new google.maps.LatLng(window['markers' + MarkerArrayNames[k]][0][0].Latitude, window['markers' + MarkerArrayNames[k]][0][0].Longitude),
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
if (typeof map == 'undefined') {
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
}
var infoWindow = new google.maps.InfoWindow();
var lat_lng = new Array();
var latlngbounds = new google.maps.LatLngBounds();
for (i = 0; i < window['markers' + MarkerArrayNames[k]][0].length; i++) {
var data = window['markers' + MarkerArrayNames[k]][0][i];
var myLatlng = new google.maps.LatLng(data.Latitude, data.Longitude);
lat_lng.push(myLatlng);
var marker = new google.maps.Marker({
position: myLatlng,
map: map
});
latlngbounds.extend(marker.position);
(function (marker, data) {
google.maps.event.addListener(marker, "click", function (e) {
infoWindow.setContent(data.description);
infoWindow.open(map, marker);
});
})(marker, data);
}
// map.setCenter(latlngbounds.getCenter());
// map.fitBounds(latlngbounds);
//***********ROUTING****************//
//Initialize the Path Array
var path = new google.maps.MVCArray();
//Initialize the Direction Service
var service = new google.maps.DirectionsService();
//Set the Path Stroke Color
var poly = new google.maps.Polyline({ map: map, strokeColor: '#489615' });
//Loop and Draw Path Route between the Points on MAP
try {
for (var i = 0; i < lat_lng.length; i++) {
if ((i + 1) < lat_lng.length) {
var src = lat_lng[i];
var des = lat_lng[i + 1];
path.push(src);
poly.setPath(path);
service.route({
origin: src,
destination: des,
travelMode: google.maps.DirectionsTravelMode.TRANSIT
}, function (result, status) {
try {
if (status == google.maps.DirectionsStatus.OK) {
for (var i = 0, len = result.routes[0].overview_path.length; i < len; i++) {
path.push(result.routes[0].overview_path[i]);
}
}
}
catch (ex1) {
alert('callback' + i);
}
});
}
else {
var src = lat_lng[i];
var des = lat_lng[i];
path.push(src);
poly.setPath(path);
service.route({
origin: src,
destination: des,
travelMode: google.maps.DirectionsTravelMode.TRANSIT
}, function (result, status) {
try {
if (status == google.maps.DirectionsStatus.OK) {
for (var i = 0, len = result.routes[0].overview_path.length; i < len; i++) {
path.push(result.routes[0].overview_path[i]);
}
}
}
catch (ex1) {
alert('callback' + i);
}
});
}
}
}
catch (ex) {
alert(i);
}
}
}
Notice i loop through the available marker arrays in the loop and then loop through the collection to place the markers and join them using polyline object
Though this can be very specific issue but i posted my solution in case someone faces this issue in future.