/// <summary> /// Creates a new weight-matrix algorithm. /// </summary> public WeightMatrixAlgorithm(RouterBase router, IProfileInstance profile, WeightHandler <T> weightHandler, IMassResolvingAlgorithm massResolver) { _router = router; _profile = profile; _weightHandler = weightHandler; _massResolver = massResolver; }
/// <summary> /// Creates a new weight-matrix algorithm. /// </summary> public DirectedWeightMatrixAlgorithm(RouterBase router, IProfileInstance profile, WeightHandler <T> weightHandler, IMassResolvingAlgorithm massResolver, T?max = null) { _router = router; _profile = profile; _weightHandler = weightHandler; _massResolver = massResolver; ContractedDb contractedDb; if (!router.Db.TryGetContracted(profile.Profile, out contractedDb)) { throw new NotSupportedException( "Contraction-based many-to-many calculates are not supported in the given router db for the given profile."); } if (!contractedDb.HasEdgeBasedGraph) { throw new NotSupportedException( "Contraction-based edge-based many-to-many calculates are not supported in the given router db for the given profile."); } _graph = contractedDb.EdgeBasedGraph; weightHandler.CheckCanUse(contractedDb); if (max.HasValue) { _max = max.Value; } else { _max = weightHandler.Infinite; } _buckets = new Dictionary <uint, Dictionary <int, LinkedEdgePath <T> > >(); }
/// <summary> /// Calculates all routes between all sources and all targets. /// </summary> /// <returns></returns> public static Result <Route[][]> TryCalculate(this RouterBase router, IProfileInstance profile, RouterPoint[] sources, RouterPoint[] targets) { var weightHandler = router.GetDefaultWeightHandler(profile); var paths = router.TryCalculateRaw(profile, weightHandler, sources, targets); if (paths.IsError) { return(paths.ConvertError <Route[][]>()); } var routes = new Route[paths.Value.Length][]; for (var s = 0; s < paths.Value.Length; s++) { routes[s] = new Route[paths.Value[s].Length]; for (var t = 0; t < paths.Value[s].Length; t++) { var localPath = paths.Value[s][t]; if (localPath != null) { var route = router.BuildRoute(profile, weightHandler, sources[s], targets[t], localPath); if (route.IsError) { return(route.ConvertError <Route[][]>()); } routes[s][t] = route.Value; } } } return(new Result <Route[][]>(routes)); }
/// <summary> /// Gets the get factor function for the given profile. /// </summary> public Func <ushort, FactorAndSpeed> GetGetFactorAndSpeed(IProfileInstance profileInstance) { if (!this.ContainsAll(profileInstance)) { throw new ArgumentException("Given profile not supported."); } var cachedFactors = _edgeProfileFactors[profileInstance.Profile.FullName]; if (profileInstance.Constraints != null) { return((p) => { var cachedFactor = cachedFactors[p]; if (profileInstance.IsConstrained(cachedFactor.Constraints)) { return FactorAndSpeed.NoFactor; } return cachedFactor; }); } return((p) => { return cachedFactors[p]; }); }
/// <summary> /// Gets the get factor function for the given profile. /// </summary> public Func <ushort, Factor> GetGetFactor(IProfileInstance profileInstance) { if (!_edgeProfileFactors.TryGetValue(profileInstance.Profile.FullName, out var cache)) { throw new ArgumentException("Given profile not supported."); } var cachedFactors = cache; if (profileInstance.Constraints != null) { return((p) => { var cachedFactor = cachedFactors[p]; if (profileInstance.IsConstrained(cachedFactor.Constraints)) { return Factor.NoFactor; } return cachedFactor.ToFactor(); }); } return((p) => { return cachedFactors[p].ToFactor(); }); }
/// <summary> /// Gets a function that gets a factor and speed for an edge with the given attributes. /// </summary> public static Func <ushort, FactorAndSpeed> GetGetFactorAndSpeed(this IProfileInstance profileInstance, RouterDb routerDb) { return((profileId) => { var profile = routerDb.EdgeProfiles.Get(profileId); return profileInstance.FactorAndSpeed(profile); }); }
/// <summary> /// Returns the default weight handler but calculates a profile cache first. /// </summary> public static DefaultWeightHandler DefaultWeightHandlerCached(this IProfileInstance profile, RouterDb routerDb) { // prebuild profile factor cache. var profileCache = new ProfileFactorAndSpeedCache(routerDb); profileCache.CalculateFor(profile.Profile); return(new Weights.DefaultWeightHandler(profileCache.GetGetFactor(profile))); }
/// <summary> /// Gets a the factor and speed for an edge with the given attributes. /// </summary> public static FactorAndSpeed FactorAndSpeed(this IProfileInstance profileInstance, IAttributeCollection attributes) { var factorAndSpeed = profileInstance.Profile.FactorAndSpeed(attributes); if (profileInstance.IsConstrained(factorAndSpeed.Constraints)) { return(Profiles.FactorAndSpeed.NoFactor); } return(factorAndSpeed); }
/// <summary> /// Builds a route. /// </summary> public override sealed Result <Route> BuildRoute <T>(IProfileInstance profileInstance, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target, EdgePath <T> path) { if (this.CustomRouteBuilder != null) { // there is a custom route builder. return(this.CustomRouteBuilder.TryBuild(_db, profileInstance.Profile, source, target, path)); } // use the default. return(CompleteRouteBuilder.TryBuild(_db, profileInstance.Profile, source, target, path)); }
/// <summary> /// Tries to calculate the weight between the given source and target. /// </summary> public static Result <T> TryCalculateWeight <T>(this RouterBase router, IProfileInstance profile, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target) where T : struct { var result = router.TryCalculateRaw <T>(profile, weightHandler, source, target); if (result.IsError) { return(result.ConvertError <T>()); } return(new Result <T>(result.Value.Weight)); }
public override Result <Route> BuildRoute <T>(IProfileInstance profile, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target, EdgePath <T> path) { var route = new Route(); route.Shape = new Coordinate[] { source.Location(), target.Location() }; return(new Result <Route>(route)); }
/// <summary> /// Calculates all weights between all sources and all targets. /// </summary> public static Result <T[][]> TryCalculateWeight <T>(this RouterBase router, IProfileInstance profile, WeightHandler <T> weightHandler, Coordinate[] sources, Coordinate[] targets) where T : struct { var resolvedSources = new RouterPoint[sources.Length]; for (var i = 0; i < sources.Length; i++) { var result = router.TryResolve(profile, sources[i]); if (result.IsError) { return(new Result <T[][]>(string.Format("Source at index {0} could not be resolved: {1}", i, result.ErrorMessage), (s) => { throw new Exceptions.ResolveFailedException(s); })); } resolvedSources[i] = result.Value; } var resolvedTargets = new RouterPoint[targets.Length]; for (var i = 0; i < targets.Length; i++) { var result = router.TryResolve(profile, targets[i]); if (result.IsError) { return(new Result <T[][]>(string.Format("Target at index {0} could not be resolved: {1}", i, result.ErrorMessage), (s) => { throw new Exceptions.ResolveFailedException(s); })); } resolvedTargets[i] = result.Value; } var invalidSources = new HashSet <int>(); var invalidTargets = new HashSet <int>(); var weights = router.TryCalculateWeight(profile, weightHandler, resolvedSources, resolvedTargets, invalidSources, invalidTargets); if (invalidSources.Count > 0) { return(new Result <T[][]>("Some sources could not be routed from. Most likely there are islands in the loaded network.", (s) => { throw new Exceptions.RouteNotFoundException(s); })); } if (invalidTargets.Count > 0) { return(new Result <T[][]>("Some targets could not be routed to. Most likely there are islands in the loaded network.", (s) => { throw new Exceptions.RouteNotFoundException(s); })); } return(weights); }
/// <summary> /// Calculates a route the given locations; /// </summary> public static Result <Route> TryCalculate(this RouterBase router, IProfileInstance profile, RouterPoint source, RouterPoint target) { var weightHandler = router.GetDefaultWeightHandler(profile); var path = router.TryCalculateRaw(profile, weightHandler, source, target); if (path.IsError) { return(path.ConvertError <Route>()); } return(router.BuildRoute(profile, weightHandler, source, target, path.Value)); }
/// <summary> /// Searches for the closest point on the routing network that's routable for the given profiles. /// </summary> public static RouterPoint[] Resolve(this RouterBase router, IProfileInstance profile, Coordinate[] coordinates, float searchDistanceInMeter = Constants.SearchDistanceInMeter) { var results = router.TryResolve(profile, coordinates, searchDistanceInMeter); var routerPoints = new RouterPoint[results.Length]; for (var i = 0; i < results.Length; i++) { routerPoints[i] = results[i].Value; } return(routerPoints); }
/// <summary> /// Checks if the given point is connected to the rest of the network. Use this to detect points on routing islands. /// </summary> /// <param name="radius">The radius metric, that can be a distance, time or custom metric.</param> /// <returns></returns> public sealed override Result <bool> TryCheckConnectivity(IProfileInstance profileInstance, RouterPoint point, float radius, bool?forward = null) { try { if (!_db.Supports(profileInstance.Profile)) { return(new Result <bool>("Routing profile is not supported.", (message) => { return new Exception(message); })); } // get the weight handler. var weightHandler = this.GetDefaultWeightHandler(profileInstance); var checkForward = forward == null || forward.Value; var checkBackward = forward == null || !forward.Value; if (checkForward) { // build and run forward dykstra search. var dykstra = new Dykstra(_db.Network.GeometricGraph.Graph, weightHandler, null, point.ToEdgePaths(_db, weightHandler, true), radius, false); dykstra.Run(); if (!dykstra.HasSucceeded || !dykstra.MaxReached) { // something went wrong or max not reached. return(new Result <bool>(false)); } } if (checkBackward) { // build and run backward dykstra search. var dykstra = new Dykstra(_db.Network.GeometricGraph.Graph, weightHandler, null, point.ToEdgePaths(_db, weightHandler, false), radius, true); dykstra.Run(); if (!dykstra.HasSucceeded || !dykstra.MaxReached) { // something went wrong or max not reached. return(new Result <bool>(false)); } } return(new Result <bool>(true)); } catch (Exception ex) { return(new Result <bool>(ex.Message, (m) => ex)); } }
/// <summary> /// Calculates all weights between all locations. /// </summary> public static Result <T[][]> TryCalculateWeight <T>(this RouterBase router, IProfileInstance profile, WeightHandler <T> weightHandler, RouterPoint[] locations) where T : struct { var invalids = new HashSet <int>(); var result = router.TryCalculateWeight(profile, weightHandler, locations, locations, invalids, invalids); if (invalids.Count > 0) { return(new Result <T[][]>("At least one location could not be routed from/to. Most likely there are islands in the loaded network.", (s) => { throw new Exceptions.RouteNotFoundException(s); })); } return(result); }
/// <summary> /// Checks the given edge values against the contraints in the profile. /// </summary> public static bool IsConstrained(this IProfileInstance profileInstance, float[] edgeValues) { if (profileInstance.Constraints == null) { return(false); } if (profileInstance.Profile.ConstrainedVariables == null) { return(false); } if (edgeValues == null) { return(false); } for (var i = 0; i < profileInstance.Profile.ConstrainedVariables.Length && i < profileInstance.Constraints.Length; i++) { var constraint = profileInstance.Profile.ConstrainedVariables[i]; if (constraint == null) { continue; } var profileValue = profileInstance.Constraints[i]; if (profileValue == constraint.DefaultValue) { continue; } var edgeValue = edgeValues[i]; if (edgeValue == constraint.DefaultValue) { continue; } if (constraint.IsMax && profileValue > edgeValue) { // the constraint is a maximum and the profile value is larger than the edge value. // the edge value for example maxweight 1.5T but vehicle weight is 2T. return(true); } else if (!constraint.IsMax && profileValue < edgeValue) { // the constraint is a minimum and the profile value is smaller than the edge value. return(true); } } return(false); }
/// <summary> /// Searches for the closest points on the routing network that's routable for the given profile(s). /// </summary> public static Result <RouterPoint>[] TryResolve(this RouterBase router, IProfileInstance profile, Coordinate[] coordinates, float searchDistanceInMeter = Constants.SearchDistanceInMeter) { if (coordinates == null) { throw new ArgumentNullException("coordinate"); } var result = new Result <RouterPoint> [coordinates.Length]; for (var i = 0; i < coordinates.Length; i++) { result[i] = router.TryResolve(profile, coordinates[i], searchDistanceInMeter); } return(result); }
/// <summary> /// Calculates a route between the two locations. /// </summary> public static Result <Route> TryCalculate(this RouterBase router, IProfileInstance profile, float sourceLatitude, float sourceLongitude, float targetLatitude, float targetLongitude) { var profiles = new IProfileInstance[] { profile }; var sourcePoint = router.TryResolve(profiles, sourceLatitude, sourceLongitude); var targetPoint = router.TryResolve(profiles, targetLatitude, targetLongitude); if (sourcePoint.IsError) { return(sourcePoint.ConvertError <Route>()); } if (targetPoint.IsError) { return(targetPoint.ConvertError <Route>()); } return(router.TryCalculate(profile, sourcePoint.Value, targetPoint.Value)); }
/// <summary> /// Calculates all routes between all sources and all targets. /// </summary> public static Result <Route[]> TryCalculate(this RouterBase router, IProfileInstance profile, RouterPoint source, RouterPoint[] targets) { var result = router.TryCalculate(profile, new RouterPoint[] { source }, targets); if (result.IsError) { return(result.ConvertError <Route[]>()); } var routes = new Route[result.Value.Length]; for (var j = 0; j < result.Value.Length; j++) { routes[j] = result.Value[0][j]; } return(new Result <Route[]>(routes)); }
/// <summary> /// Calculates the weight between the two locations. /// </summary> public static Result <T> TryCalculateWeight <T>(this RouterBase router, IProfileInstance profile, WeightHandler <T> weightHandler, float sourceLatitude, float sourceLongitude, float targetLatitude, float targetLongitude) where T : struct { var profiles = new IProfileInstance[] { profile }; var sourcePoint = router.TryResolve(profiles, sourceLatitude, sourceLongitude); var targetPoint = router.TryResolve(profiles, targetLatitude, targetLongitude); if (sourcePoint.IsError) { return(sourcePoint.ConvertError <T>()); } if (targetPoint.IsError) { return(targetPoint.ConvertError <T>()); } return(router.TryCalculateWeight(profile, weightHandler, sourcePoint.Value, targetPoint.Value)); }
/// <summary> /// Calculates a route along the given locations. /// </summary> public static Result <Route> TryCalculate(this RouterBase router, IProfileInstance profile, RouterPoint[] locations) { if (locations.Length < 2) { throw new ArgumentOutOfRangeException("Cannot calculate a routing along less than two locations."); } var route = router.TryCalculate(profile, locations[0], locations[1]); if (route.IsError) { return(route); } for (var i = 2; i < locations.Length; i++) { var nextRoute = router.TryCalculate(profile, locations[i - 1], locations[i]); if (nextRoute.IsError) { return(nextRoute); } route = new Result <Route>(route.Value.Concatenate(nextRoute.Value)); } return(route); }
public override Result <T[][]> TryCalculateWeight <T>(IProfileInstance profile, WeightHandler <T> weightHandler, RouterPoint[] sources, RouterPoint[] targets, ISet <int> invalidSources, ISet <int> invalidTargets, RoutingSettings <T> settings) { var weights = new T[sources.Length][]; for (var s = 0; s < sources.Length; s++) { weights[s] = new T[targets.Length]; for (var t = 0; t < sources.Length; t++) { weights[s][t] = weightHandler.Calculate(0, Coordinate.DistanceEstimateInMeter( new Coordinate(sources[s].Latitude, sources[s].Longitude), new Coordinate(targets[t].Latitude, targets[t].Longitude))); } } foreach (var invalid in _invalidSet) { invalidSources.Add(invalid); invalidTargets.Add(invalid); } return(new Result <T[][]>(weights)); }
/// <summary> /// Checks if the given point is connected to the rest of the network. Use this to detect points on routing islands. /// </summary> /// <returns></returns> public sealed override Result <bool> TryCheckConnectivity(IProfileInstance profileInstance, RouterPoint point, float radiusInMeters) { if (!_db.Supports(profileInstance.Profile)) { return(new Result <bool>("Routing profile is not supported.", (message) => { return new Exception(message); })); } // get the weight handler. var weightHandler = this.GetDefaultWeightHandler(profileInstance); // build and run dykstra search. var dykstra = new Dykstra(_db.Network.GeometricGraph.Graph, weightHandler, null, point.ToEdgePaths(_db, weightHandler, true), radiusInMeters, false); dykstra.Run(); if (!dykstra.HasSucceeded) { // something went wrong. return(new Result <bool>(false)); } return(new Result <bool>(dykstra.MaxReached)); }
/// <summary> /// Gets a the factor for an edge with the given attributes. /// </summary> public static Factor Factor(this IProfileInstance profileInstance, IAttributeCollection attributes) { return(profileInstance.FactorAndSpeed(attributes).ToFactor()); }
/// <summary> /// Builds a route based on a raw path. /// </summary> public abstract Result <Route> BuildRoute <T>(IProfileInstance profile, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target, EdgePath <T> path) where T : struct;
/// <summary> /// Calculates all weights between all sources and all targets. /// </summary> /// <returns></returns> public abstract Result <T[][]> TryCalculateWeight <T>(IProfileInstance profile, WeightHandler <T> weightHandler, RouterPoint[] sources, RouterPoint[] targets, ISet <int> invalidSources, ISet <int> invalidTargets, RoutingSettings <T> settings = null) where T : struct;
/// <summary> /// Calculates all routes between all sources and all targets. /// </summary> /// <returns></returns> public abstract Result <EdgePath <T>[][]> TryCalculateRaw <T>(IProfileInstance profile, WeightHandler <T> weightHandler, RouterPoint[] sources, RouterPoint[] targets, RoutingSettings <T> settings = null) where T : struct;
/// <summary> /// Calculates a route between the two directed edges. The route starts in the direction of the edge and ends with an arrive in the direction of the target edge. /// </summary> /// <returns></returns> public abstract Result <EdgePath <T> > TryCalculateRaw <T>(IProfileInstance profile, WeightHandler <T> weightHandler, long sourceDirectedEdge, long targetDirectedEdge, RoutingSettings <T> settings = null) where T : struct;
/// <summary> /// Checks if the given point is connected to the rest of the network. Use this to detect points on routing islands. /// </summary> /// <param name="radius">The radius metric, that can be a distance, time or custom metric.</param> /// <returns></returns> public abstract Result <bool> TryCheckConnectivity(IProfileInstance profile, RouterPoint point, float radius, bool?forward = null);