====== Source Code RoutingEdition ProjectTemplates CityRoutingAndDirections Wpf CS.zip ======
====MainWindow.xaml====
Shortest
Fastest
====BooleanToReverseVisibilityConverter.cs====
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace ThinkGeo.MapSuite.RoutingExamples
{
public class BooleanToReverseVisibilityConverter :IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool)
{
bool isVisible = (bool)value;
return isVisible ? Visibility.Collapsed : Visibility.Visible;
}
return Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
}
====RouteDirectionModel.cs====
using System;
using System.Globalization;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.Routing;
namespace ThinkGeo.MapSuite.RoutingExamples
{
public class RouteDirectionViewModel : ViewModelBase
{
private string roadNameColumnName;
private Feature roadFeature;
private DistanceUnit lengthUnit;
private RouteSegment roadSegment;
private GeographyUnit geographyUnit;
public RouteDirectionViewModel()
: this(null, null, null)
{ }
public RouteDirectionViewModel(RouteSegment roadSegment, Feature roadFeature, string roadNameColumnName)
: this(roadSegment, roadFeature, roadNameColumnName, GeographyUnit.DecimalDegree, DistanceUnit.Meter)
{ }
public RouteDirectionViewModel(RouteSegment roadSegment, Feature roadFeature, string roadNameColumnName, GeographyUnit geographyUnit, DistanceUnit lengthUnit)
{
this.lengthUnit = lengthUnit;
this.roadSegment = roadSegment;
this.roadFeature = roadFeature;
this.geographyUnit = geographyUnit;
this.roadNameColumnName = roadNameColumnName;
}
public DrivingDirection Direction
{
get
{
return roadSegment != null ? roadSegment.DrivingDirection : DrivingDirection.Back;
}
}
public GeographyUnit GeographyUnit
{
get { return geographyUnit; }
set { geographyUnit = value; }
}
public string Length
{
get
{
string length = string.Empty;
if (RoadFeature != null)
{
double value = Math.Round(((LineBaseShape)RoadFeature.GetShape()).GetLength(GeographyUnit, lengthUnit), 2);
length = String.Format(CultureInfo.InvariantCulture, "{0} {1}", value, lengthUnit == DistanceUnit.Mile ? "mi" : "km");
}
return length;
}
}
public DistanceUnit LengthUnit
{
get { return lengthUnit; }
set
{
lengthUnit = value;
RaisePropertyChanged(() => LengthUnit);
RaisePropertyChanged(() => Length);
}
}
public Feature RoadFeature
{
get { return roadFeature; }
set { roadFeature = value; }
}
public string RoadName
{
get
{
return !string.IsNullOrEmpty(RoadNameColumnName) ? roadFeature.ColumnValues[RoadNameColumnName] : string.Empty;
}
}
public string RoadNameColumnName
{
get { return roadNameColumnName; }
set { roadNameColumnName = value; }
}
}
}
====CommandBase.cs====
using System;
using System.Diagnostics;
using System.Windows.Input;
namespace ThinkGeo.MapSuite.RoutingExamples
{
public class CommandBase : ICommand
{
private readonly Predicate
====JsonSerializer.cs====
using System;
using System.Windows;
using System.Windows.Data;
namespace ThinkGeo.MapSuite.RoutingExamples
{
public class CountToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Visibility result = Visibility.Visible;
int count = (int)value;
if (count > 0) result = Visibility.Hidden;
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Binding.DoNothing;
}
}
}
====DirectionTypeToImageSourceConverter.cs====
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using ThinkGeo.MapSuite.Routing;
namespace ThinkGeo.MapSuite.RoutingExamples
{
public class DirectionTypeToImageSourceConverter : IValueConverter
{
private static string directionImageUriTemplate = "/CityRoutingAndDirections;component/Image/Directions/{0}";
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is DrivingDirection)
{
DrivingDirection direction = (DrivingDirection)value;
string directionImageUriString;
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.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;
default:
directionImageUriString = "Right.png";
break;
}
string url = string.Format(CultureInfo.InvariantCulture, directionImageUriTemplate, directionImageUriString);
return new BitmapImage(new Uri(url, UriKind.RelativeOrAbsolute));
}
return Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
}
====PointShapeToStringConverter.cs====
using System;
using System.Globalization;
using System.Windows.Data;
using ThinkGeo.MapSuite.Core;
namespace ThinkGeo.MapSuite.RoutingExamples
{
public class PointShapeToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
object returnValue = string.Empty;
PointShape point = value as PointShape;
if (point != null)
{
returnValue = string.Format(CultureInfo.InvariantCulture, "{0}, {1}", point.X.ToString("N8"), point.Y.ToString("N8"));
}
return returnValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
object returnValue = null;
string pointText = value as string;
if (!string.IsNullOrEmpty(pointText))
{
if (pointText != null)
{
string[] segements = pointText.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
double x, y;
if (segements.Length == 2 && double.TryParse(segements[0], out x) &&
double.TryParse(segements[1], out y))
{
returnValue = new PointShape(x, y);
}
}
}
return returnValue;
}
}
}
====MainWindowViewModel.cs====
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.Routing;
using ThinkGeo.MapSuite.WpfDesktopEdition;
namespace ThinkGeo.MapSuite.RoutingExamples
{
public class MainWindowViewModel : ViewModelBase
{
private static readonly string roadColumnName = "FULL_STREE";
private static readonly string austinCountyShapeFile = @"..\..\App_Data\AustinBorder.shp";
private static readonly string austinStreetShapeFile = @"..\..\App_Data\austin_streets.shp";
private static readonly string rtgFastestFile = @"..\..\App_Data\austin_streets_fastest.rtg";
private static readonly string rtgShortestFile = @"..\..\App_Data\austin_streets_shortest.rtg";
private static readonly RectangleShape defaultExtent = new RectangleShape(-97.803553154785, 30.352039937378, -97.700175654785, 30.259261310914);
private bool isBusy;
private double coordinateX;
private double coordinateY;
private MultipolygonShape restrictedPolygon;
private WpfMap mapControl;
private DistanceUnit distanceUnit;
private RoutingLayer routingLayer;
private RoutePriority routePriority;
private LayerOverlay routingOverlay;
private PointShape routeLocationPoint;
private InMemoryFeatureLayer barrierLayer;
private ShapeFileFeatureLayer restrictedLayer;
private ShapeFileFeatureLayer routingShapeFile;
private Collection avoidableFeatureIds;
private Collection distanceUnitCandidates;
private ObservableCollection stopItems;
private ObservableCollection directionResultList;
private CommandBase undoCommand;
private CommandBase clearAllCommand;
private CommandBase addPointCommand;
private CommandBase deleteStopCommand;
private CommandBase clearBarriersCommand;
private CommandBase updateTrackModeCommand;
private CommandBase calculateDirectionCommand;
private CommandBase inverseDestinationCommand;
public MainWindowViewModel(WpfMap map)
{
mapControl = map;
distanceUnit = DistanceUnit.Mile;
PointShape defaultCenter = defaultExtent.GetCenterPoint();
coordinateX = defaultCenter.X;
coordinateY = defaultCenter.Y;
avoidableFeatureIds = new Collection();
stopItems = new ObservableCollection();
stopItems.CollectionChanged += LocationItems_CollectionChanged;
InitializeMap();
}
public DistanceUnit DistanceUnit
{
get { return distanceUnit; }
set
{
distanceUnit = value;
RaisePropertyChanged(() => DistanceUnit);
if (mapControl != null)
{
ScaleBarAdornmentLayer adornmentLayer = (ScaleBarAdornmentLayer)mapControl.AdornmentOverlay.Layers["ScaleBar"];
adornmentLayer.UnitFamily = value == DistanceUnit.Kilometer ? UnitSystem.Metric : UnitSystem.Imperial;
}
foreach (RouteDirectionViewModel item in DirectionResultList)
{
item.LengthUnit = distanceUnit;
}
}
}
public Collection DistanceUnitCandidates
{
get { return distanceUnitCandidates ?? (distanceUnitCandidates = new Collection { DistanceUnit.Mile, DistanceUnit.Kilometer }); }
}
public bool IsBusy
{
get { return isBusy; }
set
{
isBusy = value;
RaisePropertyChanged(() => IsBusy);
}
}
public WpfMap MapControl
{
get { return mapControl; }
set { mapControl = value; }
}
public double CoordinateX
{
get { return coordinateX; }
set
{
coordinateX = value;
RaisePropertyChanged(() => CoordinateX);
}
}
public double CoordinateY
{
get { return coordinateY; }
set
{
coordinateY = value;
RaisePropertyChanged(() => CoordinateY);
}
}
public PointShape StartPoint
{
get { return routingLayer.StartPoint; }
set
{
if (routingLayer.StartPoint != value)
{
routingLayer.StartPoint = value;
RaisePropertyChanged(() => StartPoint);
routingOverlay.Refresh();
}
}
}
public PointShape EndPoint
{
get { return routingLayer.EndPoint; }
set
{
if (routingLayer.EndPoint != value)
{
routingLayer.EndPoint = value;
RaisePropertyChanged(() => EndPoint);
routingOverlay.Refresh();
}
}
}
public ObservableCollection DirectionResultList
{
get
{
return directionResultList ?? (directionResultList = new ObservableCollection());
}
}
public ObservableCollection StopItems
{
get { return stopItems; }
}
public CommandBase UndoCommand
{
get
{
return undoCommand ?? (undoCommand = new CommandBase(obj =>
{
if (barrierLayer.InternalFeatures.Count == 0) return;
barrierLayer.InternalFeatures.RemoveAt(barrierLayer.InternalFeatures.Count - 1);
routingShapeFile.Open();
avoidableFeatureIds.Clear();
foreach (Feature feature in barrierLayer.InternalFeatures)
{
Collection features = routingShapeFile.FeatureSource.GetFeaturesWithinDistanceOf(feature, mapControl.MapUnit, DistanceUnit.Meter, 1, ReturningColumnsType.NoColumns);
foreach (Feature avoidableFeature in features)
{
avoidableFeatureIds.Add(avoidableFeature.Id);
}
}
routingOverlay.Refresh();
}));
}
}
public CommandBase AddPointCommand
{
get
{
return addPointCommand ?? (addPointCommand = new CommandBase(obj =>
{
restrictedLayer.Open();
Collection features = restrictedLayer.FeatureSource.GetAllFeatures(ReturningColumnsType.NoColumns);
if (features.Count > 0 && !features[0].GetShape().Contains(routeLocationPoint))
{
Window warningWindow = new CityRoutingWarningWindow();
warningWindow.Owner = Application.Current.MainWindow;
warningWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
warningWindow.ShowDialog();
return;
}
string commandParameter = obj as string;
if (commandParameter != null)
{
switch (commandParameter)
{
case "Start":
StartPoint = routeLocationPoint;
break;
case "End":
EndPoint = routeLocationPoint;
break;
case "Stop":
routingLayer.StopPoints.Add(routeLocationPoint);
StopItemViewModel locationItem = new StopItemViewModel(routeLocationPoint);
locationItem.PropertyChanged += SyncStopsToRouteLayer;
StopItems.Add(locationItem);
break;
}
DirectionResultList.Clear();
routingLayer.Routes.Clear();
}
routingOverlay.Refresh();
}));
}
}
public CommandBase ClearAllCommand
{
get
{
return clearAllCommand ?? (clearAllCommand = new CommandBase(obj =>
{
EndPoint = null;
StartPoint = null;
StopItems.Clear();
DirectionResultList.Clear();
routingLayer.StopPoints.Clear();
routingLayer.Routes.Clear();
routingOverlay.Refresh();
}));
}
}
public CommandBase DeleteStopCommand
{
get
{
return deleteStopCommand ?? (deleteStopCommand = new CommandBase(obj =>
{
StopItemViewModel item = (StopItemViewModel)obj;
StopItems.Remove(item);
routingLayer.StopPoints.Remove(item.Location);
routingLayer.Routes.Clear();
DirectionResultList.Clear();
routingOverlay.Refresh();
}));
}
}
public CommandBase ClearBarriersCommand
{
get
{
return clearBarriersCommand ?? (clearBarriersCommand = new CommandBase(obj =>
{
barrierLayer.InternalFeatures.Clear();
avoidableFeatureIds.Clear();
routingOverlay.Refresh();
}));
}
}
public CommandBase UpdateTrackModeCommand
{
get
{
return updateTrackModeCommand ?? (updateTrackModeCommand = new CommandBase(obj =>
{
string commandParameter = obj as string;
if (!string.IsNullOrEmpty(commandParameter))
{
mapControl.TrackOverlay.TrackMode = (TrackMode)Enum.Parse(typeof(TrackMode), commandParameter);
}
}));
}
}
public CommandBase CalculateDirectionCommand
{
get
{
return calculateDirectionCommand ?? (calculateDirectionCommand = new CommandBase(obj =>
{
if (routingLayer == null || routingLayer.StartPoint == null || routingLayer.EndPoint == null) return;
IsBusy = true;
string commandParameter = obj as string;
if (!string.IsNullOrEmpty(commandParameter))
{
routePriority = (RoutePriority)Enum.Parse(typeof(RoutePriority), commandParameter);
}
string rtgFilePathName = string.Empty;
switch (routePriority)
{
case RoutePriority.Fastest:
rtgFilePathName = rtgFastestFile;
break;
case RoutePriority.Shortest:
rtgFilePathName = rtgShortestFile;
break;
}
Task.Factory.StartNew(() =>
{
RtgRoutingSource routingSource = new RtgRoutingSource(rtgFilePathName);
RoutingEngine routingEngine = new RoutingEngine(routingSource, routingShapeFile.FeatureSource);
RoutePathAndDirection routePathAndDirection = new RoutePathAndDirection(routingEngine, routingLayer.StartPoint, routingLayer.EndPoint, barrierLayer.FeatureSource, avoidableFeatureIds, routingLayer.StopPoints);
RoutingResult result = routePathAndDirection.GetRoute();
routingLayer.Routes.Clear();
routingLayer.Routes.Add(result.Route);
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
DirectionResultList.Clear();
for (int i = 0; i < result.RouteSegments.Count; i++)
{
RouteDirectionViewModel routeDirection = new RouteDirectionViewModel(result.RouteSegments[i], result.Features[i], roadColumnName, mapControl.MapUnit, distanceUnit);
DirectionResultList.Add(routeDirection);
}
routingOverlay.Refresh();
IsBusy = false;
}));
});
}));
}
}
public CommandBase InverseDestinationCommand
{
get
{
return inverseDestinationCommand ?? (inverseDestinationCommand = new CommandBase(obj =>
{
PointShape end = StartPoint;
StartPoint = EndPoint;
EndPoint = end;
routingOverlay.Refresh();
}));
}
}
private void InitializeMap()
{
routingShapeFile = new ShapeFileFeatureLayer(austinStreetShapeFile);
mapControl.MapUnit = GeographyUnit.DecimalDegree;
mapControl.CurrentExtent = defaultExtent;
mapControl.MapTools.MouseCoordinate.IsEnabled = true;
mapControl.MapTools.MouseCoordinate.MouseCoordinateType = MouseCoordinateType.Custom;
mapControl.MapTools.MouseCoordinate.CustomFormatted += MouseCoordinate_CustomFormatted;
mapControl.MapTools.PanZoomBar.GlobeButtonClick += (s, e) => e.NewExtent = defaultExtent;
mapControl.TrackOverlay.TrackEnded += TrackOverlay_TrackEnded;
mapControl.PreviewMouseRightButtonDown += MapControl_PreviewMouseRightButtonDown;
//Init Backgound Layer
mapControl.Overlays.Add("WorldMapKit", new WorldMapKitWmsWpfOverlay());
//Init RoutingOverlay
routingOverlay = new LayerOverlay();
mapControl.Overlays.Add("RoutingOverlay", routingOverlay);
routingLayer = new RoutingLayer();
routingLayer.StartPointStyle = new PointStyle(GetMarkerImage("start"));
routingLayer.EndPointStyle = new PointStyle(GetMarkerImage("end"));
routingLayer.StopPointStyle = new PointStyle(GetMarkerImage("stop"));
routingLayer.StopPointStyle.YOffsetInPixel = -10;
routingLayer.StopTextStyle.TextSolidBrush.Color = GeoColor.StandardColors.White;
routingLayer.StopTextStyle.Font = new GeoFont("Arial", 10);
routingLayer.XOffsetInPixelOfStopOrder = -3;
routingLayer.YOffsetInPixelOfStopOrder = 14;
routingOverlay.Layers.Add("RoutingLayer", routingLayer);
barrierLayer = new InMemoryFeatureLayer();
barrierLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(100, GeoColor.SimpleColors.Red), GeoColor.SimpleColors.Red, 1);
barrierLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
routingOverlay.Layers.Add("BarrierLayer", barrierLayer);
//Init restrictedOverlay
LayerOverlay restrictedOverlay = new LayerOverlay();
mapControl.Overlays.Add("RestrictedOverlay", restrictedOverlay);
restrictedLayer = new ShapeFileFeatureLayer(austinCountyShapeFile);
restrictedLayer.Open();
restrictedPolygon = (MultipolygonShape)restrictedLayer.QueryTools.GetAllFeatures(ReturningColumnsType.AllColumns)[0].GetShape();
AreaStyle extentStyle = new AreaStyle();
extentStyle.CustomAreaStyles.Add(new AreaStyle(new GeoSolidBrush(GeoColor.SimpleColors.Transparent)) { OutlinePen = new GeoPen(GeoColor.SimpleColors.White, 9.5f) });
extentStyle.CustomAreaStyles.Add(new AreaStyle(new GeoSolidBrush(GeoColor.SimpleColors.Transparent)) { OutlinePen = new GeoPen(GeoColor.SimpleColors.Red, 1.5f) { DashStyle = LineDashStyle.Dash } });
restrictedLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = extentStyle;
restrictedLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
restrictedOverlay.Layers.Add("RestrictedLayer", restrictedLayer);
// Scale bar layer
ScaleBarAdornmentLayer scaleBarAdormentLayer = new ScaleBarAdornmentLayer();
scaleBarAdormentLayer.Location = AdornmentLocation.LowerLeft;
scaleBarAdormentLayer.XOffsetInPixel = 10;
mapControl.AdornmentOverlay.Layers.Add("ScaleBar", scaleBarAdormentLayer);
mapControl.Refresh();
}
private void SyncStopsToRouteLayer(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals("Location"))
{
routingLayer.StopPoints.Clear();
foreach (var item in StopItems)
{
routingLayer.StopPoints.Add(item.Location);
}
}
}
private void LocationItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
for (int i = 0; i < stopItems.Count; i++)
{
StopItems[i].MarkerImageSource = GetMarkerImageSource(i + 1);
}
}
private void MouseCoordinate_CustomFormatted(object sender, CustomFormattedMouseCoordinateMapToolEventArgs e)
{
CoordinateX = e.WorldCoordinate.X;
CoordinateY = e.WorldCoordinate.Y;
}
private void TrackOverlay_TrackEnded(object sender, TrackEndedTrackInteractiveOverlayEventArgs e)
{
if (mapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Count > 0)
{
PolygonShape trackedPolygonShape = mapControl.TrackOverlay.TrackShapeLayer.InternalFeatures[0].GetShape() as PolygonShape;
if (trackedPolygonShape != null && trackedPolygonShape.IsWithin(restrictedPolygon))
{
barrierLayer.InternalFeatures.Add(mapControl.TrackOverlay.TrackShapeLayer.InternalFeatures[0]);
}
else
{
MessageBox.Show("Please note that this sample map is only able to analyze service areas within the Austin city limits, which are indicated by a dashed red line. Click inside that boundary for best results.", "Draw Area");
}
mapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Clear();
}
routingShapeFile.Open();
avoidableFeatureIds.Clear();
foreach (Feature feature in barrierLayer.InternalFeatures)
{
Collection features = routingShapeFile.FeatureSource.GetFeaturesWithinDistanceOf(feature, mapControl.MapUnit, DistanceUnit.Meter, 1, ReturningColumnsType.NoColumns);
foreach (Feature avoidableFeature in features.Where(f => !avoidableFeatureIds.Contains(f.Id)))
{
avoidableFeatureIds.Add(avoidableFeature.Id);
}
}
routingOverlay.Refresh();
}
private void MapControl_PreviewMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
Point menuRouteMouseLocation = e.GetPosition(mapControl);
ScreenPointF mouseScreenPoint = new ScreenPointF((float)menuRouteMouseLocation.X, (float)menuRouteMouseLocation.Y);
routeLocationPoint = ExtentHelper.ToWorldCoordinate(mapControl.CurrentExtent, mouseScreenPoint, (float)mapControl.ActualWidth, (float)mapControl.ActualHeight);
}
private static GeoImage GetMarkerImage(string imageName)
{
string url = string.Format(CultureInfo.InvariantCulture, "pack://application:,,,/CityRoutingAndDirections;Component/Image/{0}.png", imageName);
return new GeoImage(Application.GetResourceStream(new Uri(url, UriKind.RelativeOrAbsolute)).Stream);
}
private static BitmapImage GetMarkerImageSource(int index)
{
System.Drawing.Bitmap bitmap = null;
System.Drawing.Graphics g = null;
try
{
Uri stopImageUri = new Uri("pack://application:,,,/CityRoutingAndDirections;Component/Image/stop.png", UriKind.RelativeOrAbsolute);
bitmap = new System.Drawing.Bitmap(Application.GetResourceStream(stopImageUri).Stream);
g = System.Drawing.Graphics.FromImage(bitmap);
string currentIndex = index.ToString(CultureInfo.InvariantCulture);
System.Drawing.Font font = new System.Drawing.Font("Segoe UI", 10, System.Drawing.FontStyle.Bold);
System.Drawing.SizeF size = g.MeasureString(currentIndex, font);
g.DrawString(currentIndex, font, new System.Drawing.SolidBrush(System.Drawing.Color.White), new System.Drawing.PointF((bitmap.Width - size.Width) / 2, 0));
MemoryStream ms = new MemoryStream();
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byte[] bytes = ms.GetBuffer();
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = new MemoryStream(bytes);
bitmapImage.EndInit();
return bitmapImage;
}
finally
{
if (bitmap != null) bitmap.Dispose();
if (g != null) g.Dispose();
}
}
private enum RoutePriority
{
Shortest = 0,
Fastest = 1
}
}
}
====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 FeatureSource BarrierFeatureSource
{
get { return barrierFeatureSource; }
set { barrierFeatureSource = value; }
}
public List AvoidableFeatureIds
{
get { return avoidableFeatureIds; }
}
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 static 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);
}
}
}
}
}
====StopItemViewModel.cs====
using System;
using System.Windows.Media.Imaging;
using ThinkGeo.MapSuite.Core;
namespace ThinkGeo.MapSuite.RoutingExamples
{
public class StopItemViewModel : ViewModelBase
{
private const string markerImageSourceUri = "pack://application:,,,/CityRoutingAndDirections;Component/Image/stop.png";
private BitmapImage markerImageSource;
private PointShape location;
public StopItemViewModel()
: this(null)
{ }
public StopItemViewModel(PointShape location)
{
this.location = location;
this.MarkerImageSource = new BitmapImage(new Uri(markerImageSourceUri, UriKind.RelativeOrAbsolute));
}
public BitmapImage MarkerImageSource
{
get { return markerImageSource; }
set
{
markerImageSource = value;
RaisePropertyChanged(() => MarkerImageSource);
}
}
public PointShape Location
{
get { return location; }
set
{
location = value;
RaisePropertyChanged(() => Location);
}
}
}
}