Buckets:

immErfanrajabee/bd / Core /Services /RoutingService.cs
imerfanrajabee's picture
download
raw
11.9 kB
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using Microsoft.Extensions.Logging;
using static BlockchainNetworkAnalyzer.App;
namespace BlockchainNetworkAnalyzer.Core.Services
{
/// <summary>
/// Routing service for navigation and directions
/// </summary>
public class RoutingService
{
private readonly ILogger<RoutingService> _logger;
private readonly HttpClient _httpClient;
public RoutingService()
{
_logger = App.LoggerFactory.CreateLogger<RoutingService>();
_httpClient = new HttpClient
{
Timeout = TimeSpan.FromSeconds(30)
};
}
public async Task<RouteInfo> GetRouteAsync(double startLat, double startLng, double endLat, double endLng, RouteProfile profile = RouteProfile.Driving)
{
var routeInfo = new RouteInfo
{
StartLatitude = startLat,
StartLongitude = startLng,
EndLatitude = endLat,
EndLongitude = endLng,
Profile = profile
};
try
{
// Try multiple routing services
RouteInfo result = null;
// Try Google Maps first
result = await GetRouteFromGoogleMaps(startLat, startLng, endLat, endLng, profile);
if (result != null && result.Success)
{
routeInfo = result;
routeInfo.Source = "Google Maps";
return routeInfo;
}
// Try OpenRouteService
result = await GetRouteFromOpenRouteService(startLat, startLng, endLat, endLng, profile);
if (result != null && result.Success)
{
routeInfo = result;
routeInfo.Source = "OpenRouteService";
return routeInfo;
}
// Try Mapbox
result = await GetRouteFromMapbox(startLat, startLng, endLat, endLng, profile);
if (result != null && result.Success)
{
routeInfo = result;
routeInfo.Source = "Mapbox";
return routeInfo;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting route");
}
return routeInfo;
}
public async Task<RouteInfo> GetRouteToAddressAsync(double startLat, double startLng, string address)
{
// First geocode the address, then get route
var geocodingService = new GeolocationService();
var addressLocation = await geocodingService.GetAddressAsync(startLat, startLng); // Reverse geocode
// For now, return basic route info
// In production, would geocode the target address first
return await GetRouteAsync(startLat, startLng, addressLocation.Latitude, addressLocation.Longitude);
}
private async Task<RouteInfo> GetRouteFromGoogleMaps(double startLat, double startLng, double endLat, double endLng, RouteProfile profile)
{
try
{
var apiKey = App.Configuration["Routing:GoogleMapsAPIKey"] ?? "";
if (string.IsNullOrEmpty(apiKey))
return null;
var mode = profile switch
{
RouteProfile.Driving => "driving",
RouteProfile.Walking => "walking",
RouteProfile.Cycling => "bicycling",
RouteProfile.Transit => "transit",
_ => "driving"
};
var url = $"https://maps.googleapis.com/maps/api/directions/json?" +
$"origin={startLat},{startLng}&" +
$"destination={endLat},{endLng}&" +
$"mode={mode}&" +
$"key={apiKey}&" +
$"language=fa";
var response = await _httpClient.GetStringAsync(url);
var data = JObject.Parse(response);
if (data["status"]?.ToString() == "OK" && data["routes"]?.First != null)
{
var route = data["routes"][0];
var legs = route["legs"][0];
var routeInfo = new RouteInfo
{
Success = true,
Distance = legs["distance"]?["value"]?.ToObject<double>() ?? 0,
DistanceText = legs["distance"]?["text"]?.ToString(),
Duration = legs["duration"]?["value"]?.ToObject<double>() ?? 0,
DurationText = legs["duration"]?["text"]?.ToString(),
StartAddress = legs["start_address"]?.ToString(),
EndAddress = legs["end_address"]?.ToString()
};
// Extract polyline
var overviewPolyline = route["overview_polyline"]?["points"]?.ToString();
routeInfo.Polyline = overviewPolyline;
// Extract steps
routeInfo.Steps = new List<RouteStep>();
if (legs["steps"] != null)
{
foreach (var step in legs["steps"])
{
routeInfo.Steps.Add(new RouteStep
{
Distance = step["distance"]?["value"]?.ToObject<double>() ?? 0,
DistanceText = step["distance"]?["text"]?.ToString(),
Duration = step["duration"]?["value"]?.ToObject<double>() ?? 0,
DurationText = step["duration"]?["text"]?.ToString(),
Instruction = step["html_instructions"]?.ToString(),
StartLatitude = step["start_location"]?["lat"]?.ToObject<double>() ?? 0,
StartLongitude = step["start_location"]?["lng"]?.ToObject<double>() ?? 0,
EndLatitude = step["end_location"]?["lat"]?.ToObject<double>() ?? 0,
EndLongitude = step["end_location"]?["lng"]?.ToObject<double>() ?? 0
});
}
}
return routeInfo;
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to get route from Google Maps");
}
return null;
}
private async Task<RouteInfo> GetRouteFromOpenRouteService(double startLat, double startLng, double endLat, double endLng, RouteProfile profile)
{
try
{
var apiKey = App.Configuration["Routing:OpenRouteServiceAPIKey"] ?? "";
if (string.IsNullOrEmpty(apiKey))
return null;
var profileStr = profile switch
{
RouteProfile.Driving => "driving-car",
RouteProfile.Walking => "foot-walking",
RouteProfile.Cycling => "cycling-regular",
_ => "driving-car"
};
var url = $"https://api.openrouteservice.org/v2/directions/{profileStr}?" +
$"api_key={apiKey}&" +
$"start={startLng},{startLat}&" +
$"end={endLng},{endLat}";
var response = await _httpClient.GetStringAsync(url);
var data = JObject.Parse(response);
if (data["features"]?.First != null)
{
var feature = data["features"][0];
var properties = feature["properties"];
var geometry = feature["geometry"];
return new RouteInfo
{
Success = true,
Distance = properties["segments"]?[0]?["distance"]?.ToObject<double>() ?? 0,
Duration = properties["segments"]?[0]?["duration"]?.ToObject<double>() ?? 0,
Polyline = geometry["coordinates"]?.ToString()
};
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to get route from OpenRouteService");
}
return null;
}
private async Task<RouteInfo> GetRouteFromMapbox(double startLat, double startLng, double endLat, double endLng, RouteProfile profile)
{
try
{
var apiKey = App.Configuration["Routing:MapboxAPIKey"] ?? "";
if (string.IsNullOrEmpty(apiKey))
return null;
var profileStr = profile switch
{
RouteProfile.Driving => "driving",
RouteProfile.Walking => "walking",
RouteProfile.Cycling => "cycling",
_ => "driving"
};
var url = $"https://api.mapbox.com/directions/v5/mapbox/{profileStr}/{startLng},{startLat};{endLng},{endLat}?" +
$"access_token={apiKey}&" +
$"geometries=geojson&" +
$"overview=full";
var response = await _httpClient.GetStringAsync(url);
var data = JObject.Parse(response);
if (data["code"]?.ToString() == "Ok" && data["routes"]?.First != null)
{
var route = data["routes"][0];
return new RouteInfo
{
Success = true,
Distance = route["distance"]?.ToObject<double>() ?? 0,
Duration = route["duration"]?.ToObject<double>() ?? 0,
Polyline = route["geometry"]?.ToString()
};
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to get route from Mapbox");
}
return null;
}
}
public enum RouteProfile
{
Driving,
Walking,
Cycling,
Transit
}
public class RouteInfo
{
public bool Success { get; set; }
public double StartLatitude { get; set; }
public double StartLongitude { get; set; }
public double EndLatitude { get; set; }
public double EndLongitude { get; set; }
public double Distance { get; set; } // in meters
public string DistanceText { get; set; }
public double Duration { get; set; } // in seconds
public string DurationText { get; set; }
public string StartAddress { get; set; }
public string EndAddress { get; set; }
public string Polyline { get; set; }
public List<RouteStep> Steps { get; set; } = new List<RouteStep>();
public RouteProfile Profile { get; set; }
public string Source { get; set; }
}
public class RouteStep
{
public double Distance { get; set; }
public string DistanceText { get; set; }
public double Duration { get; set; }
public string DurationText { get; set; }
public string Instruction { get; set; }
public double StartLatitude { get; set; }
public double StartLongitude { get; set; }
public double EndLatitude { get; set; }
public double EndLongitude { get; set; }
}
}

Xet Storage Details

Size:
11.9 kB
·
Xet hash:
268f16666f6713c4a58538ccbad9264056c6e4b4f2d4d9b0b19dce8a21052f55

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.