/// <summary> /// Gets a POST body for a truck route request. /// </summary> /// <param name="startIdx">The starting index for the request when breaking waypoints up into a batch.</param> /// <param name="endIdx">The last waypoint index that was in the request.</param> /// <returns>A POST body for a truck route request.</returns> private string GetTruckPostRequestBody(int startIdx, out int endIdx) { endIdx = Waypoints.Count; var sb = new StringBuilder(); sb.Append("{"); sb.Append("\"waypoints\":["); int wayCnt = 0; for (int i = startIdx; i < Waypoints.Count; i++) { if (Waypoints[i].Coordinate != null) { sb.AppendFormat(CultureInfo.InvariantCulture, "{{\"latitude\":{0:0.#####},\"longitude\":{1:0.#####}", Waypoints[i].Latitude, Waypoints[i].Longitude); } else if (!string.IsNullOrWhiteSpace(Waypoints[i].Address)) { sb.AppendFormat("{{\"address\":\"{0}\"", Waypoints[i].Address); } else { throw new Exception("Invalid waypoint, an Address or Coordinate must be specified."); } if (Waypoints[i].IsViaPoint) { sb.Append(",\"isViaPoint\":true},"); } else { wayCnt++; sb.Append("},"); } //Only allow up to the batchSize waypoints in a request. if (wayCnt == batchSize) { endIdx = i; break; } } //Remove trailing comma. sb.Length--; sb.Append("]"); if (RouteOptions != null) { if (RouteOptions.Avoid != null && RouteOptions.Avoid.Count > 0) { sb.Append(",\"avoid\":\""); for (var i = 0; i < RouteOptions.Avoid.Count; i++) { sb.Append(Enum.GetName(typeof(AvoidType), RouteOptions.Avoid[i])); sb.Append(","); } //Remove trailing comma. sb.Length--; sb.Append("\""); } if (RouteOptions.DistanceBeforeFirstTurn > 0) { sb.AppendFormat(",\"distanceBeforeFirstTurn\":{0}", RouteOptions.DistanceBeforeFirstTurn); } if (RouteOptions.Heading.HasValue) { sb.AppendFormat(",\"heading\":{0}", RouteOptions.Heading.Value); } if (RouteOptions.MaxSolutions > 1 && RouteOptions.MaxSolutions <= 3) { sb.AppendFormat(",\"maxSolutions\":{0}", RouteOptions.MaxSolutions); } if (RouteOptions.Optimize == RouteOptimizationType.Time) { sb.Append(",\"optimize\":\"time\""); } else if (RouteOptions.Optimize == RouteOptimizationType.TimeWithTraffic) { sb.Append(",\"optimize\":\"timeWithTraffic\""); } else { 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\":\""); //Route summaries only supported, but other route attributes try to do something similar, so have them short circuit to this option. if (RouteOptions.RouteAttributes.Contains(RouteAttributeType.RouteSummariesOnly) || RouteOptions.RouteAttributes.Contains(RouteAttributeType.All) || RouteOptions.RouteAttributes.Contains(RouteAttributeType.ExcludeItinerary)) { sb.Append("routeSummariesOnly,"); } if (RouteOptions.RouteAttributes.Contains(RouteAttributeType.RoutePath) || RouteOptions.RouteAttributes.Contains(RouteAttributeType.All)) { sb.Append("routePath,"); } //Remove trailing comma. sb.Length--; sb.Append("\""); } if (RouteOptions.DistanceUnits == DistanceUnitType.Kilometers) { sb.Append(",\"distanceUnit\":\"kilometer\""); } else { sb.Append(",\"distanceUnit\":\"mile\""); } if (RouteOptions.DateTime != null) { sb.AppendFormat(DateTimeFormatInfo.InvariantInfo, ",\"dateTime\":\"{0:G}\"", RouteOptions.DateTime); } if (RouteOptions.Tolerances != null && RouteOptions.Tolerances.Count > 0) { sb.Append(",\"tolerances\":["); int cnt = Math.Min(RouteOptions.Tolerances.Count, 7); for (int i = 0; i < cnt; i++) { sb.AppendFormat(CultureInfo.InvariantCulture, "{0:0.######}", RouteOptions.Tolerances[i]); sb.Append(","); } //Remove trailing comma. sb.Length--; sb.Append("]"); } if (RouteOptions.VehicleSpec != null) { sb.Append(",\"vehicleSpec\":{"); sb.AppendFormat("\"dimensionUnit\":\"{0}\"", Enum.GetName(typeof(DimensionUnitType), RouteOptions.VehicleSpec.DimensionUnit).ToLowerInvariant()); sb.AppendFormat(",\"weightUnit\":\"{0}\"", Enum.GetName(typeof(WeightUnitType), RouteOptions.VehicleSpec.WeightUnit).ToLowerInvariant()); if (RouteOptions.VehicleSpec.VehicleAvoidCrossWind) { sb.Append(",\"vehicleAvoidCrossWind\":true"); } if (RouteOptions.VehicleSpec.VehicleAvoidGroundingRisk) { sb.Append(",\"vehicleAvoidGroundingRisk\":true"); } if (RouteOptions.VehicleSpec.VehicleSemi) { sb.Append(",\"VehicleSemi\":true"); } if (RouteOptions.VehicleSpec.VehicleAxles > 1) { sb.AppendFormat(",\"vehicleAxles\":{0}", RouteOptions.VehicleSpec.VehicleAxles); } if (RouteOptions.VehicleSpec.VehicleHeight > 0) { sb.AppendFormat(",\"vehicleHeight\":{0}", RouteOptions.VehicleSpec.VehicleHeight); } if (RouteOptions.VehicleSpec.VehicleWidth > 0) { sb.AppendFormat(",\"vehicleWidth\":{0}", RouteOptions.VehicleSpec.VehicleWidth); } if (RouteOptions.VehicleSpec.VehicleLength > 0) { sb.AppendFormat(",\"vehicleLength\":{0}", RouteOptions.VehicleSpec.VehicleLength); } if (RouteOptions.VehicleSpec.VehicleWeight > 0) { sb.AppendFormat(",\"vehicleWeight\":{0}", RouteOptions.VehicleSpec.VehicleWeight); } if (RouteOptions.VehicleSpec.VehicleMaxGradient > 0) { sb.AppendFormat(",\"vehicleMaxGradient\":{0}", RouteOptions.VehicleSpec.VehicleMaxGradient); } if (RouteOptions.VehicleSpec.VehicleMinTurnRadius > 0) { sb.AppendFormat(",\"vehicleMinTurnRadius\":{0}", RouteOptions.VehicleSpec.VehicleMinTurnRadius); } if (RouteOptions.VehicleSpec.VehicleTrailers > 0) { sb.AppendFormat(",\"vehicleTrailers\":{0}", RouteOptions.VehicleSpec.VehicleTrailers); } if (RouteOptions.VehicleSpec.VehicleHazardousMaterials != null && RouteOptions.VehicleSpec.VehicleHazardousMaterials.Count > 0 && !(RouteOptions.VehicleSpec.VehicleHazardousMaterials.Count == 1 && RouteOptions.VehicleSpec.VehicleHazardousMaterials[0] == HazardousMaterialType.None)) { sb.Append(",\"vehicleHazardousMaterials\":\""); foreach (var vhm in RouteOptions.VehicleSpec.VehicleHazardousMaterials) { sb.Append(EnumHelper.HazardousMaterialTypeToString(vhm)); sb.Append(","); } //Remove trailing comma. sb.Length--; sb.Append("\""); } if (RouteOptions.VehicleSpec.VehicleHazardousPermits != null && RouteOptions.VehicleSpec.VehicleHazardousPermits.Count > 0 && !(RouteOptions.VehicleSpec.VehicleHazardousPermits.Count == 1 && RouteOptions.VehicleSpec.VehicleHazardousPermits[0] == HazardousMaterialPermitType.None)) { sb.Append(",\"vehicleHazardousPermits\":\""); foreach (var vhp in RouteOptions.VehicleSpec.VehicleHazardousPermits) { sb.Append(EnumHelper.HazardousMaterialPermitTypeToString(vhp)); sb.Append(","); } //Remove trailing comma and quote. sb.Length--; sb.Append("\""); } sb.Append("}"); } } sb.Append("}"); return(sb.ToString()); }
/// <summary> /// Gets the request URL to perform a query for an isochrone. /// </summary> /// <returns>A request URL to perform a query for an isochron.</returns> public override string GetRequestUrl() { var sb = new StringBuilder(this.Domain); sb.Append("Routes/IsochronesAsync"); //Truck mode is not supported, so fall back to driving. if (TravelMode == TravelModeType.Truck) { TravelMode = TravelModeType.Driving; } sb.AppendFormat("?travelMode={0}", Enum.GetName(typeof(TravelModeType), TravelMode)); if (Waypoint == null) { throw new Exception("A waypoint must be specified."); } if (Waypoint.Coordinate != null) { sb.AppendFormat(CultureInfo.InvariantCulture, "&waypoint={0:0.#####},{1:0.#####}", Waypoint.Coordinate.Latitude, Waypoint.Coordinate.Longitude); } else if (!String.IsNullOrWhiteSpace(Waypoint.Address)) { sb.AppendFormat("&waypoint={0}", Waypoint.Address); } else { throw new Exception("Invalid waypoint: A coordinate or address must be specified."); } if (MaxTime > 0) { if (TimeUnit == TimeUnitType.Second && MaxTime > 3600) { throw new Exception("MaxTime value must be <= 3600 seconds."); } else if (TimeUnit == TimeUnitType.Minute && MaxTime > 60) { throw new Exception("MaxTime value must be <= 60 minutes."); } sb.AppendFormat("&maxTime={0}&timeUnit={1}", MaxTime, Enum.GetName(typeof(TimeUnitType), TimeUnit)); if (TravelMode != TravelModeType.Walking && DateTime != null && DateTime.HasValue) { sb.AppendFormat(DateTimeFormatInfo.InvariantInfo, "&dt={0:G}", DateTime.Value); } //TODO: in the future expose the optimize option and add support for timeWithTraffic. sb.AppendFormat("&optimize={0}", Enum.GetName(typeof(RouteOptimizationType), RouteOptimizationType.Time)); } else if (MaxDistance > 0) { if (TravelMode == TravelModeType.Transit) { throw new Exception("Distance based isochrones are not supported for transit travel mode. Use maxTime."); } sb.AppendFormat("&maxDistance={0}&distanceUnit={1}", MaxDistance, EnumHelper.DistanceUnitTypeToString(DistanceUnit)); sb.AppendFormat("&optimize={0}", Enum.GetName(typeof(RouteOptimizationType), RouteOptimizationType.Distance)); } else { throw new Exception("A max time or distance must be specified."); } //TODO: uncomment when/if avoid is supported. //if (TravelMode == TravelModeType.Driving) //{ // if (Avoid != null && Avoid.Count > 0) // { // sb.Append("&avoid="); // for (var i = 0; i < Avoid.Count; i++) // { // sb.Append(Enum.GetName(typeof(AvoidType), Avoid[i])); // if (i < Avoid.Count - 1) // { // sb.Append(","); // } // } // } //} sb.Append(GetBaseRequestUrl()); return(sb.ToString()); }