private MSSimpleShortcutSet FindShortcutsInDirection(MSShortcutChecker checker, bool forward) { var input = checker.Input; var trajectory = input.Trajectory; checker.Forward = forward; var shortcutSet = new MSSimpleShortcutSet(input, ShortcutSetFactory); Func <int, int> step; int startI; Func <int, bool> conditionI; Func <int, bool> conditionJ; if (forward) { step = i => i + 1; startI = 0; conditionI = i => i < trajectory.Count - 2; conditionJ = j => j < trajectory.Count; } else { step = i => i - 1; startI = trajectory.Count - 1; conditionI = i => i >= 2; conditionJ = j => j >= 0; } TPoint2D intervalLimit = null; LinkedListNode <TPoint2D> intervalLimitNode = null; if (input.SearchIntervals != null) { intervalLimitNode = forward ? input.SearchIntervals.First.Next : input.SearchIntervals.Last.Previous; intervalLimit = intervalLimitNode.Value; } var shortcutStartsHandled = 0; for (var i = startI; conditionI(i); i = step(i)) { var pointI = trajectory[i]; if (input.PrunedPoints.Contains(pointI)) { continue; } if (input.SearchIntervals != null) { if (intervalLimit.Index == pointI.Index) { intervalLimitNode = forward ? intervalLimitNode.Next : intervalLimitNode.Previous; intervalLimit = intervalLimitNode.Value; } } checker.OnNewShortcutStart(pointI); for (var j = step(i); conditionJ(j); j = step(j)) { var pointJ = trajectory[j]; if (input.SearchIntervals != null) { if (forward && pointJ.Index > intervalLimit.Index || !forward && pointJ.Index < intervalLimit.Index) { break; } } checker.BeforeShortcut(pointI, pointJ); if (Math.Abs(j - i) > 1 && !input.PrunedPoints.Contains(pointJ)) { checker.BeforeShortcutValidation(pointI, pointJ); var shortcutValid = false; for (var level = 1; level <= input.NumLevels; level++) { if (!shortcutValid) { shortcutValid = checker.ShortcutValid(level, pointI, pointJ); } if (!shortcutValid) { continue; } var start = forward ? pointI : pointJ; var end = forward ? pointJ : pointI; if (forward) { shortcutSet.Shortcuts[level].AppendShortcut(start, end); } else { shortcutSet.Shortcuts[level].PrependShortcut(start, end); } } } if (!checker.AfterShortcut(pointI, pointJ)) { break; } } shortcutStartsHandled++; if (shortcutStartsHandled >= trajectory.Count / 100) { var progress = forward ? i : trajectory.Count - i; //System.Diagnostics.Debug.WriteLine("Shortcuts handled: " + progress * 100 / trajectory.Count + "%"); checker.Output.LogLine("Shortcuts handled: " + progress * 100 / trajectory.Count + "%"); shortcutStartsHandled = 0; } } return(shortcutSet); }
public override IMSShortcutSet FindShortcuts(MSShortcutChecker checker, bool bidirectional) { var input = checker.Input; var shortcutSet = new MSSimpleShortcutSet(input, ShortcutSetFactory); if (bidirectional) { var forwardOutput = FindShortcutsInDirection(checker, true); var backwardOutput = FindShortcutsInDirection(checker, false); for (var level = 1; level <= input.NumLevels; level++) { var shortcutsForward = forwardOutput.GetShortcuts(level); var shortcutsBackwards = backwardOutput.GetShortcuts(level); shortcutsForward.Intersect(shortcutsBackwards); shortcutSet.Shortcuts[level] = shortcutsForward; } } else { var tempOutput = FindShortcutsInDirection(checker, true); for (var level = 1; level <= input.NumLevels; level++) { shortcutSet.Shortcuts[level] = tempOutput.Shortcuts[level]; } } //trivial shortcuts var trajectory = input.Trajectory; for (var level = 1; level <= input.NumLevels; level++) { var shortcuts = shortcutSet.Shortcuts[level]; if (level != 1 && input.Cumulative) { continue; } for (var i = 0; i < trajectory.Count - 1; i++) { if (input.PrunedPoints.Contains(trajectory[i]) || input.PrunedPoints.Contains(trajectory[i + 1])) { continue; } shortcuts.PrependShortcut(trajectory[i], trajectory[i + 1]); } } if (input.Cumulative) { for (var level = input.NumLevels; level >= 2; level--) { var shortcuts = shortcutSet.Shortcuts[level]; var shortcutsOnPreviousLevel = shortcutSet.Shortcuts[level - 1]; shortcuts.Except(shortcutsOnPreviousLevel); } } return(shortcutSet); }