using System;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.MvcEdition;
using ThinkGeo.MapSuite.Routing;
namespace ThinkGeo.MapSuite.RoutingExamples.Controllers
{
public class DefaultController : Controller
{
// GET: /Default/
private static readonly string roadColumnName = "FULL_STREE";
private static Collection avoidableFeatureIds;
private static Feature newBarrierFeature;
private static ShapeFileFeatureLayer routingShapeFile;
public ActionResult Index()
{
routingShapeFile = new ShapeFileFeatureLayer(Server.MapPath(ConfigurationManager.AppSettings["austinStreetShapeFile"]));
avoidableFeatureIds = new Collection();
// Initialize map
Map map = InitializeMap();
return View(map);
}
[MapActionFilter]
public ActionResult addRouteAddresses(Map map, GeoCollection
====RouteDirectionModel.cs====
using System;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.Routing;
namespace ThinkGeo.MapSuite.RoutingExamples
{
public class RouteDirectionModel
{
private string roadNameColumnName;
private string directionImageUriString;
private static string directionImageUriTemplate = "../Content/Images/Directions/{0}";
private Feature roadFeature;
private DistanceUnit lengthUnit;
private RouteSegment roadSegment;
private Feature roadSegmentFeature;
private GeographyUnit geographyUnit;
public RouteDirectionModel()
{ }
public RouteDirectionModel(RouteSegment roadSegment, Feature roadFeature, string roadNameColumnName)
: this(roadSegment, roadFeature, roadNameColumnName, GeographyUnit.DecimalDegree, DistanceUnit.Meter)
{ }
public RouteDirectionModel(RouteSegment roadSegment, Feature roadFeature, string roadNameColumnName, GeographyUnit geographyUnit, DistanceUnit lengthUnit)
{
this.roadSegment = roadSegment;
this.roadFeature = roadFeature;
this.roadNameColumnName = roadNameColumnName;
this.geographyUnit = geographyUnit;
this.lengthUnit = lengthUnit;
}
public DrivingDirection Direction
{
get
{
if (roadSegment != null)
{
return roadSegment.DrivingDirection;
}
else
{
return DrivingDirection.Back;
}
}
}
public Uri DirectionImageUri
{
get
{
switch (Direction)
{
case DrivingDirection.Back:
directionImageUriString = "back.png";
break;
case DrivingDirection.Forward:
directionImageUriString = "Forward.png";
break;
case DrivingDirection.Invalid:
directionImageUriString = "Invalid.png";
break;
case DrivingDirection.LeftForward:
directionImageUriString = "LeftForward.png";
break;
case DrivingDirection.Right:
directionImageUriString = "Right.png";
break;
case DrivingDirection.RightBack:
directionImageUriString = "RightBack.png";
break;
case DrivingDirection.RightForward:
directionImageUriString = "RightForward.png";
break;
case DrivingDirection.LeftBack:
directionImageUriString = "LeftBack.png";
break;
case DrivingDirection.Left:
directionImageUriString = "Left.png";
break;
}
return new Uri(string.Format(directionImageUriTemplate, directionImageUriString), UriKind.RelativeOrAbsolute);
}
}
public GeographyUnit GeographyUnit
{
get { return geographyUnit; }
set { geographyUnit = value; }
}
public string Length
{
get
{
string length = string.Empty;
double value = Math.Round(((LineBaseShape)RoadFeature.GetShape()).GetLength(GeographyUnit, lengthUnit), 2);
if (lengthUnit == DistanceUnit.Mile)
{
length = string.Format("{0} mi", value);
}
else
{
length = string.Format("{0} km", value);
}
return length;
}
}
public DistanceUnit LengthUnit
{
get { return lengthUnit; }
set { lengthUnit = value; }
}
public Feature RoadFeature
{
get { return roadFeature; }
set { roadFeature = value; }
}
public string RoadName
{
get
{
if (!string.IsNullOrEmpty(RoadNameColumnName))
{
return roadFeature.ColumnValues[RoadNameColumnName];
}
else
{
return string.Empty;
}
}
}
public string RoadNameColumnName
{
get { return roadNameColumnName; }
set { roadNameColumnName = value; }
}
public RouteSegment RoadSegment
{
get { return roadSegment; }
set { roadSegment = value; }
}
public Feature RoadSegmentFeature
{
get { return roadSegmentFeature; }
set { roadSegmentFeature = value; }
}
}
}
====RoutePathAndDirection.cs====
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.Routing;
namespace ThinkGeo.MapSuite.RoutingExamples
{
public class RoutePathAndDirection
{
private readonly List stopPoints;
private readonly List avoidableFeatureIds;
private PointShape endPoint;
private PointShape startPoint;
private RoutingEngine routingEngine;
private FeatureSource barrierFeatureSource;
public RoutePathAndDirection()
{ }
public RoutePathAndDirection(RoutingEngine routingEngine, PointShape startPoint, PointShape endPoint)
: this(routingEngine, startPoint, endPoint, null)
{
}
public RoutePathAndDirection(RoutingEngine routingEngine, PointShape startPoint, PointShape endPoint, FeatureSource barrierFeatureSource)
: this(routingEngine, startPoint, endPoint, barrierFeatureSource, new string[] { })
{
}
public RoutePathAndDirection(RoutingEngine routingEngine, PointShape startPoint, PointShape endPoint, FeatureSource barrierFeatureSource, IEnumerable avoidableFeatureIds)
: this(routingEngine, startPoint, endPoint, barrierFeatureSource, avoidableFeatureIds, new PointShape[] { })
{
}
public RoutePathAndDirection(RoutingEngine routingEngine, PointShape startPoint, PointShape endPoint, FeatureSource barrierFeatureSource, IEnumerable stopPoints)
: this(routingEngine, startPoint, endPoint, barrierFeatureSource, new string[] { }, stopPoints)
{
}
public RoutePathAndDirection(RoutingEngine routingEngine, PointShape startPoint, PointShape endPoint, FeatureSource barrierFeatureSource, IEnumerable avoidableFeatureIds, IEnumerable stopPoints)
{
this.endPoint = endPoint;
this.startPoint = startPoint;
this.routingEngine = routingEngine;
this.barrierFeatureSource = barrierFeatureSource;
this.stopPoints = new List(stopPoints);
this.avoidableFeatureIds = new List(avoidableFeatureIds);
routingEngine.RoutingAlgorithm.FindingRoute += RoutingAlgorithm_FindingRoute;
}
public PointShape StartPoint
{
get { return startPoint; }
set { startPoint = value; }
}
public PointShape EndPoint
{
get { return endPoint; }
set { endPoint = value; }
}
public List StopPoints
{
get { return stopPoints; }
}
public RoutingEngine RoutingEngine
{
get { return routingEngine; }
set { routingEngine = value; }
}
public List AvoidableFeatureIds
{
get { return avoidableFeatureIds; }
}
public FeatureSource BarrierFeatureSource
{
get { return barrierFeatureSource; }
set { barrierFeatureSource = value; }
}
public RoutingResult GetRoute()
{
if (stopPoints != null && !stopPoints.Any())
{
RoutingResult result = routingEngine.GetRoute(startPoint, endPoint);
return result;
}
else
{
Collection points = new Collection();
points.Add(startPoint);
foreach (PointShape stopPoint in stopPoints)
{
points.Add(stopPoint);
}
points.Add(endPoint);
// Filter the invalid point.
Collection availablePoint = FilterInvalidPoints(points);
RoutingResult result = null;
for (int i = 0; i < availablePoint.Count - 1; i++)
{
RoutingResult tempResult = routingEngine.GetRoute(availablePoint[i], availablePoint[i|+ 1]);
result = CombineRoutingResult(result, tempResult);
}
return result;
}
}
private Collection FilterInvalidPoints(IEnumerable points)
{
Collection result = new Collection();
barrierFeatureSource.Open();
Collection barrierFeatures = barrierFeatureSource.GetAllFeatures(ReturningColumnsType.NoColumns);
foreach (PointShape point in points)
{
bool inBarrier = barrierFeatures.Any(a => a.Contains(new Feature(point)));
if (!inBarrier) result.Add(point);
}
return result;
}
private RoutingResult CombineRoutingResult(RoutingResult baseResult, RoutingResult additionalResult)
{
if (baseResult == null)
{
baseResult = new RoutingResult();
baseResult.Distance = additionalResult.Distance;
baseResult.Weight = additionalResult.Weight;
baseResult.Route = additionalResult.Route;
additionalResult.Features.ForEach(a => baseResult.Features.Add(a));
additionalResult.OrderedStops.ForEach(a => baseResult.OrderedStops.Add(a));
additionalResult.RouteSegments.ForEach(a => baseResult.RouteSegments.Add(a));
}
else
{
baseResult.Distance += additionalResult.Distance;
baseResult.Weight += additionalResult.Weight;
Collection vertexes = new Collection();
baseResult.Route.Vertices.ForEach(vertexes.Add);
additionalResult.Route.Vertices.ForEach(vertexes.Add);
baseResult.Route = new LineShape(vertexes);
additionalResult.Features.ForEach(a => baseResult.Features.Add(a));
additionalResult.OrderedStops.ForEach(a => baseResult.OrderedStops.Add(a));
additionalResult.RouteSegments.ForEach(a => baseResult.RouteSegments.Add(a));
}
return baseResult;
}
private void RoutingAlgorithm_FindingRoute(object sender, FindingRouteRoutingAlgorithmEventArgs e)
{
Collection beContainedFeatureIds = new Collection();
barrierFeatureSource.Open();
Collection startPointAdjacentIds = e.RouteSegment.StartPointAdjacentIds;
Collection endPointAdjacentIds = e.RouteSegment.EndPointAdjacentIds;
foreach (string id in startPointAdjacentIds.Where(id => avoidableFeatureIds.Contains(id)))
{
beContainedFeatureIds.Add(id);
}
foreach (string id in endPointAdjacentIds.Where(id => avoidableFeatureIds.Contains(id)))
{
beContainedFeatureIds.Add(id);
}
// Remove the ones that be contained in the avoidable area
foreach (string id in beContainedFeatureIds)
{
if (e.RouteSegment.StartPointAdjacentIds.Contains(id))
{
e.RouteSegment.StartPointAdjacentIds.Remove(id);
}
if (e.RouteSegment.EndPointAdjacentIds.Contains(id))
{
e.RouteSegment.EndPointAdjacentIds.Remove(id);
}
}
}
}
}
====RouteStopType.cs====
namespace ThinkGeo.MapSuite.RoutingExamples
{
public enum RouteStopType
{
Start = 0,
Stop = 1,
End = 2
}
}
====ready-functions.cs====
$(document).ready(function () {
initializePageElements();
// clear all the route result and addresses
$("#btnClearAll").bind("click", function (e) {
Map1.ajaxCallAction('Default', 'ClearAll', {}, function (result) {
var response = result.get_responseData();
if (response != "") {
$("#divAddresses").empty().html(response);
Map1.redrawLayer('RoutingOverlay');
}
$("#routeDirections").empty();
if (Map1.getEditOverlay() != null) {
Map1.getEditOverlay().removeAllFeatures();
}
Map1.redrawLayer('RoutingOverlay');
});
});
$("#divTrackMode input[type=image]").bind("click", function () {
var mode = $(this).attr("command");
switch (mode) {
case "ClearAll":
Map1.setDrawMode("Normal");
Map1.getEditOverlay().removeAllFeatures();
Map1.ajaxCallAction("default", "ClearAllBarriers", {}, function () {
Map1.redrawLayer('RoutingOverlay');
});
$("#btnPanMap").trigger("click");
break;
case "Undo":
Map1.ajaxCallAction("default", "UndoDrawnBarrier", {}, function () {
Map1.redrawLayer('RoutingOverlay');
});
$("#btnPanMap").trigger("click");
break;
case "Polygon":
Map1.setDrawMode("Polygon");
$(this).trigger("click");
break;
case "PanMap":
Map1.setDrawMode("Normal");
$("#btnPanMap").trigger("click");
break;
default: break;
}
});
});
var OnMapCreated = function (map) {
map.events.register("mousemove", map, function (e) {
var mouseCoordinate = this.getLonLatFromPixel(new OpenLayers.Pixel(e.clientX, e.clientY));
if (mouseCoordinate) {
$("#spanMouseCoordinate").text("X:" + mouseCoordinate.lon.toFixed(6) + " Y: " + mouseCoordinate.lat.toFixed(6));
}
});
}
function initializePageElements() {
var resizeElementHeight = function () {
var documentheight = $(window).height();
var contentDivH = documentheight - $("#footer").height() - $("#header").height() - 1;
$("#content-container").height(contentDivH + "px");
$("#leftContainer").height(contentDivH + "px");
$("#map-content").height(contentDivH + "px");
$("#toggle").css("line-height", contentDivH + "px");
if (contentDivH > 500) {
$("#queryResultUpdatePanel").height(contentDivH - 365 - $("#stopPanle").height() + "px");
} else {
$("#queryResultUpdatePanel").visible = false;
}
// refresh the map.
Map1.updateSize();
}
window.onload = resizeElementHeight();
$(window).resize(resizeElementHeight);
// Bind toggle button events
$("#toggle").bind("click", function () {
if ($("#leftContainer").is(':visible')) {
$("#collapse").attr("src", "Content/Images/expand.gif");
$("#map-content").css("width", "100%");
$("#toggle").css("left", "0%");
$("#leftContainer").hide();
}
else {
$("#leftContainer").show();
$("#collapse").attr("src", "Content/Images/collapse.gif");
$("#map-content").css("width", "80%");
$("#toggle").css("left", "20%");
}
resizeElementHeight();
});
// set the toggle style for group buttons
$("#divTrackMode input[type=image]").bind("click", function () {
var btnImgs = $("#divTrackMode input[type=image]");
for (var i = 0; i < btnImgs.length; i++) {
$(btnImgs[i]).attr("class", "imgButton");
}
$(this).attr("class", "active imgButton");
});
$("#warningDialog").dialog({
autoOpen: false,
modal: true,
buttons: {
Ok: function () {
$(this).dialog("close");
}
}
});
}
function addRouteAddress(e) {
var addressText;
if (e.srcElement == undefined)
addressText = e.target;
else {
addressText = e.srcElement;
}
var args = { type: $(addressText).text(), x: e.worldXY.lon, y: e.worldXY.lat };
Map1.ajaxCallAction('Default', 'addRouteAddresses', args, function (result) {
var response = result.get_responseData();
if (response == "") {
$("warningDialog").dialog("open");
} else {
$("#divAddresses").empty().html(response);
Map1.redrawLayer('RoutingOverlay');
}
});
}
function removeStopItem(number) {
Map1.ajaxCallAction('Default', 'RemoveRouteAddresses', { x: number }, function (result) {
var response = result.get_responseData();
if (response != "") {
$("#divAddresses").empty().html(response);
Map1.redrawLayer('RoutingOverlay');
}
if ($("#tbAddresses tr").length < 1) {
$("#imgInvert").show();
}
});
}
function switchPoint() {
Map1.ajaxCallAction('Default', 'SwithStartEndPoint', {}, function (result) {
var startValue = $("#startPoint").val();
$("#startPoint").val($('#endPoint').val());
$('#endPoint').val(startValue);
// clear last route records
$("#routeDirections").empty();
getDirections();
});
}
function trackShapeFinished(e) {
var features = JSON.parse(e.features);
var wkts = [];
for (var i = 0; i < features.length; i++) {
wkts.push(features[i].wkt);
}
$("#loading").show();
Map1.ajaxCallAction("default", "ProcessTrackFeatures", wkts, function (result) {
Map1.redrawLayer('RoutingOverlay');
Map1.getEditOverlay().removeAllFeatures();
$("#loading").hide();
});
}
function resizeResultTable() {
var documentheight = $(window).height();
var contentDivH = documentheight - $("#footer").height() - $("#header").height() - 1;
if (contentDivH > 500) {
$("#routeDirections").height(contentDivH - 265 - $("#divAddresses").height() + "px");
} else {
$("#routeDirections").visible = false;
}
}
function getDirections() {
$("#loading").show();
Map1.ajaxCallAction('Default', 'RouteDirections', { routeMode: $('#RouteMode')[0].checked, distanceUnit: $("#DistanceUnit").val() }, function (result) {
$("#loading").hide();
$("#routeDirections").empty().html(result.get_responseData());
resizeResultTable();
Map1.redrawLayer('RoutingOverlay');
});
}
function changeDistanceUnit() {
getDirections();
Map1.getAdornmentOverlay().redraw(true);
}
====Index.cshtml====
@using ThinkGeo.MapSuite.Routing
@using ThinkGeo.MapSuite.MvcEdition
@using System.Collections.ObjectModel;
@using ThinkGeo.MapSuite.RoutingExamples;
@model ThinkGeo.MapSuite.MvcEdition.Map
@{
ViewBag.Title = "City Routing and Directions";
}
Map Suite City Routing and
Directions
Right click on the map to set up a route:
@{
Html.RenderPartial("RouteStops", new RoutingLayer());
}
Tools:
Result
Road Name
Length
@{
Html.ThinkGeo().Map(Model).Render();
}
Please note that this sample map is only able to support finding the route within
the Austin, TX city limits, which are indicated by a dashed red line. Click inside
that boundary for best results.
====LinqExtension.cs====
using System;
using System.Collections.Generic;
namespace ThinkGeo.MapSuite.RoutingExamples
{
public static class LinqExtension
{
public static void ForEach(this IEnumerable items, Action action)
{
foreach (var item in items)
{
if (action != null) action(item);
}
}
}
}