private void DoEdgeBased() { // do forward searches into buckets. for (var i = 0; i < _sourcePaths.Length; i++) { var path = _sourcePaths[i]; if (path != null) { var forward = new Itinero.Algorithms.Contracted.EdgeBased.Dykstra <T>(_graph, _weightHandler, new EdgePath <T>[] { path }, (v) => null, false, _max); forward.WasFound += (foundPath) => { LinkedEdgePath <T> visits; forward.TryGetVisits(foundPath.Vertex, out visits); return(this.ForwardVertexFound(i, foundPath.Vertex, visits)); }; forward.Run(); } } // do backward searches into buckets. for (var i = 0; i < _targetPaths.Length; i++) { var path = _targetPaths[i]; if (path != null) { var backward = new Itinero.Algorithms.Contracted.EdgeBased.Dykstra <T>(_graph, _weightHandler, new EdgePath <T>[] { path }, (v) => null, true, _max); backward.WasFound += (foundPath) => { LinkedEdgePath <T> visits; backward.TryGetVisits(foundPath.Vertex, out visits); return(this.BackwardVertexFound(i, foundPath.Vertex, visits)); }; backward.Run(); } } }
/// <summary> /// Executes the algorithm. /// </summary> protected sealed override void DoRun() { // run mass resolver if needed. if (!_massResolver.HasRun) { _massResolver.Run(); } // create error and resolved point management data structures. _correctedResolvedPoints = _massResolver.RouterPoints; _errors = new Dictionary <int, RouterPointError>(_correctedResolvedPoints.Count); _correctedIndices = new List <int>(_correctedResolvedPoints.Count); // convert sources into directed paths. _sourcePaths = new EdgePath <T> [_correctedResolvedPoints.Count * 2]; for (var i = 0; i < _correctedResolvedPoints.Count; i++) { _correctedIndices.Add(i); var paths = _correctedResolvedPoints[i].ToEdgePathsDirected(_router.Db, _weightHandler, true); if (paths.Length == 0) { this.ErrorMessage = string.Format("Source at {0} could not be resolved properly.", i); return; } _sourcePaths[i * 2 + 0] = paths[0]; if (paths.Length == 2) { _sourcePaths[i * 2 + 1] = paths[1]; } } // convert targets into directed paths. _targetPaths = new EdgePath <T> [_correctedResolvedPoints.Count * 2]; for (var i = 0; i < _correctedResolvedPoints.Count; i++) { var paths = _correctedResolvedPoints[i].ToEdgePathsDirected(_router.Db, _weightHandler, false); if (paths.Length == 0) { this.ErrorMessage = string.Format("Target at {0} could not be resolved properly.", i); return; } // make sure paths are the opposive of the sources. if (paths[0].Edge == _sourcePaths[i * 2 + 0].Edge) { // switchs. _targetPaths[i * 2 + 1] = paths[0]; if (paths.Length == 2) { _targetPaths[i * 2 + 0] = paths[1]; } } else { // keep. _targetPaths[i * 2 + 0] = paths[0]; if (paths.Length == 2) { _targetPaths[i * 2 + 1] = paths[1]; } } } // put in default weights and weights for one-edge-paths. _weights = new T[_sourcePaths.Length][]; for (var i = 0; i < _sourcePaths.Length; i++) { var source = _sourcePaths[i]; _weights[i] = new T[_targetPaths.Length]; for (var j = 0; j < _targetPaths.Length; j++) { var target = _targetPaths[j]; _weights[i][j] = _weightHandler.Infinite; if (source == null || target == null) { continue; } if (target.Edge == -source.Edge) { var s = i / 2; var t = j / 2; var sourcePoint = _correctedResolvedPoints[s]; var targetPoint = _correctedResolvedPoints[t]; EdgePath <T> newPath = null; if (source.Edge > 0 && sourcePoint.Offset <= targetPoint.Offset) { newPath = sourcePoint.EdgePathTo(_router.Db, _weightHandler, targetPoint); } else if (source.Edge < 0 && sourcePoint.Offset >= targetPoint.Offset) { newPath = sourcePoint.EdgePathTo(_router.Db, _weightHandler, targetPoint); } if (newPath != null) { if (_weightHandler.IsLargerThan(_weights[i][j], newPath.Weight)) { _weights[i][j] = newPath.Weight; } } } } } // do forward searches into buckets. for (var i = 0; i < _sourcePaths.Length; i++) { var path = _sourcePaths[i]; if (path != null) { var forward = new Itinero.Algorithms.Contracted.EdgeBased.Dykstra <T>(_graph, _weightHandler, new EdgePath <T>[] { path }, (v) => null, false, _max); forward.WasFound += (foundPath) => { LinkedEdgePath <T> visits; forward.TryGetVisits(foundPath.Vertex, out visits); return(this.ForwardVertexFound(i, foundPath.Vertex, visits)); }; forward.Run(); } } // do backward searches into buckets. for (var i = 0; i < _targetPaths.Length; i++) { var path = _targetPaths[i]; if (path != null) { var backward = new Itinero.Algorithms.Contracted.EdgeBased.Dykstra <T>(_graph, _weightHandler, new EdgePath <T>[] { path }, (v) => null, true, _max); backward.WasFound += (foundPath) => { LinkedEdgePath <T> visits; backward.TryGetVisits(foundPath.Vertex, out visits); return(this.BackwardVertexFound(i, foundPath.Vertex, visits)); }; backward.Run(); } } // check for invalids. var originalInvalids = new HashSet <int>(); var invalidTargetCounts = new int[_weights.Length / 2]; for (var s = 0; s < _weights.Length / 2; s++) { var invalids = 0; for (var t = 0; t < _weights[s * 2].Length / 2; t++) { if (t != s) { if (_weightHandler.GetMetric(_weights[s * 2 + 0][t * 2 + 0]) == float.MaxValue && _weightHandler.GetMetric(_weights[s * 2 + 0][t * 2 + 1]) == float.MaxValue && _weightHandler.GetMetric(_weights[s * 2 + 1][t * 2 + 0]) == float.MaxValue && _weightHandler.GetMetric(_weights[s * 2 + 1][t * 2 + 1]) == float.MaxValue) { invalids++; invalidTargetCounts[t]++; if (invalidTargetCounts[t] > ((_weights.Length / 2) - 1) / 2) { originalInvalids.Add(t); } } } } if (invalids > ((_weights.Length / 2) - 1) / 2) { originalInvalids.Add(s); } } // take into account the non-null invalids now. if (originalInvalids.Count > 0) { // shrink lists and add errors. _correctedResolvedPoints = _correctedResolvedPoints.ShrinkAndCopyList(originalInvalids); _correctedIndices = _correctedIndices.ShrinkAndCopyList(originalInvalids); // convert back to the path indexes. var nonNullInvalids = new HashSet <int>(); foreach (var invalid in originalInvalids) { nonNullInvalids.Add(invalid * 2); nonNullInvalids.Add(invalid * 2 + 1); _errors[invalid] = new RouterPointError() { Code = RouterPointErrorCode.NotRoutable, Message = "Location could not routed to or from." }; } _weights = _weights.SchrinkAndCopyMatrix(nonNullInvalids); _sourcePaths = _sourcePaths.ShrinkAndCopyArray(nonNullInvalids); _targetPaths = _targetPaths.ShrinkAndCopyArray(nonNullInvalids); } this.HasSucceeded = true; }