Update 1.0.7
This commit is contained in:
Родитель
8b8c7f8ee5
Коммит
321a36e2ca
|
@ -2,7 +2,7 @@
|
|||
<package xmlns="http://schemas.microsoft.com/packaging/2013/01/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>BingMapsRESTToolkit</id>
|
||||
<version>1.0.6</version>
|
||||
<version>1.0.7</version>
|
||||
<title>Bing Maps REST Services Toolkit</title>
|
||||
<authors>Microsoft</authors>
|
||||
<owners>microsoft bingmaps</owners>
|
||||
|
|
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -1,4 +1,9 @@
|
|||
## Version 1.0.6 ##
|
||||
## Version 1.0.7
|
||||
|
||||
* Extended the RouteRequest class so that it can support more than 25 waypoints. It will simply break the request up into multiple sub-requests, process them, then merge the responses together.
|
||||
* Bug fix for Distance Matrix waypoint geocoding.
|
||||
|
||||
## Version 1.0.6
|
||||
|
||||
* Created a .NET Standard v1.4 assembly.
|
||||
* Add Custom Map Styles support for static images.
|
||||
|
@ -7,22 +12,22 @@
|
|||
* Add Execute method to all requests which contains custom business logic for processing each request. No need to use the ServiceManager now.
|
||||
* Add new imagery types; AerialWithLabelsOnDemand, BirdseyeV2, BirdseyeV2WithLabels, CanvasGray, CanvasDark, CanvasLight, and RoadOnDemand.
|
||||
|
||||
## Version 1.0.5 - 3/22/2017 ##
|
||||
## Version 1.0.5 - 3/22/2017
|
||||
|
||||
* Add support for Geospatial Endpoint service.
|
||||
|
||||
## Version 1.0.4 - 2/16/2017 ##
|
||||
## Version 1.0.4 - 2/16/2017
|
||||
|
||||
* Added support for catching network related exceptions.
|
||||
|
||||
## Version 1.0.3 - 2/15/2017 ##
|
||||
## Version 1.0.3 - 2/15/2017
|
||||
|
||||
* Added Globalization support for coordinates.
|
||||
|
||||
## Version 1.0.2 - 2/8/2017 ##
|
||||
## Version 1.0.2 - 2/8/2017
|
||||
|
||||
* Removed DetailAddress class and replaced with the standard Address class.
|
||||
|
||||
## Version 1.0.1 - 1/30/2017 ##
|
||||
## Version 1.0.1 - 1/30/2017
|
||||
|
||||
* Added Imagery Providers to response classes.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
![Bing Maps Logo](https://github.com/Microsoft/Bing-Maps-V8-TypeScript-Definitions/blob/master/images/BingMapsLogoTeal.png)
|
||||
|
||||
[![NuGet](https://img.shields.io/badge/NuGet-1.0.6-blue.svg)](https://www.nuget.org/packages/BingMapsRESTToolkit)
|
||||
[![NuGet](https://img.shields.io/badge/NuGet-1.0.7-blue.svg)](https://www.nuget.org/packages/BingMapsRESTToolkit)
|
||||
[![license](https://img.shields.io/badge/license-MIT-yellow.svg)](https://github.com/Microsoft/BingMapsRESTToolkit/blob/master/LICENSE.md)
|
||||
|
||||
# Bing Maps REST Toolkit for .NET #
|
||||
|
@ -14,6 +14,7 @@ This is a portable .NET class library which provides a set of tools that make it
|
|||
* Handles errors and rate limiting by catching exception and returning response with error message.
|
||||
* Automatically determines when a POST request should be made instead of a GET request.
|
||||
* Fast indexed lookups of Distance Matrix results.
|
||||
* Supports calculating routes of any size.
|
||||
|
||||
## NuGet Package ##
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
<Button Content="Reverse Geocode" Click="ReverseGeocodeBtn_Clicked" Height="30"/>
|
||||
<Button Content="Elevation" Click="ElevationBtn_Clicked" Height="30"/>
|
||||
<Button Content="Route" Click="RouteBtn_Clicked" Height="30"/>
|
||||
<Button Content="Long Route" Click="LongRouteBtn_Clicked" Height="30"/>
|
||||
<Button Content="Transit Route" Click="TransitRouteBtn_Clicked" Height="30"/>
|
||||
<Button Content="Traffic" Click="TrafficBtn_Clicked" Height="30"/>
|
||||
<Button Content="Imagery Metadata" Click="ImageMetadataBtn_Clicked" Height="30"/>
|
||||
|
|
|
@ -167,6 +167,68 @@ namespace RESTToolkitTestApp
|
|||
ProcessRequest(r);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Demostrates how to make a Driving Route Request that has more than 25 waypoints.
|
||||
/// </summary>
|
||||
private void LongRouteBtn_Clicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var r = new RouteRequest()
|
||||
{
|
||||
RouteOptions = new RouteOptions()
|
||||
{
|
||||
Avoid = new List<AvoidType>()
|
||||
{
|
||||
AvoidType.MinimizeTolls
|
||||
},
|
||||
TravelMode = TravelModeType.Driving,
|
||||
DistanceUnits = DistanceUnitType.Miles,
|
||||
Heading = 45,
|
||||
RouteAttributes = new List<RouteAttributeType>()
|
||||
{
|
||||
RouteAttributeType.RoutePath
|
||||
},
|
||||
Optimize = RouteOptimizationType.TimeWithTraffic
|
||||
},
|
||||
Waypoints = new List<SimpleWaypoint>() //29 waypoints, more than what the routing service normally handles, so the request will break this up into two requests and merge the results.
|
||||
{
|
||||
new SimpleWaypoint(47.5886, -122.336),
|
||||
new SimpleWaypoint(47.5553, -122.334),
|
||||
new SimpleWaypoint(47.5557, -122.316),
|
||||
new SimpleWaypoint(47.5428, -122.322),
|
||||
new SimpleWaypoint(47.5425, -122.341),
|
||||
new SimpleWaypoint(47.5538, -122.362),
|
||||
new SimpleWaypoint(47.5647, -122.384),
|
||||
new SimpleWaypoint(47.5309, -122.380),
|
||||
new SimpleWaypoint(47.5261, -122.351),
|
||||
new SimpleWaypoint(47.5137, -122.382),
|
||||
new SimpleWaypoint(47.5101, -122.337),
|
||||
new SimpleWaypoint(47.4901, -122.341),
|
||||
new SimpleWaypoint(47.4850, -122.320),
|
||||
new SimpleWaypoint(47.5024, -122.263),
|
||||
new SimpleWaypoint(47.4970, -122.226),
|
||||
new SimpleWaypoint(47.4736, -122.265),
|
||||
new SimpleWaypoint(47.4562, -122.287),
|
||||
new SimpleWaypoint(47.4452, -122.338),
|
||||
new SimpleWaypoint(47.4237, -122.292),
|
||||
new SimpleWaypoint(47.4230, -122.257),
|
||||
new SimpleWaypoint(47.3974, -122.249),
|
||||
new SimpleWaypoint(47.3765, -122.277),
|
||||
new SimpleWaypoint(47.3459, -122.302),
|
||||
new SimpleWaypoint(47.3073, -122.280),
|
||||
new SimpleWaypoint(47.3115, -122.228),
|
||||
new SimpleWaypoint(47.2862, -122.218),
|
||||
new SimpleWaypoint(47.2714, -122.294),
|
||||
new SimpleWaypoint(47.2353, -122.306),
|
||||
new SimpleWaypoint(47.1912, -122.408)
|
||||
},
|
||||
BingMapsKey = BingMapsKey
|
||||
};
|
||||
|
||||
ProcessRequest(r);
|
||||
|
||||
RequestUrlTbx.Text = "Request broken up into multiple sub-requests.";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Demostrates how to make a Transit Route Request.
|
||||
/// </summary>
|
||||
|
@ -392,7 +454,7 @@ namespace RESTToolkitTestApp
|
|||
/// <summary>
|
||||
/// Demostrates how to make a Distance Matrix Request.
|
||||
/// </summary>
|
||||
private async void DistanceMatrixBtn_Clicked(object sender, RoutedEventArgs e)
|
||||
private void DistanceMatrixBtn_Clicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var r = new DistanceMatrixRequest()
|
||||
{
|
||||
|
@ -409,7 +471,8 @@ namespace RESTToolkitTestApp
|
|||
},
|
||||
BingMapsKey = BingMapsKey,
|
||||
TimeUnits = TimeUnitType.Minutes,
|
||||
DistanceUnits = DistanceUnitType.Miles
|
||||
DistanceUnits = DistanceUnitType.Miles,
|
||||
TravelMode = TravelModeType.Transit
|
||||
};
|
||||
|
||||
ProcessRequest(r);
|
||||
|
@ -446,6 +509,10 @@ namespace RESTToolkitTestApp
|
|||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// This method has a lot of logic that is specific to the sample. To process a request you can easily just call the Execute method on the request.
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
private async void ProcessRequest(BaseRestRequest request)
|
||||
{
|
||||
try
|
||||
|
@ -455,8 +522,6 @@ namespace RESTToolkitTestApp
|
|||
|
||||
ResultTreeView.ItemsSource = null;
|
||||
|
||||
RequestUrlTbx.Text = request.GetRequestUrl();
|
||||
|
||||
var start = DateTime.Now;
|
||||
|
||||
//Execute the request.
|
||||
|
@ -472,6 +537,8 @@ namespace RESTToolkitTestApp
|
|||
}
|
||||
});
|
||||
|
||||
RequestUrlTbx.Text = request.GetRequestUrl();
|
||||
|
||||
var end = DateTime.Now;
|
||||
|
||||
var processingTime = end - start;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard1.4</TargetFramework>
|
||||
<Version>1.0.6</Version>
|
||||
<Version>1.0.7</Version>
|
||||
<Authors>Microsoft</Authors>
|
||||
<Company>Microsoft</Company>
|
||||
<Description>A toolkit that makes it easy to access the Bing Maps REST services from .NET</Description>
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BingMapsRESTToolkit
|
||||
{
|
||||
|
|
|
@ -38,6 +38,62 @@ namespace BingMapsRESTToolkit
|
|||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
/// <summary>
|
||||
/// A pushpin that is rendered on a static map image.
|
||||
/// </summary>
|
||||
public ImageryPushpin()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A pushpin that is rendered on a static map image.
|
||||
/// </summary>
|
||||
/// <param name="latitude">The latitude coordinate.</param>
|
||||
/// <param name="longitude">The longitude coordinate.</param>
|
||||
public ImageryPushpin(double latitude, double longitude):
|
||||
this(new Coordinate(latitude, longitude), 1, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A pushpin that is rendered on a static map image.
|
||||
/// </summary>
|
||||
/// <param name="coord">The coordinate where to position the pushpin.</param>
|
||||
public ImageryPushpin(Coordinate coord) :
|
||||
this(coord, 1, null)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A pushpin that is rendered on a static map image.
|
||||
/// </summary>
|
||||
/// <param name="latitude">The latitude coordinate.</param>
|
||||
/// <param name="longitude">The longitude coordinate.</param>
|
||||
/// <param name="iconStyle">The style of icon to render as a pushpin.</param>
|
||||
/// <param name="label">The label to put on top of the pushpin.</param>
|
||||
public ImageryPushpin(double latitude, double longitude, int iconStyle, string label):
|
||||
this(new Coordinate(latitude, longitude), iconStyle, label)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A pushpin that is rendered on a static map image.
|
||||
/// </summary>
|
||||
/// <param name="coord">The coordinate where to position the pushpin.</param>
|
||||
/// <param name="iconStyle">The style of icon to render as a pushpin.</param>
|
||||
/// <param name="label">The label to put on top of the pushpin.</param>
|
||||
public ImageryPushpin(Coordinate coord, int iconStyle, string label)
|
||||
{
|
||||
this.label = label;
|
||||
this.iconStyle = iconStyle;
|
||||
this.Location = coord;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -174,7 +174,7 @@ namespace BingMapsRESTToolkit
|
|||
|
||||
#region Internal Methods
|
||||
|
||||
internal string GetUrlParam()
|
||||
internal string GetUrlParam(int startIdx)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
|
@ -198,14 +198,17 @@ namespace BingMapsRESTToolkit
|
|||
}
|
||||
}
|
||||
|
||||
if (TravelMode == TravelModeType.Driving && distanceBeforeFirstTurn > 0)
|
||||
if (startIdx == 0)
|
||||
{
|
||||
sb.AppendFormat("&dbft={0}", distanceBeforeFirstTurn);
|
||||
}
|
||||
if (TravelMode == TravelModeType.Driving && distanceBeforeFirstTurn > 0)
|
||||
{
|
||||
sb.AppendFormat("&dbft={0}", distanceBeforeFirstTurn);
|
||||
}
|
||||
|
||||
if (heading > 0)
|
||||
{
|
||||
sb.AppendFormat("&hd={0}", heading);
|
||||
if (heading > 0)
|
||||
{
|
||||
sb.AppendFormat("&hd={0}", heading);
|
||||
}
|
||||
}
|
||||
|
||||
if (DistanceUnits != DistanceUnitType.Kilometers)
|
||||
|
@ -258,7 +261,7 @@ namespace BingMapsRESTToolkit
|
|||
}
|
||||
}
|
||||
|
||||
if (TravelMode != TravelModeType.Walking)
|
||||
if (TravelMode != TravelModeType.Walking)
|
||||
{
|
||||
sb.AppendFormat("&maxSolns={0}", maxSolutions);
|
||||
}
|
||||
|
|
|
@ -180,45 +180,42 @@ namespace BingMapsRESTToolkit
|
|||
/// <param name="waypoint">The simple waypoint to geocode.</param>
|
||||
/// <param name="baseRequest">A base request that has the information need to perform a geocode, primarily a Bing Maps key.</param>
|
||||
/// <returns>A Task in which the simple waypoint will be geocoded.</returns>
|
||||
internal static Task TryGeocode(SimpleWaypoint waypoint, BaseRestRequest baseRequest)
|
||||
internal static async Task TryGeocode(SimpleWaypoint waypoint, BaseRestRequest baseRequest)
|
||||
{
|
||||
return new Task(async () =>
|
||||
if (waypoint != null && waypoint.Coordinate == null && !string.IsNullOrEmpty(waypoint.Address))
|
||||
{
|
||||
if (waypoint != null && waypoint.Coordinate == null && !string.IsNullOrEmpty(waypoint.Address))
|
||||
var request = new GeocodeRequest()
|
||||
{
|
||||
var request = new GeocodeRequest()
|
||||
{
|
||||
Query = waypoint.Address,
|
||||
MaxResults = 1,
|
||||
BingMapsKey = baseRequest.BingMapsKey,
|
||||
Culture = baseRequest.Culture,
|
||||
Domain = baseRequest.Domain,
|
||||
UserIp = baseRequest.UserIp,
|
||||
UserLocation = baseRequest.UserLocation,
|
||||
UserMapView = baseRequest.UserMapView,
|
||||
UserRegion = baseRequest.UserRegion
|
||||
};
|
||||
Query = waypoint.Address,
|
||||
MaxResults = 1,
|
||||
BingMapsKey = baseRequest.BingMapsKey,
|
||||
Culture = baseRequest.Culture,
|
||||
Domain = baseRequest.Domain,
|
||||
UserIp = baseRequest.UserIp,
|
||||
UserLocation = baseRequest.UserLocation,
|
||||
UserMapView = baseRequest.UserMapView,
|
||||
UserRegion = baseRequest.UserRegion
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var r = await ServiceManager.GetResponseAsync(request);
|
||||
try
|
||||
{
|
||||
var r = await ServiceManager.GetResponseAsync(request);
|
||||
|
||||
if (r != null && r.ResourceSets != null &&
|
||||
r.ResourceSets.Length > 0 &&
|
||||
r.ResourceSets[0].Resources != null &&
|
||||
r.ResourceSets[0].Resources.Length > 0)
|
||||
{
|
||||
var l = r.ResourceSets[0].Resources[0] as Location;
|
||||
|
||||
waypoint.Coordinate = new Coordinate(l.Point.Coordinates[0], l.Point.Coordinates[1]);
|
||||
}
|
||||
}
|
||||
catch
|
||||
if (r != null && r.ResourceSets != null &&
|
||||
r.ResourceSets.Length > 0 &&
|
||||
r.ResourceSets[0].Resources != null &&
|
||||
r.ResourceSets[0].Resources.Length > 0)
|
||||
{
|
||||
//Do nothing.
|
||||
var l = r.ResourceSets[0].Resources[0] as Location;
|
||||
|
||||
waypoint.Coordinate = new Coordinate(l.Point.Coordinates[0], l.Point.Coordinates[1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
catch
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -26,5 +26,5 @@ using System.Runtime.InteropServices;
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.6.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.6.0")]
|
||||
[assembly: AssemblyVersion("1.0.7.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.7.0")]
|
||||
|
|
|
@ -368,7 +368,7 @@ namespace BingMapsRESTToolkit
|
|||
|
||||
if (RouteOptions != null)
|
||||
{
|
||||
sb.Append(RouteOptions.GetUrlParam());
|
||||
sb.Append(RouteOptions.GetUrlParam(0));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
|
||||
namespace BingMapsRESTToolkit
|
||||
{
|
||||
|
@ -39,7 +41,7 @@ namespace BingMapsRESTToolkit
|
|||
/// <summary>
|
||||
/// Specifies two or more locations that define the route and that are in sequential order.
|
||||
/// A route is defined by a set of waypoints and viaWaypoints (intermediate locations that the route must pass through).
|
||||
/// You can have a maximum of 25 waypoints, and a maximum of 10 viaWaypoints between each set of waypoints.
|
||||
/// You can have a maximum of 10 viaWaypoints between each set of waypoints.
|
||||
/// The start and end points of the route cannot be viaWaypoints.
|
||||
/// </summary>
|
||||
public List<SimpleWaypoint> Waypoints { get; set; }
|
||||
|
@ -49,12 +51,143 @@ namespace BingMapsRESTToolkit
|
|||
/// </summary>
|
||||
public RouteOptions RouteOptions { get; set; }
|
||||
|
||||
private int batchSize = 25;
|
||||
|
||||
/// <summary>
|
||||
/// The maximium number of waypoints that can be in a single request. If the batchSize is smaller than the number of waypoints, when the request is executed, it will break the request up into multiple requests. Must by between 2 and 25. Default: 25.
|
||||
/// </summary>
|
||||
public int BatchSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return batchSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
if(value >=2 && value <= 25)
|
||||
{
|
||||
batchSize = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets the request URL to perform a query for route directions.
|
||||
/// Executes the request. If there are more waypoints than the batchSize value (default 25), only a MaxSolutions is set to 1, and Tolerances is set to null.
|
||||
/// </summary>
|
||||
/// <returns>A response containing the requested data.</returns>
|
||||
public override async Task<Response> Execute()
|
||||
{
|
||||
return await this.Execute(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the request. If there are more waypoints than the batchSize value (default 25), only a MaxSolutions is set to 1, and Tolerances is set to null.
|
||||
/// </summary>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time is sent.</param>
|
||||
/// <returns>A response containing the requested data.</returns>
|
||||
public override async Task<Response> Execute(Action<int> remainingTimeCallback)
|
||||
{
|
||||
if(Waypoints.Count <= batchSize)
|
||||
{
|
||||
return await base.Execute();
|
||||
}
|
||||
|
||||
//There is more waypoints than the batchSize value (default 25), break it up into multiple requests. Only allow a single route in the response and no tolerances.
|
||||
if (RouteOptions != null)
|
||||
{
|
||||
if (RouteOptions.MaxSolutions > 1)
|
||||
{
|
||||
RouteOptions.MaxSolutions = 1;
|
||||
}
|
||||
|
||||
RouteOptions.Tolerances = null;
|
||||
}
|
||||
|
||||
if (Waypoints == null)
|
||||
{
|
||||
throw new Exception("Waypoints not specified.");
|
||||
}
|
||||
else if (Waypoints.Count < 2)
|
||||
{
|
||||
throw new Exception("Not enough Waypoints specified.");
|
||||
}
|
||||
else if (Waypoints[0].IsViaPoint || Waypoints[Waypoints.Count - 1].IsViaPoint)
|
||||
{
|
||||
throw new Exception("Start and end waypoints must not be ViaWaypoints.");
|
||||
}
|
||||
|
||||
int startIdx = 0;
|
||||
int endIdx = 0;
|
||||
|
||||
var requestUrls = new List<string>();
|
||||
|
||||
while (endIdx < Waypoints.Count - 1)
|
||||
{
|
||||
requestUrls.Add(GetRequestUrl(startIdx, out endIdx));
|
||||
startIdx = endIdx - 1;
|
||||
}
|
||||
|
||||
var routes = new Route[requestUrls.Count];
|
||||
Response response = null;
|
||||
Response errorResponse = null;
|
||||
|
||||
Parallel.For(0, requestUrls.Count, (i) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
//Make the call synchronously as we are in a parrallel for loop and need this to block, otherwise the for loop will exist before the async code has completed.
|
||||
using (var responseStream = ServiceHelper.GetStreamAsync(new Uri(requestUrls[i])).GetAwaiter().GetResult())
|
||||
{
|
||||
var r = ServiceHelper.DeserializeStream<Response>(responseStream);
|
||||
|
||||
if (r != null)
|
||||
{
|
||||
if (r.ErrorDetails != null && r.ErrorDetails.Length > 0)
|
||||
{
|
||||
errorResponse = r;
|
||||
}
|
||||
else if (r.ResourceSets != null && r.ResourceSets.Length > 0 &&
|
||||
r.ResourceSets[0].Resources != null && r.ResourceSets[0].Resources.Length > 0)
|
||||
{
|
||||
routes[i] = r.ResourceSets[0].Resources[0] as Route;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
response = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorResponse = new Response()
|
||||
{
|
||||
ErrorDetails = new string[]
|
||||
{
|
||||
ex.Message
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
//If any of the responses failed to process, do not merge results, return the error info.
|
||||
if(errorResponse != null)
|
||||
{
|
||||
return errorResponse;
|
||||
}
|
||||
|
||||
response.ResourceSets[0].Resources[0] = await MergeRoutes(routes);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the request URL to perform a query for route directions. This method will only generate a URL that includes the first batchSize waypoints in the request.
|
||||
/// </summary>
|
||||
/// <returns>A request URL to perform a query for route directions.</returns>
|
||||
public override string GetRequestUrl()
|
||||
|
@ -74,6 +207,23 @@ namespace BingMapsRESTToolkit
|
|||
throw new Exception("Start and end waypoints must not be ViaWaypoints.");
|
||||
}
|
||||
|
||||
int endIdx;
|
||||
|
||||
return GetRequestUrl(0, out endIdx);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Generates a route REST request
|
||||
/// </summary>
|
||||
/// <param name="startIdx"></param>
|
||||
/// <param name="endIdx"></param>
|
||||
/// <returns></returns>
|
||||
private string GetRequestUrl(int startIdx, out int endIdx)
|
||||
{
|
||||
endIdx = Waypoints.Count;
|
||||
|
||||
var sb = new StringBuilder(this.Domain);
|
||||
|
||||
var TravelMode = (RouteOptions != null) ? RouteOptions.TravelMode : TravelModeType.Driving;
|
||||
|
@ -82,11 +232,11 @@ namespace BingMapsRESTToolkit
|
|||
|
||||
int wayCnt = 0, viaCnt = 0;
|
||||
|
||||
for (int i = 0; i < Waypoints.Count; i++)
|
||||
for (int i = startIdx; i < Waypoints.Count; i++)
|
||||
{
|
||||
if (Waypoints[i].IsViaPoint)
|
||||
{
|
||||
sb.AppendFormat("&vwp.{0}=", i);
|
||||
sb.AppendFormat("&vwp.{0}=", i - startIdx);
|
||||
viaCnt++;
|
||||
|
||||
if (TravelMode == TravelModeType.Transit)
|
||||
|
@ -96,7 +246,7 @@ namespace BingMapsRESTToolkit
|
|||
}
|
||||
else
|
||||
{
|
||||
sb.AppendFormat("&wp.{0}=", i);
|
||||
sb.AppendFormat("&wp.{0}=", i - startIdx);
|
||||
|
||||
if (viaCnt > 10)
|
||||
{
|
||||
|
@ -115,23 +265,115 @@ namespace BingMapsRESTToolkit
|
|||
{
|
||||
sb.AppendFormat("{0}", Uri.EscapeDataString(Waypoints[i].Address));
|
||||
}
|
||||
}
|
||||
|
||||
if (wayCnt > 25)
|
||||
{
|
||||
throw new Exception("More than 25 waypoints in route request.");
|
||||
//Only allow up to the batchSize waypoints in a request.
|
||||
if (wayCnt == batchSize)
|
||||
{
|
||||
endIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (RouteOptions != null)
|
||||
{
|
||||
sb.Append(RouteOptions.GetUrlParam());
|
||||
}
|
||||
sb.Append(RouteOptions.GetUrlParam(startIdx));
|
||||
}
|
||||
|
||||
sb.Append(GetBaseRequestUrl());
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// Merges an array of Route objects together into a single route object.
|
||||
/// </summary>
|
||||
/// <param name="routes">Array of Route objects to merge.</param>
|
||||
/// <returns>A single route that consists of all the merged routes.</returns>
|
||||
private Task<Route> MergeRoutes(Route[] routes)
|
||||
{
|
||||
return Task<Route>.Run(() =>
|
||||
{
|
||||
if (routes.Length > 0)
|
||||
{
|
||||
var mergedRoute = routes[0];
|
||||
|
||||
for (var i = 1; i < routes.Length; i++)
|
||||
{
|
||||
if (routes[i] != null)
|
||||
{
|
||||
mergedRoute.Id = null;
|
||||
|
||||
if (mergedRoute.BoundingBox != null)
|
||||
{
|
||||
if (routes[i].BoundingBox != null)
|
||||
{
|
||||
mergedRoute.BoundingBox[0] = Math.Min(mergedRoute.BoundingBox[0], routes[i].BoundingBox[0]);
|
||||
mergedRoute.BoundingBox[1] = Math.Min(mergedRoute.BoundingBox[1], routes[i].BoundingBox[1]);
|
||||
mergedRoute.BoundingBox[2] = Math.Max(mergedRoute.BoundingBox[2], routes[i].BoundingBox[2]);
|
||||
mergedRoute.BoundingBox[3] = Math.Max(mergedRoute.BoundingBox[3], routes[i].BoundingBox[3]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mergedRoute.BoundingBox = routes[i].BoundingBox;
|
||||
}
|
||||
|
||||
int routePathOffset = (mergedRoute.RoutePath != null) ? mergedRoute.RoutePath.Line.Coordinates.Length : 0;
|
||||
|
||||
//Merge the route legs.
|
||||
var legs = mergedRoute.RouteLegs;
|
||||
|
||||
//Loop through each leg and offset path indicies to align with merged path.
|
||||
for (var j = 0; j < routes[i].RouteLegs.Length; j++)
|
||||
{
|
||||
for (var k = 0; k < routes[i].RouteLegs[j].ItineraryItems.Length; k++)
|
||||
{
|
||||
for (var l = 0; l < routes[i].RouteLegs[j].ItineraryItems[k].Details.Length; l++)
|
||||
{
|
||||
for (var m = 0; m < routes[i].RouteLegs[j].ItineraryItems[k].Details[l].EndPathIndices.Length; m++)
|
||||
{
|
||||
routes[i].RouteLegs[j].ItineraryItems[k].Details[l].EndPathIndices[m] += routePathOffset;
|
||||
}
|
||||
|
||||
for (var m = 0; m < routes[i].RouteLegs[j].ItineraryItems[k].Details[l].StartPathIndices.Length; m++)
|
||||
{
|
||||
routes[i].RouteLegs[j].ItineraryItems[k].Details[l].StartPathIndices[m] += routePathOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var k = 0; k < routes[i].RouteLegs[j].RouteSubLegs.Length; k++)
|
||||
{
|
||||
routes[i].RouteLegs[j].RouteSubLegs[k].EndWaypoint.RoutePathIndex += routePathOffset;
|
||||
routes[i].RouteLegs[j].RouteSubLegs[k].StartWaypoint.RoutePathIndex += routePathOffset;
|
||||
}
|
||||
}
|
||||
|
||||
mergedRoute.RouteLegs = mergedRoute.RouteLegs.Concat(routes[i].RouteLegs).ToArray();
|
||||
|
||||
if (mergedRoute.RoutePath != null)
|
||||
{
|
||||
if (routes[i].RoutePath != null)
|
||||
{
|
||||
mergedRoute.RoutePath.Line.Coordinates[0] = mergedRoute.RoutePath.Line.Coordinates[0].Concat(routes[i].RoutePath.Line.Coordinates[0]).ToArray();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mergedRoute.RoutePath = routes[i].RoutePath;
|
||||
}
|
||||
|
||||
mergedRoute.TravelDistance += routes[i].TravelDistance;
|
||||
mergedRoute.TravelDuration += routes[i].TravelDuration;
|
||||
mergedRoute.TravelDurationTraffic += routes[i].TravelDurationTraffic;
|
||||
}
|
||||
}
|
||||
|
||||
return mergedRoute;
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче