Update 1.1.0
This commit is contained in:
Родитель
e9d0c3ebb7
Коммит
8b1068b667
|
@ -2,7 +2,7 @@
|
|||
<package xmlns="http://schemas.microsoft.com/packaging/2013/01/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>BingMapsRESTToolkit</id>
|
||||
<version>1.0.9</version>
|
||||
<version>1.1.0</version>
|
||||
<title>Bing Maps REST Services Toolkit</title>
|
||||
<authors>Microsoft</authors>
|
||||
<owners>microsoft bingmaps</owners>
|
||||
|
@ -47,9 +47,9 @@
|
|||
<file src="..\Source\bin\Release\BingMapsRESTToolkit.dll" target="lib\net45\BingMapsRESTToolkit.dll" />
|
||||
<file src="..\Source\bin\Release\BingMapsRESTToolkit.pdb" target="lib\net45\BingMapsRESTToolkit.pdb" />
|
||||
<file src="..\Source\bin\Release\BingMapsRESTToolkit.XML" target="lib\net45\BingMapsRESTToolkit.XML" />
|
||||
<file src="..\Source\BingMapsRESTToolkit.Standard\bin\Release\netstandard1.4\BingMapsRESTToolkit.Standard.deps.json" target="lib\netstandard1.4\BingMapsRESTToolkit.Standard.deps.json" />
|
||||
<file src="..\Source\BingMapsRESTToolkit.Standard\bin\Release\netstandard1.4\BingMapsRESTToolkit.Standard.dll" target="lib\netstandard1.4\BingMapsRESTToolkit.Standard.dll" />
|
||||
<file src="..\Source\BingMapsRESTToolkit.Standard\bin\Release\netstandard1.4\BingMapsRESTToolkit.Standard.pdb" target="lib\netstandard1.4\BingMapsRESTToolkit.Standard.pdb" />
|
||||
<file src="..\Source\BingMapsRESTToolkit.Standard\bin\Release\netstandard2.0\BingMapsRESTToolkit.Standard.deps.json" target="lib\netstandard2.0\BingMapsRESTToolkit.Standard.deps.json" />
|
||||
<file src="..\Source\BingMapsRESTToolkit.Standard\bin\Release\netstandard2.0\BingMapsRESTToolkit.Standard.dll" target="lib\netstandard2.0\BingMapsRESTToolkit.Standard.dll" />
|
||||
<file src="..\Source\BingMapsRESTToolkit.Standard\bin\Release\netstandard2.0\BingMapsRESTToolkit.Standard.pdb" target="lib\netstandard2.0\BingMapsRESTToolkit.Standard.pdb" />
|
||||
<file src="..\Source\bin\Release\BingMapsRESTToolkit.dll" target="lib\portable-net45+wp8+win8\BingMapsRESTToolkit.dll" />
|
||||
<file src="..\Source\bin\Release\BingMapsRESTToolkit.pdb" target="lib\portable-net45+wp8+win8\BingMapsRESTToolkit.pdb" />
|
||||
<file src="..\Source\bin\Release\BingMapsRESTToolkit.XML" target="lib\portable-net45+wp8+win8\BingMapsRESTToolkit.XML" />
|
||||
|
|
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -1,9 +1,16 @@
|
|||
## Version 1.0.9 - 12/14/2017
|
||||
## Version 1.1.0 -
|
||||
|
||||
* .NET Standard Library support upgraded to v2.0.
|
||||
* Static Proxy setting option added to ServiceManager.
|
||||
* Truck routing based distance matrix support added (wraps truck routing service).
|
||||
* QPS limiting setting added to ServiceManager. Used for batch geocode and truck routing calls which occur with distance matrix.
|
||||
|
||||
## Version 1.0.9 - 12/14/2017
|
||||
|
||||
* Add support for Truck Routing API.
|
||||
* Add support for Isochrones API.
|
||||
* Add support for Snap to Road API.
|
||||
* Add Travelling Salesmen extension which includes 2 different TSP algorithms; greedy brute forcem and genetic approximation.
|
||||
* Add Travelling Salesmen extension which includes 2 different TSP algorithms; greedy brute force and genetic approximation.
|
||||
* Extended the RouteRequest class to support waypoint optimization as part of the request.
|
||||
* Added a WPF sample for the travelling salesmen which demostrates the ease of calculating a route with optimized waypoints.
|
||||
* Extended DistanceMatrix class with method to get edge/path (array of waypoint indicies to pass through) time/distance for easier analysis.
|
||||
|
|
|
@ -104,14 +104,15 @@ Abstract class that all Imagery rest requests will derive from. Inherits from th
|
|||
|
||||
| Name | Type | Description |
|
||||
|------------|-------------|
|
||||
| origins | List\<[SimpleWaypoint](#SimpleWaypoint)\> |**Required**. List of origins. |
|
||||
| destinations | List\<[SimpleWaypoint](#SimpleWaypoint)\> | **Required**. List of destinations. |
|
||||
| Origins | List\<[SimpleWaypoint](#SimpleWaypoint)\> |**Required**. List of origins. |
|
||||
| Destinations | List\<[SimpleWaypoint](#SimpleWaypoint)\> | **Required**. List of destinations. |
|
||||
| TravelMode | [TravelModeType](#TravelModeType) | **Required**. Specifies the mode of transportation to use when calculating the distance matrix. |
|
||||
| StartTime | DateTime | **Optional for Driving**. Specifies the start or departure time of the matrix to calculate and uses predictive traffic data. |
|
||||
| endTime | DateTime | **Optional for Driving**. If specified, a matrix based on traffic data with contain a histogram of travel times and distances for the specified resolution intervals (default is 15 minutes) between the start and end times. A start time must be specified for the request to be valid and the total time between start and end cannot be greater than 24 hours. |
|
||||
| resolution | int | **Optional for Driving**. The number of intervals to calculate a histogram of data for each cell where a single interval is a quarter of an hour. Can be one of the following values:<br/><br/> • **1** - 15 minutes<br/> • **2** - 30 minutes<br/> • **3** - 45 minutes<br/> • **4** - an hour<br/><br/>If start time is specified and `resolution` is not, it will default to an interval of 1 (15 minutes).<br/><br/>**Example**: resolution=2 |
|
||||
| distanceUnit | [DistanceUnitType](#DistanceUnitType) | **Optional.** The units to use for distances in the response. |
|
||||
| timeUnit | [TimeUnitType](#TimeUnitType) | **Optional.** The units to use for time durations in the response. |
|
||||
| EndTime | DateTime | **Optional for Driving**. If specified, a matrix based on traffic data with contain a histogram of travel times and distances for the specified resolution intervals (default is 15 minutes) between the start and end times. A start time must be specified for the request to be valid and the total time between start and end cannot be greater than 24 hours. |
|
||||
| Resolution | int | **Optional for Driving**. The number of intervals to calculate a histogram of data for each cell where a single interval is a quarter of an hour. Can be one of the following values:<br/><br/> • **1** - 15 minutes<br/> • **2** - 30 minutes<br/> • **3** - 45 minutes<br/> • **4** - an hour<br/><br/>If start time is specified and `resolution` is not, it will default to an interval of 1 (15 minutes).<br/><br/>**Example**: resolution=2 |
|
||||
| DistanceUnit | [DistanceUnitType](#DistanceUnitType) | **Optional.** The units to use for distances in the response. |
|
||||
| TimeUnit | [TimeUnitType](#TimeUnitType) | **Optional.** The units to use for time durations in the response. |
|
||||
| VehicleSpec | [VehicleSpec](#VehicleSpec) | Truck routing specific vehicle attribute. |
|
||||
|
||||
## <a name="ElevationRequest"></a> ElevationRequest Class
|
||||
|
||||
|
@ -469,6 +470,13 @@ A class that defines the options that can to use when calculating a route.
|
|||
|
||||
This is a static class that is used for processing all requests to the Bing Maps REST Services asynchronously. Note that all requests classes now have an Execute function which will retrun a Response object which can be used as an alternative.
|
||||
|
||||
### Static Properties
|
||||
|
||||
| Name | Type | Description |
|
||||
|---------------|-----------|---------------|
|
||||
| Proxy | IWebProxy | Proxy settings to be used when making web requests. |
|
||||
| QpsLimit | int | The number of queries per second to limit certain requests to. This is primarily used when batching multiple requests in a single process such as when geoeocidng all waypoints for the distance matrix API, or when manually generating a truck based distance matrix using the routing API. |
|
||||
|
||||
### Static Methods
|
||||
|
||||
| Name | Return Type | Description |
|
||||
|
@ -797,10 +805,10 @@ An indexing system has been added to the DistanceMatrix class to make it easy to
|
|||
| GetDistance(int originIdx, int destinationIdx, DateTime timeInterval) | double | Retrives the travel distance for a specified origin-destination pair and time interval. Returns -1 if a cell can not be found in the results or had an error in calculation. |
|
||||
| GetDistance(int originIdx, int destinationIdx, int timeIntervalIdx) | double | Retrives the travel distance for a specified origin-destination pair and time interval. Returns -1 if a cell can not be found in the results or had an error in calculation. |
|
||||
| GetDistances(int originIdx, int destinationIdx) | double[] | Gets all travel distances for the specified origin and destination index, ordered by time (ascending). |
|
||||
| GetEdgeDistance(int[] waypointIndicies) | double | Retrieves the total travel distance between all waypoints indicies which represent an edge (graph/path). |
|
||||
| GetEdgeDistance(int[] waypointIndicies, bool isRoundTrip) | double | Retrieves the total travel distance between all waypoints indicies which represent an edge (graph/path). |
|
||||
| GetEdgeTime(int[] waypointIndicies) | double | Retrieves the total travel time between all waypoints indicies which represent an edge (graph/path). |
|
||||
| GetEdgeTime(int[] waypointIndicies, bool isRoundTrip) | double | Retrieves the total travel time between all waypoints indicies which represent an edge (graph/path). |
|
||||
| GetEdgeDistance(int[] waypointIndicies) | double | Retrieves the total travel distance between all waypoints indicies which represent an edge (graph/path). If a path between to waypoints is not routable, a large distance value will be returned.|
|
||||
| GetEdgeDistance(int[] waypointIndicies, bool isRoundTrip) | double | Retrieves the total travel distance between all waypoints indicies which represent an edge (graph/path). If a path between to waypoints is not routable, a large distance value will be returned.|
|
||||
| GetEdgeTime(int[] waypointIndicies) | double | Retrieves the total travel time between all waypoints indicies which represent an edge (graph/path). If a path between to waypoints is not routable, a large time value will be returned. |
|
||||
| GetEdgeTime(int[] waypointIndicies, bool isRoundTrip) | double | Retrieves the total travel time between all waypoints indicies which represent an edge (graph/path). If a path between to waypoints is not routable, a large time value will be returned.|
|
||||
| GetTime(int originIdx, int destinationIdx) | double | Retrives the travel time for a specified origin-destination pair. Returns -1 if a cell can not be found in the results or had an error in calculation. |
|
||||
| GetTime(int originIdx, int destinationIdx, DateTime timeInterval) | double | Retrieves the travel time for a specified origin-destination pair and time interval. Returns -1 if a cell can not be found in the results or had an error in calculation. |
|
||||
| GetTime(int originIdx, int destinationIdx, int timeIntervalIdx) | double | Retrieves the travel time for a specified origin-destination pair and time interval. Returns -1 if a cell can not be found in the results or had an error in calculation. |
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* [Running the Samples](#RunningTheSamples)
|
||||
* [Adding the Bing Maps REST Toolkit to your project](#AddingToolkitToProject)
|
||||
* [How to make a Request to the REST services](#HowToMakeARequest)
|
||||
* [QPS Limits](#QPSLimits)
|
||||
* [Proxies](#Proxies)
|
||||
* [Travelling Salesmen Problem](#TravellingSalesmen)
|
||||
|
||||
The Bing Maps REST services allow you to query the raw data that powers Bing Maps. The Bing Maps REST Services Toolkit provides an easy to use .NET wrapper around these services. To keep things easy the request and response classes in this library are aligned with the structure of the [documented Bing Maps REST Services API](https://msdn.microsoft.com/en-us/library/ff701713.aspx).
|
||||
|
@ -191,7 +193,24 @@ using (var imageStream = await ServiceManager.GetImageAsync(request))
|
|||
}
|
||||
```
|
||||
|
||||
## <a name="TravellingSalesmen"></a> Travelling Salesmen Problem
|
||||
## <a name="QPSLimits"></a> QPS Limits
|
||||
|
||||
The Bing Maps platform allows basic accounts to generate up to 5 QPS (queries per second) and Enterprise accounts 50 QPS (enterprise accounts can upgrade to higher QPS levels). This library has a few methods which will make multiple requests to the Bing Maps platform;
|
||||
|
||||
* The SimpleWaypoint class has a `TryGeocodeWaypoints` method which will geocode an array of SimpleWaypoints.
|
||||
* The distance matrix API only accepts coordinates as waypoints, as such the `DistanceMatrixRequest` class will geocode all waypoints automatically if needed. Additionally, the distance matrix API does not support truck routing based matricies, but this library adds support by wrapping the truck routing service and making multiple requests to it.
|
||||
|
||||
Since these methods can generate a lot of requests in a short period of time, a static `QpsLimit` property has been added the `ServiceManager` class which will allow you to fine tune this value as needed. By default this value is set to 5. To change this value to 50 (or some other value), add the following line of code before your request.
|
||||
|
||||
```
|
||||
ServiceManager.QpsLimit = 50;
|
||||
```
|
||||
|
||||
## <a name="Proxies"></a> Proxies
|
||||
|
||||
Some networks require requests to go through a proxy. The `ServiceManager` class has a static `Proxy` property which can be used to specify web proxy settings.
|
||||
|
||||
## <a name="TravellingSalesmen"></a> Travelling Salesmen Problem
|
||||
|
||||
This toolkit provides some classes which wrap the routing and distance matrix API's and provides solutions for the [travelling salesmen problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem) (waypoint order optimization). You can optimize based on travel time, travel distance or straight line distance. When travel time/distance is specified, the distance matrix API which will generate Bing Maps transactions. For straight line distances, the haversine formula will be used to generate a matrix based on as-the-crow-flies distance between the waypoints.
|
||||
|
||||
|
|
28
README.md
28
README.md
|
@ -1,9 +1,9 @@
|
|||
![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.9-blue.svg)](https://www.nuget.org/packages/BingMapsRESTToolkit)
|
||||
[![NuGet](https://img.shields.io/badge/NuGet-1.1.0-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 #
|
||||
# Bing Maps REST Toolkit for .NET
|
||||
|
||||
This is a portable .NET class library which provides a set of tools that make it easy to access the Bing Maps REST services in .NET based apps. Take a look at the [Getting Started documentation](https://github.com/Microsoft/BingMapsRESTToolkit/blob/master/Docs/Getting%20Started.md). The Bing Maps REST Services provides the following functionality:
|
||||
|
||||
|
@ -16,7 +16,7 @@ This is a portable .NET class library which provides a set of tools that make it
|
|||
* **Elevation data**
|
||||
* **Static map imagery and metadata**
|
||||
|
||||
## Toolkit Features ##
|
||||
## Toolkit Features
|
||||
|
||||
* Uses HTTPS by default.
|
||||
* Implements the documented [best practices for Bing Maps](https://msdn.microsoft.com/en-us/library/dn894107.aspx). For example, it automatically encodes query parameters. A commonly overlooked stepped which greatly reduces the chances of invalid queries being sent to the service.
|
||||
|
@ -25,8 +25,9 @@ This is a portable .NET class library which provides a set of tools that make it
|
|||
* Fast indexed lookups of Distance Matrix results.
|
||||
* Supports calculating driving, walking and transit routes that have more than 25 waypoints.
|
||||
* **Travelling Salesmen** algorithms that tie into the distance matrix API [documentation](https://github.com/Microsoft/BingMapsRESTToolkit/blob/master/Docs/Getting%20Started.md#TravellingSalesmen).
|
||||
* **Truck routing based Distance Matricies** - The Bing Maps distance matric API does not support truck routing based matricies. This library adds support for this by wrapping the truck routing API.
|
||||
|
||||
## NuGet Package ##
|
||||
## NuGet Package
|
||||
|
||||
The Bing Maps REST Services Toolkit is available as a [NuGet package](https://www.nuget.org/packages/BingMapsRESTToolkit). If using Visual Studio, open the nuget package manager, select the Browse tab and search for "Bing Maps REST". This should reduce the list of results enough to find the "BingMapsRESTToolkit" package. The owner of the package is bingmaps and the author is Microsoft.
|
||||
|
||||
|
@ -41,17 +42,24 @@ If you prefer to use the NuGet package manager interface, ere are the steps to a
|
|||
3. Select the top result from Microsoft.
|
||||
4. Check the projects you want to add it to then press install.
|
||||
|
||||
## Supported Platforms ##
|
||||
## Supported Platforms
|
||||
|
||||
* .NET Framework 4.5+
|
||||
* .NET Standard 1.4+
|
||||
* .NET Standard 2.0+
|
||||
* Universal Windows Platform (UWP)
|
||||
* Windows 8+
|
||||
* Xamarin.Android
|
||||
* Xamarin.iOS
|
||||
* Xamarin.iOS (Classic)
|
||||
|
||||
## Contributing ##
|
||||
## TODO
|
||||
|
||||
Here are some tasks that are being considered:
|
||||
|
||||
* Add QPS limiting to SimpleWaypoint batch geocoding.
|
||||
* Consider wrapping truck routing service to generate truck based distance matrices.
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions. Feel free to file issues and pull requests on the repo and we'll address them as we can. Learn more about how you can help on our [Contribution Rules & Guidelines](CONTRIBUTING.md).
|
||||
|
||||
|
@ -61,11 +69,11 @@ You can reach out to us anytime with questions and suggestions using our communi
|
|||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information, see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
## Related Projects ##
|
||||
## Related Projects
|
||||
|
||||
* [Bing Maps SDS Toolkit for .NET](https://github.com/Microsoft/BingMapsSDSToolkit)
|
||||
|
||||
## Additional Resources ##
|
||||
## Additional Resources
|
||||
|
||||
* [Bing Maps REST Services MSDN Documentation](https://msdn.microsoft.com/en-us/library/ff701713.aspx)
|
||||
* [Bing Maps MSDN Documentation](https://msdn.microsoft.com/en-us/library/dd877180.aspx)
|
||||
|
@ -73,7 +81,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
|
|||
* [Bing Maps forums](https://social.msdn.microsoft.com/Forums/en-US/home?forum=bingmapsajax&filter=alltypes&sort=lastpostdesc)
|
||||
* [Bing Maps for Enterprise site](https://www.microsoft.com/maps/)
|
||||
|
||||
## License ##
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
|
|
|
@ -37,14 +37,10 @@
|
|||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Runtime.Serialization.Primitives, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\System.Runtime.Serialization.Primitives.4.1.1\lib\net46\System.Runtime.Serialization.Primitives.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="System.Runtime.Serialization.Primitives" version="4.1.1" targetFramework="net462" />
|
||||
<package id="System.Runtime.Serialization.Primitives" version="4.3.0" targetFramework="net462" />
|
||||
</packages>
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard1.4</TargetFramework>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<Version>1.0.9</Version>
|
||||
<Authors>Microsoft</Authors>
|
||||
<Company>Microsoft</Company>
|
||||
|
@ -52,6 +52,7 @@
|
|||
<Compile Include="..\Internal\InternalSettings.cs" Link="Internal\InternalSettings.cs" />
|
||||
<Compile Include="..\Internal\ServiceHelper.cs" Link="Internal\ServiceHelper.cs" />
|
||||
<Compile Include="..\Internal\SpatialTools.cs" Link="Internal\SpatialTools.cs" />
|
||||
<Compile Include="..\Internal\TruckDistanceMatrixGenerator.cs" Link="Internal\TruckDistanceMatrixGenerator.cs" />
|
||||
<Compile Include="..\Models\BoundingBox.cs" Link="Models\BoundingBox.cs" />
|
||||
<Compile Include="..\Models\Coordinate.cs" Link="Models\Coordinate.cs" />
|
||||
<Compile Include="..\Models\CustomMapStyles\BorderedMapElementStyle.cs" Link="Models\CustomMapStyles\BorderedMapElementStyle.cs" />
|
||||
|
@ -138,9 +139,8 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Net.Requests" Version="4.3.0" />
|
||||
<PackageReference Include="System.Runtime.Serialization.Json" Version="4.0.3" />
|
||||
<PackageReference Include="System.Runtime.Serialization.Primitives" Version="4.1.1" />
|
||||
<PackageReference Include="System.Runtime.Serialization.Json" Version="4.3.0" />
|
||||
<PackageReference Include="System.Runtime.Serialization.Primitives" Version="4.3.0" />
|
||||
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
<Compile Include="Enums\TrafficType.cs" />
|
||||
<Compile Include="Enums\WarningType.cs" />
|
||||
<Compile Include="Enums\WeightUnitType.cs" />
|
||||
<Compile Include="Internal\TruckDistanceMatrixGenerator.cs" />
|
||||
<Compile Include="Extensions\TSP Resources\BaseTspAlgorithm.cs" />
|
||||
<Compile Include="Extensions\TSP Resources\GreedyTspAlgorithm.cs" />
|
||||
<Compile Include="Extensions\TSP Resources\GeneticTspAlgorithm.cs" />
|
||||
|
|
|
@ -158,7 +158,7 @@ namespace BingMapsRESTToolkit
|
|||
{
|
||||
if(style.settings != null)
|
||||
{
|
||||
extractPropertyInfo("g", style.settings, styleString);
|
||||
ExtractPropertyInfo("g", style.settings, styleString);
|
||||
}
|
||||
|
||||
if(style.elements != null)
|
||||
|
@ -180,7 +180,7 @@ namespace BingMapsRESTToolkit
|
|||
continue;
|
||||
}
|
||||
|
||||
extractPropertyInfo(shortName, val, styleString);
|
||||
ExtractPropertyInfo(shortName, val, styleString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ namespace BingMapsRESTToolkit
|
|||
return styleString.ToString();
|
||||
}
|
||||
|
||||
private static void extractPropertyInfo(string shortName, object obj, StringBuilder writer)
|
||||
private static void ExtractPropertyInfo(string shortName, object obj, StringBuilder writer)
|
||||
{
|
||||
var prop = obj.GetType().GetRuntimeProperties();
|
||||
|
||||
|
@ -226,7 +226,7 @@ namespace BingMapsRESTToolkit
|
|||
else
|
||||
{
|
||||
// otherwise, it's a color, lets get the hex value of it
|
||||
stringValue = getValidHexColor((string)propertyValue, false);
|
||||
stringValue = GetValidHexColor((string)propertyValue, false);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(stringValue))
|
||||
|
@ -256,7 +256,7 @@ namespace BingMapsRESTToolkit
|
|||
|
||||
private static Regex _hexRx = new Regex("^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$");
|
||||
|
||||
private static string getValidHexColor(string hexColor, bool includeHash)
|
||||
private static string GetValidHexColor(string hexColor, bool includeHash)
|
||||
{
|
||||
if (_hexRx.IsMatch(hexColor))
|
||||
{
|
||||
|
|
|
@ -64,7 +64,6 @@ namespace BingMapsRESTToolkit.Extensions
|
|||
/// <param name="travelMode">The mode of transportation.</param>
|
||||
/// <param name="tspOptimization">The metric in which to base the TSP algorithm.</param>
|
||||
/// <param name="departureTime">The departure time in which to consider predictive traffic for. Only used when travel mode is driving and tsp optimiation is based on travel time or travel distance. Ignored if there is more than 10 waypoints as that would exceed limits of a distance matrix call.</param>
|
||||
/// <param name="isRoundTrip">Indicates if the path should be round trip and return to the origin or not.</param>
|
||||
/// <param name="bingMapsKey">A bing maps key.</param>
|
||||
/// <returns>An efficient path between all waypoints based on time or distance.</returns>
|
||||
public async Task<TspResult> Solve(List<SimpleWaypoint> waypoints, TravelModeType? travelMode, TspOptimizationType? tspOptimization, DateTime? departureTime, string bingMapsKey)
|
||||
|
@ -95,11 +94,6 @@ namespace BingMapsRESTToolkit.Extensions
|
|||
//Default to driving if not specified.
|
||||
travelMode = TravelModeType.Driving;
|
||||
}
|
||||
else if (travelMode == TravelModeType.Truck)
|
||||
{
|
||||
//Truck routes not supported for distance matrix, fall back to driving.
|
||||
travelMode = TravelModeType.Driving;
|
||||
}
|
||||
|
||||
var distanceMatrixRequest = new DistanceMatrixRequest()
|
||||
{
|
||||
|
@ -107,7 +101,9 @@ namespace BingMapsRESTToolkit.Extensions
|
|||
BingMapsKey = bingMapsKey
|
||||
};
|
||||
|
||||
if (departureTime.HasValue && distanceMatrixRequest.TravelMode == TravelModeType.Driving && waypoints.Count <= 10)
|
||||
if (departureTime.HasValue &&
|
||||
(distanceMatrixRequest.TravelMode == TravelModeType.Driving && waypoints.Count <= 10 ||
|
||||
distanceMatrixRequest.TravelMode == TravelModeType.Truck))
|
||||
{
|
||||
distanceMatrixRequest.StartTime = departureTime.Value;
|
||||
}
|
||||
|
@ -161,7 +157,6 @@ namespace BingMapsRESTToolkit.Extensions
|
|||
/// </summary>
|
||||
/// <param name="waypoints">Waypoints to optimize.</param>
|
||||
/// <param name="minTour">An optimized array of waypoint indicies</param>
|
||||
/// <param name="isRoundTrip">A boolean indicating if it is a round trip tour.</param>
|
||||
/// <returns>An optimized lis tof waypoints.</returns>
|
||||
protected List<SimpleWaypoint> GetOptimizedWaypoints(List<SimpleWaypoint> waypoints, int[] minTour)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
@ -51,6 +52,11 @@ namespace BingMapsRESTToolkit
|
|||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Proxy settings to use when making requests.
|
||||
/// </summary>
|
||||
public static IWebProxy Proxy { get; set; }
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
|
@ -63,6 +69,11 @@ namespace BingMapsRESTToolkit
|
|||
var tcs = new TaskCompletionSource<string>();
|
||||
|
||||
var request = HttpWebRequest.Create(url);
|
||||
|
||||
if (ServiceManager.Proxy != null) {
|
||||
request.Proxy = ServiceManager.Proxy;
|
||||
}
|
||||
|
||||
request.BeginGetResponse((a) =>
|
||||
{
|
||||
try
|
||||
|
@ -109,6 +120,12 @@ namespace BingMapsRESTToolkit
|
|||
var tcs = new TaskCompletionSource<Stream>();
|
||||
|
||||
var request = HttpWebRequest.Create(url);
|
||||
|
||||
if (ServiceManager.Proxy != null)
|
||||
{
|
||||
request.Proxy = ServiceManager.Proxy;
|
||||
}
|
||||
|
||||
request.BeginGetResponse((a) =>
|
||||
{
|
||||
try
|
||||
|
@ -152,6 +169,11 @@ namespace BingMapsRESTToolkit
|
|||
|
||||
var request = HttpWebRequest.Create(url);
|
||||
|
||||
if (ServiceManager.Proxy != null)
|
||||
{
|
||||
request.Proxy = ServiceManager.Proxy;
|
||||
}
|
||||
|
||||
request.Method = "POST";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(contentType))
|
||||
|
@ -246,7 +268,7 @@ namespace BingMapsRESTToolkit
|
|||
/// </summary>
|
||||
/// <typeparam name="T">The type of resource to expect to be returned.</typeparam>
|
||||
/// <param name="requestUrl">REST URL request.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time is sent.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time in seconds is sent.</param>
|
||||
/// <returns>A completed response for a request.</returns>
|
||||
internal static async Task<Response> MakeAsyncGetRequest<T>(string requestUrl, Action<int> remainingTimeCallback) where T : Resource
|
||||
{
|
||||
|
@ -265,7 +287,7 @@ namespace BingMapsRESTToolkit
|
|||
/// <typeparam name="T">The type of resource to expect to be returned.</typeparam>
|
||||
/// <param name="requestUrl">REST URL request.</param>
|
||||
/// <param name="requestBody">The post request body.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time is sent.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time in seconds is sent.</param>
|
||||
/// <returns>A completed response for a request.</returns>
|
||||
internal static async Task<Response> MakeAsyncPostRequest<T>(string requestUrl, string requestBody, Action<int> remainingTimeCallback) where T: Resource
|
||||
{
|
||||
|
@ -296,6 +318,47 @@ namespace BingMapsRESTToolkit
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes an array of tasks but limits the number of queries made per second.
|
||||
/// </summary>
|
||||
/// <param name="tasks">The tasks to process.</param>
|
||||
/// <returns>A task that processes the array of tasks</returns>
|
||||
internal static Task WhenAllTaskLimiter(List<Task> tasks)
|
||||
{
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
var taskGroup = new List<Task>();
|
||||
|
||||
for (var i = 0; i < tasks.Count; i++)
|
||||
{
|
||||
taskGroup.Add(tasks[i]);
|
||||
|
||||
if (taskGroup.Count >= ServiceManager.QpsLimit)
|
||||
{
|
||||
var start = DateTime.Now;
|
||||
|
||||
await Task.WhenAll(taskGroup);
|
||||
|
||||
var end = DateTime.Now;
|
||||
|
||||
taskGroup.Clear();
|
||||
|
||||
var ellapsed = (end - start);
|
||||
|
||||
if (i != tasks.Count - 1 && ellapsed.TotalMilliseconds < 1000)
|
||||
{
|
||||
//Ensure that atleast a second has passed since the last batch of requests.
|
||||
await Task.Delay(1000 - (int)ellapsed.TotalMilliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (taskGroup.Count > 0)
|
||||
{
|
||||
await Task.WhenAll(taskGroup);
|
||||
}
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
@ -361,7 +424,7 @@ namespace BingMapsRESTToolkit
|
|||
/// Processes an Async Status until it is completed or runs into an error.
|
||||
/// </summary>
|
||||
/// <param name="status">The async status to process.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time is sent.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time in seconds is sent.</param>
|
||||
/// <returns></returns>
|
||||
private static async Task<AsyncStatus> ProcessAsyncStatus(AsyncStatus status, Action<int> remainingTimeCallback)
|
||||
{
|
||||
|
@ -405,7 +468,7 @@ namespace BingMapsRESTToolkit
|
|||
/// </summary>
|
||||
/// <param name="statusUrl">The status URL for the async request.</param>
|
||||
/// <param name="failedTries">The number of times the status check has failed consecutively.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time is sent.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time in seconds is sent.</param>
|
||||
/// <returns>The final async status when the request completed, had an error, or was not accepted.</returns>
|
||||
private static async Task<AsyncStatus> MonitorAsyncStatus(Uri statusUrl, int failedTries, Action<int> remainingTimeCallback)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Copyright(c) 2017 Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* This code is licensed under the MIT License (MIT).
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BingMapsRESTToolkit.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class used to generate distance matricies based on truck driving attributes.
|
||||
/// </summary>
|
||||
internal class TruckDistanceMatrixGenerator
|
||||
{
|
||||
#region Private Properties
|
||||
|
||||
/// <summary>
|
||||
/// List of cells that have been manually generated.
|
||||
/// </summary>
|
||||
private List<DistanceMatrixCell> MatrixCells;
|
||||
|
||||
private List<DateTime> TimeIntervals;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a distance matrix based on truck routing attributes.
|
||||
/// </summary>
|
||||
/// <param name="request">The distance matrix request to base the request on.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time in seconds is sent.</param>
|
||||
/// <returns>A response which contains the truck routing based distance matrix.</returns>
|
||||
public async Task<Response> Calculate(DistanceMatrixRequest request, Action<int> remainingTimeCallback)
|
||||
{
|
||||
if (request.Destinations == null || request.Destinations.Count == 0)
|
||||
{
|
||||
request.Destinations = request.Origins;
|
||||
}
|
||||
|
||||
int numIntervals = 1;
|
||||
int intervalMin = 0;
|
||||
double numBatches = 0;
|
||||
|
||||
if (request.StartTime != null && request.StartTime.HasValue)
|
||||
{
|
||||
TimeIntervals = new List<DateTime>() { request.StartTime.Value };
|
||||
|
||||
if (request.EndTime != null && request.EndTime.HasValue)
|
||||
{
|
||||
intervalMin = request.Resolution * 15;
|
||||
numIntervals = (int)Math.Floor((request.EndTime.Value - request.StartTime.Value).TotalMinutes / intervalMin);
|
||||
}
|
||||
|
||||
numBatches = Math.Ceiling((double)(request.Destinations.Count * request.Origins.Count * numIntervals) / (double)ServiceManager.QpsLimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
TimeIntervals = null;
|
||||
numBatches = Math.Ceiling((double)(request.Destinations.Count * request.Origins.Count) / (double)ServiceManager.QpsLimit);
|
||||
}
|
||||
|
||||
if (remainingTimeCallback != null)
|
||||
{
|
||||
//Assume an average processing time of 2 seconds per batch.
|
||||
remainingTimeCallback((int)Math.Round(numBatches * 2));
|
||||
}
|
||||
|
||||
MatrixCells = new List<DistanceMatrixCell>();
|
||||
|
||||
//Calculate the first cell on it's own to verify that the request can be made. If it fails, do not proceed.
|
||||
var firstResponse = await CalculateTruckRoute(request.Origins[0], request.Destinations[0], 0, request);
|
||||
|
||||
if(firstResponse != null && firstResponse.ErrorDetails != null && firstResponse.ErrorDetails.Length > 0){
|
||||
return firstResponse;
|
||||
}
|
||||
else if (firstResponse == null || firstResponse.ResourceSets == null || firstResponse.ResourceSets.Length == 0 ||
|
||||
firstResponse.ResourceSets[0].Resources == null || firstResponse.ResourceSets[0].Resources.Length == 0)
|
||||
{
|
||||
return new Response()
|
||||
{
|
||||
ErrorDetails = new string[] { "Unabble to calculate distance matrix." },
|
||||
StatusCode = 400,
|
||||
StatusDescription = "Bad request"
|
||||
};
|
||||
}
|
||||
|
||||
var truckRoute = firstResponse.ResourceSets[0].Resources[0] as Route;
|
||||
|
||||
MatrixCells.Add(new DistanceMatrixCell()
|
||||
{
|
||||
OriginIndex = 0,
|
||||
DestinationIndex = 0,
|
||||
HasError = false,
|
||||
TravelDistance = truckRoute.TravelDistance,
|
||||
TravelDuration = (request.TimeUnits == TimeUnitType.Minute) ? truckRoute.TravelDuration * 60 : truckRoute.TravelDuration
|
||||
});
|
||||
|
||||
var cellTasks = new List<Task>();
|
||||
|
||||
if (request.StartTime != null && request.StartTime.HasValue)
|
||||
{
|
||||
TimeIntervals.Clear();
|
||||
|
||||
for (var k = 0; k < numIntervals; k++)
|
||||
{
|
||||
TimeIntervals.Add(request.StartTime.Value.AddMinutes(k * intervalMin));
|
||||
|
||||
for (var i = 0; i < request.Origins.Count; i++)
|
||||
{
|
||||
for (var j = 0; j < request.Destinations.Count; j++)
|
||||
{
|
||||
//Skip the first cell as we already calculated it.
|
||||
if (!(k==0 && i == 0 && j == 0))
|
||||
{
|
||||
cellTasks.Add(CalculateCell(i, j, k, request));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < request.Origins.Count; i++)
|
||||
{
|
||||
for (var j = 0; j < request.Destinations.Count; j++)
|
||||
{
|
||||
//Skip the first cell as we already calculated it.
|
||||
if (!(i == 0 && j == 0))
|
||||
{
|
||||
cellTasks.Add(CalculateCell(i, j, -1, request));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await ServiceHelper.WhenAllTaskLimiter(cellTasks);
|
||||
|
||||
var dm = new DistanceMatrix()
|
||||
{
|
||||
Origins = request.Origins,
|
||||
Destinations = request.Destinations,
|
||||
Results = MatrixCells.ToArray(),
|
||||
TimeIntervals = TimeIntervals
|
||||
};
|
||||
|
||||
return new Response()
|
||||
{
|
||||
StatusCode = firstResponse.StatusCode,
|
||||
StatusDescription = firstResponse.StatusDescription,
|
||||
TraceId = firstResponse.TraceId,
|
||||
AuthenticationResultCode = firstResponse.AuthenticationResultCode,
|
||||
BrandLogoUri = firstResponse.BrandLogoUri,
|
||||
Copyright = firstResponse.Copyright,
|
||||
ResourceSets = new ResourceSet[]
|
||||
{
|
||||
new ResourceSet() {
|
||||
Resources = new Resource[] { dm }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a truck ruting based matrix cell.
|
||||
/// </summary>
|
||||
/// <param name="originIdx">The index of the origin.</param>
|
||||
/// <param name="destIdx">The index of the destination.</param>
|
||||
/// <param name="timeIdx">The time interval index.</param>
|
||||
/// <param name="dmRequest">The distance matrix request.</param>
|
||||
/// <returns>A task which calculates the matrix cell and addes it to the MatrixCells array.</returns>
|
||||
private async Task CalculateCell(int originIdx, int destIdx, int timeIdx, DistanceMatrixRequest dmRequest)
|
||||
{
|
||||
DateTime? dt = null;
|
||||
|
||||
if (TimeIntervals != null && timeIdx >= 0)
|
||||
{
|
||||
dt = TimeIntervals[timeIdx];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var response = await CalculateTruckRoute(dmRequest.Origins[originIdx], dmRequest.Destinations[destIdx], timeIdx, dmRequest);
|
||||
|
||||
if (response != null && response.ResourceSets != null && response.ResourceSets.Length > 0 &&
|
||||
response.ResourceSets[0].Resources != null && response.ResourceSets[0].Resources.Length > 0)
|
||||
{
|
||||
var truckRoute = response.ResourceSets[0].Resources[0] as Route;
|
||||
|
||||
MatrixCells.Add(new DistanceMatrixCell()
|
||||
{
|
||||
OriginIndex = originIdx,
|
||||
DestinationIndex = destIdx,
|
||||
DepartureTimeUtc = dt,
|
||||
HasError = false,
|
||||
TravelDistance = truckRoute.TravelDistance,
|
||||
TravelDuration = (dmRequest.TimeUnits == TimeUnitType.Minute) ? truckRoute.TravelDuration / 60 : truckRoute.TravelDuration
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
//If we made it this far, the cell can't be calculated.
|
||||
MatrixCells.Add(new DistanceMatrixCell()
|
||||
{
|
||||
OriginIndex = originIdx,
|
||||
DestinationIndex = destIdx,
|
||||
DepartureTimeUtc = dt,
|
||||
HasError = true,
|
||||
TravelDistance = -1,
|
||||
TravelDuration = -1
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requests the truck route information needed for a matrix cell.
|
||||
/// </summary>
|
||||
/// <param name="origin">Origin of the route.</param>
|
||||
/// <param name="destination">Destination of the route.</param>
|
||||
/// <param name="timeIdx">The time interval index.</param>
|
||||
/// <param name="dmRequest">The distance matrix request.</param>
|
||||
/// <returns>Truck route information needed for a matrix cell.</returns>
|
||||
private async Task<Response> CalculateTruckRoute(SimpleWaypoint origin, SimpleWaypoint destination, int timeIdx, DistanceMatrixRequest dmRequest)
|
||||
{
|
||||
var request = new RouteRequest()
|
||||
{
|
||||
BingMapsKey = dmRequest.BingMapsKey,
|
||||
Culture = dmRequest.Culture,
|
||||
Domain = dmRequest.Domain,
|
||||
UserIp = dmRequest.UserIp,
|
||||
UserLocation = dmRequest.UserLocation,
|
||||
UserMapView = dmRequest.UserMapView,
|
||||
UserRegion = dmRequest.UserRegion,
|
||||
RouteOptions = new RouteOptions()
|
||||
{
|
||||
MaxSolutions = 1,
|
||||
DistanceUnits = dmRequest.DistanceUnits,
|
||||
Optimize = RouteOptimizationType.Time,
|
||||
TravelMode = TravelModeType.Truck,
|
||||
VehicleSpec = dmRequest.VehicleSpec
|
||||
},
|
||||
Waypoints = new List<SimpleWaypoint>() { origin, destination }
|
||||
};
|
||||
|
||||
if(TimeIntervals != null && timeIdx >= 0)
|
||||
{
|
||||
request.RouteOptions.DateTime = TimeIntervals[timeIdx];
|
||||
request.RouteOptions.Optimize = RouteOptimizationType.TimeWithTraffic;
|
||||
}
|
||||
|
||||
return await request.Execute();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -116,6 +116,7 @@ namespace BingMapsRESTToolkit
|
|||
|
||||
/// <summary>
|
||||
/// Retrieves the total travel distance between all waypoints indicies which represent an edge (graph/path).
|
||||
/// If a path between to waypoints is not routable, a large distance value will be returned.
|
||||
/// </summary>
|
||||
/// <param name="waypointIndicies">Waypoint indicies that represent the edge/path.</param>
|
||||
/// <returns>The total travel distance between all waypoints indicies.</returns>
|
||||
|
@ -129,9 +130,11 @@ namespace BingMapsRESTToolkit
|
|||
{
|
||||
var d = GetDistance(waypointIndicies[i], waypointIndicies[i + 1]);
|
||||
|
||||
if (d > 0)
|
||||
distance += d;
|
||||
|
||||
if (d < 0)
|
||||
{
|
||||
distance += d;
|
||||
return double.MaxValue;
|
||||
}
|
||||
}
|
||||
return distance;
|
||||
|
@ -142,6 +145,7 @@ namespace BingMapsRESTToolkit
|
|||
|
||||
/// <summary>
|
||||
/// Retrieves the total travel distance between all waypoints indicies which represent an edge (graph/path).
|
||||
/// If a path between to waypoints is not routable, a large distance value will be returned.
|
||||
/// </summary>
|
||||
/// <param name="waypointIndicies">Waypoint indicies that represent the edge/path.</param>
|
||||
/// <param name="isRoundTrip">Indicates if the edge should be round trip and return to the first waypoint in the indicies array.</param>
|
||||
|
@ -153,10 +157,11 @@ namespace BingMapsRESTToolkit
|
|||
if (isRoundTrip && waypointIndicies.Length >= 2)
|
||||
{
|
||||
var d = GetDistance(waypointIndicies[waypointIndicies.Length - 1], waypointIndicies[0]);
|
||||
distance += d;
|
||||
|
||||
if (d > 0)
|
||||
if (d < 0)
|
||||
{
|
||||
distance += d;
|
||||
return double.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +169,8 @@ namespace BingMapsRESTToolkit
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the total travel time between all waypoints indicies which represent an edge (graph/path).
|
||||
/// Retrieves the total travel time between all waypoints indicies which represent an edge (graph/path).
|
||||
/// If a path between to waypoints is not routable, a large time value will be returned.
|
||||
/// </summary>
|
||||
/// <param name="waypointIndicies">Waypoint indicies that represent the edge/path.</param>
|
||||
/// <returns>The total travel time between all waypoints indicies.</returns>
|
||||
|
@ -178,9 +184,11 @@ namespace BingMapsRESTToolkit
|
|||
{
|
||||
var t = GetTime(waypointIndicies[i], waypointIndicies[i + 1]);
|
||||
|
||||
if (t > 0)
|
||||
time += t;
|
||||
|
||||
if (t < 0)
|
||||
{
|
||||
time += t;
|
||||
return double.MaxValue;
|
||||
}
|
||||
}
|
||||
return time;
|
||||
|
@ -423,7 +431,7 @@ namespace BingMapsRESTToolkit
|
|||
{
|
||||
var c = GetCell(originIdx, destinationIdx, timeIntervalIdx);
|
||||
|
||||
if (c != null)
|
||||
if (c != null && c.TravelDuration >= 0)
|
||||
{
|
||||
return c.TravelDuration;
|
||||
}
|
||||
|
@ -447,7 +455,14 @@ namespace BingMapsRESTToolkit
|
|||
|
||||
for (int i = 0; i < cells.Length; i++)
|
||||
{
|
||||
times[i] = cells[i].TravelDuration;
|
||||
if(cells[i].TravelDuration <= 0)
|
||||
{
|
||||
times[i] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
times[i] = cells[i].TravelDuration;
|
||||
}
|
||||
}
|
||||
|
||||
return times;
|
||||
|
|
|
@ -49,12 +49,14 @@ namespace BingMapsRESTToolkit
|
|||
|
||||
/// <summary>
|
||||
/// The physical distance covered to complete a route between the origin and destination.
|
||||
/// When travel mode is set to transit or a path between the origin and destination can't be calculated, this value is set to -1.
|
||||
/// </summary>
|
||||
[DataMember(Name = "travelDistance", EmitDefaultValue = false)]
|
||||
public double TravelDistance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The time that it takes, in minutes, to travel a corresponding TravelDistance.
|
||||
/// If a path a path between the origin and destination can't be calculated, this value will be a negative number.
|
||||
/// </summary>
|
||||
[DataMember(Name = "travelDuration", EmitDefaultValue = false)]
|
||||
public double TravelDuration { get; set; }
|
||||
|
|
|
@ -213,9 +213,22 @@ namespace BingMapsRESTToolkit
|
|||
return string.Format("{0}|{1:0.######}|{2:0.######}", Address, Latitude, Longitude).GetHashCode();
|
||||
}
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// Tries to geocode a simple waypoint.
|
||||
/// </summary>
|
||||
/// <param name="waypoint">The simple waypoint to geocode.</param>
|
||||
/// <param name="bingMapsKey">The Bing Maps key to use when geocoding.</param>
|
||||
/// <returns>A Task in which the simple waypoint will be geocoded.</returns>
|
||||
public static async Task TryGeocode(SimpleWaypoint waypoint, string bingMapsKey)
|
||||
{
|
||||
var request = new GeocodeRequest()
|
||||
{
|
||||
BingMapsKey = bingMapsKey
|
||||
};
|
||||
|
||||
await TryGeocode(waypoint, request);
|
||||
}
|
||||
|
||||
#region Static Methods
|
||||
|
||||
/// <summary>
|
||||
/// Tries to geocode a simple waypoint.
|
||||
|
@ -223,7 +236,7 @@ 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 async Task TryGeocode(SimpleWaypoint waypoint, BaseRestRequest baseRequest)
|
||||
public static async Task TryGeocode(SimpleWaypoint waypoint, BaseRestRequest baseRequest)
|
||||
{
|
||||
if (waypoint != null && waypoint.Coordinate == null && !string.IsNullOrEmpty(waypoint.Address))
|
||||
{
|
||||
|
@ -267,7 +280,7 @@ namespace BingMapsRESTToolkit
|
|||
/// <param name="waypoints">A list of simple waypoints 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 a list of simple waypoints will be geocoded.</returns>
|
||||
internal static async Task TryGeocodeWaypoints(List<SimpleWaypoint> waypoints, BaseRestRequest baseRequest)
|
||||
public static async Task TryGeocodeWaypoints(List<SimpleWaypoint> waypoints, BaseRestRequest baseRequest)
|
||||
{
|
||||
var geocodeTasks = new List<Task>();
|
||||
|
||||
|
@ -281,45 +294,8 @@ namespace BingMapsRESTToolkit
|
|||
|
||||
if (geocodeTasks.Count > 0)
|
||||
{
|
||||
await Task.WhenAll(geocodeTasks);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to geocode a simple waypoint.
|
||||
/// </summary>
|
||||
/// <param name="waypoint">The simple waypoint to geocode.</param>
|
||||
/// <param name="bingMapsKey">The Bing Maps key to use when geocoding.</param>
|
||||
/// <returns>A Task in which the simple waypoint will be geocoded.</returns>
|
||||
internal static async Task TryGeocode(SimpleWaypoint waypoint, string bingMapsKey)
|
||||
{
|
||||
if (waypoint != null && waypoint.Coordinate == null && !string.IsNullOrEmpty(waypoint.Address))
|
||||
{
|
||||
var request = new GeocodeRequest()
|
||||
{
|
||||
Query = waypoint.Address,
|
||||
MaxResults = 1,
|
||||
BingMapsKey = bingMapsKey,
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
//await Task.WhenAll(geocodeTasks);
|
||||
await ServiceHelper.WhenAllTaskLimiter(geocodeTasks);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,22 +305,14 @@ namespace BingMapsRESTToolkit
|
|||
/// <param name="waypoints">A list of simple waypoints to geocode.</param>
|
||||
/// <param name="bingMapsKey">The Bing Maps key to use when geocoding.</param>
|
||||
/// <returns>A Task in which a list of simple waypoints will be geocoded.</returns>
|
||||
internal static async Task TryGeocodeWaypoints(List<SimpleWaypoint> waypoints, string bingMapsKey)
|
||||
public static async Task TryGeocodeWaypoints(List<SimpleWaypoint> waypoints, string bingMapsKey)
|
||||
{
|
||||
var geocodeTasks = new List<Task>();
|
||||
|
||||
foreach (var wp in waypoints)
|
||||
var request = new GeocodeRequest()
|
||||
{
|
||||
if (wp != null && wp.Coordinate == null && !string.IsNullOrEmpty(wp.Address))
|
||||
{
|
||||
geocodeTasks.Add(TryGeocode(wp, bingMapsKey));
|
||||
}
|
||||
}
|
||||
BingMapsKey = bingMapsKey
|
||||
};
|
||||
|
||||
if (geocodeTasks.Count > 0)
|
||||
{
|
||||
await Task.WhenAll(geocodeTasks);
|
||||
}
|
||||
await TryGeocodeWaypoints(waypoints, request);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -107,7 +107,7 @@ namespace BingMapsRESTToolkit
|
|||
/// <summary>
|
||||
/// Executes the request.
|
||||
/// </summary>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time is sent.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time in seconds is sent.</param>
|
||||
/// <returns>A response containing the requested data.</returns>
|
||||
public virtual async Task<Response> Execute(Action<int> remainingTimeCallback)
|
||||
{
|
||||
|
|
|
@ -116,6 +116,11 @@ namespace BingMapsRESTToolkit
|
|||
/// </summary>
|
||||
public TimeUnitType TimeUnits { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Truck routing specific vehicle attribute.
|
||||
/// </summary>
|
||||
public VehicleSpec VehicleSpec { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
@ -131,35 +136,45 @@ namespace BingMapsRESTToolkit
|
|||
/// <summary>
|
||||
/// Executes the request.
|
||||
/// </summary>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time is sent.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time in seconds is sent.</param>
|
||||
/// <returns>A response containing the requested distance matrix.</returns>
|
||||
public override async Task<Response> Execute(Action<int> remainingTimeCallback)
|
||||
{
|
||||
//Make sure all origins and destinations are geocoded.
|
||||
await GeocodeWaypoints();
|
||||
|
||||
var requestUrl = GetRequestUrl();
|
||||
var requestBody = GetPostRequestBody();
|
||||
|
||||
var response = await ServiceHelper.MakeAsyncPostRequest<DistanceMatrix>(requestUrl, requestBody, remainingTimeCallback);
|
||||
|
||||
var dm = response.ResourceSets[0].Resources[0] as DistanceMatrix;
|
||||
|
||||
//TODO: Overwrite origins/destinations for now as we have added support for geocoding in this library, but this is not yet supported by the Distance Matirx API.
|
||||
dm.Origins = this.Origins;
|
||||
|
||||
if (this.Destinations != null)
|
||||
if (TravelMode != TravelModeType.Truck)
|
||||
{
|
||||
dm.Destinations = this.Destinations;
|
||||
//Make sure all origins and destinations are geocoded.
|
||||
await GeocodeWaypoints();
|
||||
|
||||
var requestUrl = GetRequestUrl();
|
||||
var requestBody = GetPostRequestBody();
|
||||
|
||||
var response = await ServiceHelper.MakeAsyncPostRequest<DistanceMatrix>(requestUrl, requestBody, remainingTimeCallback);
|
||||
|
||||
var dm = response.ResourceSets[0].Resources[0] as DistanceMatrix;
|
||||
|
||||
//TODO: Overwrite origins/destinations for now as we have added support for geocoding in this library, but this is not yet supported by the Distance Matirx API.
|
||||
dm.Origins = this.Origins;
|
||||
|
||||
if (this.Destinations != null)
|
||||
{
|
||||
dm.Destinations = this.Destinations;
|
||||
}
|
||||
|
||||
if (dm.Results != null)
|
||||
{
|
||||
return response;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(dm.ErrorMessage))
|
||||
{
|
||||
throw new Exception(dm.ErrorMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var requestUrl = GetRequestUrl();
|
||||
|
||||
if (dm.Results != null)
|
||||
{
|
||||
return response;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(dm.ErrorMessage))
|
||||
{
|
||||
throw new Exception(dm.ErrorMessage);
|
||||
//Generate truck routing based distnace matrix by wrapping routing service.
|
||||
return await new Extensions.TruckDistanceMatrixGenerator().Calculate(this, remainingTimeCallback);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -285,16 +300,16 @@ namespace BingMapsRESTToolkit
|
|||
|
||||
int numCoordPairs = GetNumberOfCoordinatePairs();
|
||||
|
||||
if (numCoordPairs > MaxCoordinatePairs)
|
||||
if (numCoordPairs > MaxCoordinatePairs && TravelMode != TravelModeType.Truck)
|
||||
{
|
||||
throw new Exception("The number of Origins and Destinations provided would result in a matrix that has more than 625 coordinate pairs.");
|
||||
}
|
||||
|
||||
if (StartTime.HasValue)
|
||||
{
|
||||
if(TravelMode != TravelModeType.Driving)
|
||||
if(TravelMode != TravelModeType.Driving || TravelMode != TravelModeType.Truck)
|
||||
{
|
||||
throw new Exception("Start time parameter can only be used with the driving travel mode.");
|
||||
throw new Exception("Start time parameter can only be used with the driving or truck travel mode.");
|
||||
}
|
||||
|
||||
//Since start time is specified, an asynchronous request will be made which allows up to 100 coordinate pairs in the matrix (coordinate pairs).
|
||||
|
@ -310,7 +325,7 @@ namespace BingMapsRESTToolkit
|
|||
{
|
||||
if(!StartTime.HasValue)
|
||||
{
|
||||
throw new Exception("End time specified without a corresponding stat time.");
|
||||
throw new Exception("End time specified without a corresponding start time.");
|
||||
}
|
||||
|
||||
var timeSpan = EndTime.Value.Subtract(StartTime.Value);
|
||||
|
@ -326,6 +341,11 @@ namespace BingMapsRESTToolkit
|
|||
}
|
||||
}
|
||||
|
||||
if(TravelMode == TravelModeType.Truck)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return this.Domain + "Routes/DistanceMatrix" + ((isAsyncRequest)? "Async?" : "" + "?") + GetBaseRequestUrl();
|
||||
}
|
||||
|
||||
|
@ -335,6 +355,11 @@ namespace BingMapsRESTToolkit
|
|||
/// <returns></returns>
|
||||
public string GetPostRequestBody()
|
||||
{
|
||||
if(TravelMode == TravelModeType.Truck)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
//Build the JSON object using string builder as faster than JSON serializer.
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
@ -367,8 +392,7 @@ namespace BingMapsRESTToolkit
|
|||
}
|
||||
|
||||
string mode;
|
||||
|
||||
//TODO: Add truck when support added in distance matirx API.
|
||||
|
||||
switch (TravelMode)
|
||||
{
|
||||
case TravelModeType.Transit:
|
||||
|
@ -468,7 +492,7 @@ namespace BingMapsRESTToolkit
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -152,7 +152,7 @@ namespace BingMapsRESTToolkit
|
|||
/// <summary>
|
||||
/// Executes the request.
|
||||
/// </summary>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time is sent.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time in seconds is sent.</param>
|
||||
/// <returns>A response containing the requested data.</returns>
|
||||
public override async Task<Response> Execute(Action<int> remainingTimeCallback)
|
||||
{
|
||||
|
|
|
@ -219,7 +219,7 @@ namespace BingMapsRESTToolkit
|
|||
/// <summary>
|
||||
/// Executes the request.
|
||||
/// </summary>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time is sent.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time in seconds is sent.</param>
|
||||
/// <returns>A response containing the requested data.</returns>
|
||||
public override async Task<Response> Execute(Action<int> remainingTimeCallback)
|
||||
{
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace BingMapsRESTToolkit
|
|||
/// <summary>
|
||||
/// Executes the request.
|
||||
/// </summary>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time is sent.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time in seconds is sent.</param>
|
||||
/// <returns>A response containing the requested data.</returns>
|
||||
public override async Task<Response> Execute(Action<int> remainingTimeCallback)
|
||||
{
|
||||
|
|
|
@ -109,7 +109,7 @@ namespace BingMapsRESTToolkit
|
|||
/// <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>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time in seconds is sent.</param>
|
||||
/// <returns>A response containing the requested data.</returns>
|
||||
public override async Task<Response> Execute(Action<int> remainingTimeCallback)
|
||||
{
|
||||
|
@ -548,6 +548,8 @@ namespace BingMapsRESTToolkit
|
|||
throw new Exception("Truck routes must be optimized based on time or timeWithTraffic.");
|
||||
}
|
||||
|
||||
//sb.Append(",\"timeType\":\"minute\"");
|
||||
|
||||
if (RouteOptions.RouteAttributes != null && RouteOptions.RouteAttributes.Count > 0)
|
||||
{
|
||||
sb.Append(",\"routeAttributes\":\"");
|
||||
|
@ -598,7 +600,7 @@ namespace BingMapsRESTToolkit
|
|||
sb.Length--;
|
||||
sb.Append("]");
|
||||
}
|
||||
|
||||
|
||||
if (RouteOptions.VehicleSpec != null)
|
||||
{
|
||||
sb.Append(",\"vehicleSpec\":{");
|
||||
|
@ -687,7 +689,7 @@ namespace BingMapsRESTToolkit
|
|||
sb.Append(",");
|
||||
}
|
||||
|
||||
//Remove trailing comma.
|
||||
//Remove trailing comma and quote.
|
||||
sb.Length--;
|
||||
sb.Append("\"");
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ namespace BingMapsRESTToolkit
|
|||
/// <summary>
|
||||
/// Executes the request.
|
||||
/// </summary>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time is sent.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time in seconds is sent.</param>
|
||||
/// <returns>A response containing the requested data.</returns>
|
||||
public override async Task<Response> Execute(Action<int> remainingTimeCallback)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BingMapsRESTToolkit
|
||||
|
@ -33,6 +34,29 @@ namespace BingMapsRESTToolkit
|
|||
/// </summary>
|
||||
public static class ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Proxy settings to use when making requests.
|
||||
/// </summary>
|
||||
public static IWebProxy Proxy
|
||||
{
|
||||
get
|
||||
{
|
||||
return ServiceHelper.Proxy;
|
||||
}
|
||||
set
|
||||
{
|
||||
ServiceHelper.Proxy = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of queries per second to limit certain requests to.
|
||||
/// This is primarily used when batching multiple requests in a single process such as when
|
||||
/// geoeocidng all waypoints for the distance matrix API, or when manually generating a truck
|
||||
/// based distance matrix using the routing API.
|
||||
/// </summary>
|
||||
public static int QpsLimit = 5;
|
||||
|
||||
/// <summary>
|
||||
/// Processes a REST requests that returns data.
|
||||
/// </summary>
|
||||
|
@ -47,7 +71,7 @@ namespace BingMapsRESTToolkit
|
|||
/// Processes a REST requests that returns data.
|
||||
/// </summary>
|
||||
/// <param name="request">The REST request to process.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time is sent.</param>
|
||||
/// <param name="remainingTimeCallback">A callback function in which the estimated remaining time in seconds is sent.</param>
|
||||
/// <returns>The response from the REST service.</returns>
|
||||
public static async Task<Response> GetResponseAsync(BaseRestRequest request, Action<int> remainingTimeCallback)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче