/// <summary> /// Creates a closed circle of windows connected by links. /// </summary> private static AvidModelWindow[] BuildFullRing(AvidModel model, AvidRing ring, bool abovePlane) { AvidModelWindow firstWindow = null; AvidModelWindow previousWindow = null; var result = new AvidModelWindow[12]; for (int i = 1; i <= 12; i++) { var newWindow = new AvidModelWindow((AvidDirection)i, ring, abovePlane); result[i - 1] = newWindow; if (firstWindow == null) { firstWindow = newWindow; } if (previousWindow != null) { model.Links.Add(new AvidModelLink(newWindow, previousWindow, 2, false, false)); } previousWindow = newWindow; model.Windows.Add(newWindow); } //Connect first and last windows closing the circle. model.Links.Add(new AvidModelLink(firstWindow, previousWindow, 2, false, false)); return result; }
/// <summary> /// Creates a closed circle of windows connected by links. /// </summary> private static AvidModelWindow[] BuildFullRing(AvidModel model, AvidRing ring, bool abovePlane) { AvidModelWindow firstWindow = null; AvidModelWindow previousWindow = null; var result = new AvidModelWindow[12]; for (int i = 1; i <= 12; i++) { var newWindow = new AvidModelWindow((AvidDirection)i, ring, abovePlane); result[i - 1] = newWindow; if (firstWindow == null) { firstWindow = newWindow; } if (previousWindow != null) { model.Links.Add(new AvidModelLink(newWindow, previousWindow, 2, false, false)); } previousWindow = newWindow; model.Windows.Add(newWindow); } //Connect first and last windows closing the circle. model.Links.Add(new AvidModelLink(firstWindow, previousWindow, 2, false, false)); return(result); }
public LinkedAvidNode(AvidModelWindow window, LinkedAvidNode previousNode, AvidModelLink linkUsed) { Window = window; PreviousNode = previousNode; LinkUsed = linkUsed; UpdateTransitionsCount(); }
private void ProfferNewDistance(AvidModelWindow window, int newDistance) { if (window.MinDistance == AvidModelWindow.UndefinedDistance || window.MinDistance > newDistance) { window.MinDistance = newDistance; } }
public AvidPathInfo(int distance, AvidModelWindow start, AvidModelWindow destination) { PathNodes = new List<LinkedAvidNode>(); Distance = distance; Destination = destination; Start = start; }
private AvidPathInfo TracePath(LinkedAvidNode leaf, AvidModelWindow start, AvidModelWindow destination) { var pathInfo = new AvidPathInfo(leaf.NodeDistance, start, destination); pathInfo.PathNodes.AddRange(leaf.GetBranch()); pathInfo.PathNodes.Reverse(); return(pathInfo); }
private void InitializeNodes(AvidModel model, AvidModelWindow start, AvidModelWindow destination) { model.ClearOperationalData(); start.MinDistance = 0; // We will now exclude all nodes that are on edge, except if such node is either starting point or the destination. foreach (var window in model.Windows.Where(window => window.IsOnSpine && !window.Equals(start) && !window.Equals(destination))) { window.Excluded = true; } }
private LinkedAvidNode[] BuildTree(AvidModelWindow start, AvidModelWindow destination, AvidPathingOptions options) { var rootNode = new LinkedAvidNode(start, null, null); var result = new List<LinkedAvidNode>(); TraverseDescendants(result, rootNode, destination, options); if (result.Count > 0) { result.Sort((ndA, ndB) => ndA.NodeDistance - ndB.NodeDistance); int minimumDistance = result[0].NodeDistance; return result.Where(nd => nd.NodeDistance == minimumDistance).ToArray(); } return result.ToArray(); }
private LinkedAvidNode[] BuildTree(AvidModelWindow start, AvidModelWindow destination, AvidPathingOptions options) { var rootNode = new LinkedAvidNode(start, null, null); var result = new List <LinkedAvidNode>(); TraverseDescendants(result, rootNode, destination, options); if (result.Count > 0) { result.Sort((ndA, ndB) => ndA.NodeDistance - ndB.NodeDistance); int minimumDistance = result[0].NodeDistance; return(result.Where(nd => nd.NodeDistance == minimumDistance).ToArray()); } return(result.ToArray()); }
public AvidPathfindingResult GetShortestPaths(AvidModel model, AvidWindow start, AvidWindow destination, AvidPathingOptions options) { AvidModelWindow startWnd = model.ProjectWindow(start); AvidModelWindow destinationWnd = model.ProjectWindow(destination); InitializeNodes(model, startWnd, destinationWnd); var validLeaves = BuildTree(startWnd, destinationWnd, options); var result = new AvidPathfindingResult { PathExists = validLeaves.Length > 0 }; if (result.PathExists) { result.MinimalDistance = validLeaves[0].NodeDistance; result.AllShortestPaths.AddRange(validLeaves.Select(lf => TracePath(lf, startWnd, destinationWnd))); } return(result); }
/// <summary> /// Creates a green ring and attaches it to the right magenta window. Model must have magenta windows. /// </summary> private void BuildGreenRing(AvidModel model, AvidModelWindow[] adjacentFullRing, AvidModelWindow adjacentCap) { AvidModelWindow firstWindow = null; AvidModelWindow previousWindow = null; for (int i = 0; i < 6; i++) { var newWindow = new AvidModelWindow((AvidDirection)(i * 2 + 1), AvidRing.Green, adjacentCap.AbovePlane); if (firstWindow == null) { firstWindow = newWindow; } model.Links.Add(new AvidModelLink(newWindow, adjacentCap, 2, false, false)); model.Links.Add(new AvidModelLink(newWindow, adjacentFullRing[i * 2], 2, false, false)); int previousIndex = i == 0 ? 11 : i * 2 - 1; int nextIndex = (i * 2 + 1) % 12; model.Links.Add(new AvidModelLink(newWindow, adjacentFullRing[previousIndex], 2, false, true)); model.Links.Add(new AvidModelLink(newWindow, adjacentFullRing[nextIndex], 2, false, true)); if (previousWindow != null) { model.Links.Add(new AvidModelLink(newWindow, previousWindow, 2, false, false)); var cornerWindow = new AvidModelWindow((AvidDirection)(i * 2), AvidRing.Green, adjacentCap.AbovePlane); model.Windows.Add(cornerWindow); model.Links.Add(new AvidModelLink(cornerWindow, newWindow, 1, false, false)); model.Links.Add(new AvidModelLink(cornerWindow, previousWindow, 1, false, false)); } previousWindow = newWindow; model.Windows.Add(newWindow); } //Connect first and last windows closing the circle. model.Links.Add(new AvidModelLink(firstWindow, previousWindow, 2, false, false)); var closingCornerWindow = new AvidModelWindow(AvidDirection.FA, AvidRing.Green, adjacentCap.AbovePlane); model.Windows.Add(closingCornerWindow); model.Links.Add(new AvidModelLink(closingCornerWindow, firstWindow, 1, false, false)); model.Links.Add(new AvidModelLink(closingCornerWindow, previousWindow, 1, false, false)); }
public AvidModel BuildModel() { var result = new AvidModel(); // Add caps. var upperCap = new AvidModelWindow(AvidDirection.Undefined, AvidRing.Magenta, true); var lowerCap = new AvidModelWindow(AvidDirection.Undefined, AvidRing.Magenta, false); result.Windows.Add(upperCap); result.Windows.Add(lowerCap); var emberRing = BuildFullRing(result, AvidRing.Ember, true); var blueUpperRing = BuildFullRing(result, AvidRing.Blue, true); var blueLowerRing = BuildFullRing(result, AvidRing.Blue, false); ConnectFullRings(result, emberRing, blueUpperRing); ConnectFullRings(result, emberRing, blueLowerRing); BuildGreenRing(result, blueUpperRing, upperCap); BuildGreenRing(result, blueLowerRing, lowerCap); return result; }
private void TraverseDescendants(List<LinkedAvidNode> result, LinkedAvidNode node, AvidModelWindow destination, AvidPathingOptions options) { var validTransitions = node.Window.AdjacentWindows.ToList(); // Create a new list validTransitions.AddRange(node.Window.DiagonalWindows); foreach (var transition in validTransitions) { var linkedWindow = transition.GetLinkedNode(node.Window); // We encountered an excluded window or we are in a loop! if (linkedWindow.Excluded || WindowOccuredInPath(node, linkedWindow)) { continue; } if (!CanDoTransition(node, transition, options)) { continue; } var newNode = new LinkedAvidNode(linkedWindow, node, transition); if (newNode.NodeDistance / 2 > MaximumDepth) { continue; } ProfferNewDistance(linkedWindow, newNode.NodeDistance); if (!linkedWindow.Equals(destination)) { TraverseDescendants(result, newNode, destination, options); continue; } //New node is destination and we the path is at least minDistance, but not over maxDistance. result.Add(newNode); } }
public AvidModel BuildModel() { var result = new AvidModel(); // Add caps. var upperCap = new AvidModelWindow(AvidDirection.Undefined, AvidRing.Magenta, true); var lowerCap = new AvidModelWindow(AvidDirection.Undefined, AvidRing.Magenta, false); result.Windows.Add(upperCap); result.Windows.Add(lowerCap); var emberRing = BuildFullRing(result, AvidRing.Ember, true); var blueUpperRing = BuildFullRing(result, AvidRing.Blue, true); var blueLowerRing = BuildFullRing(result, AvidRing.Blue, false); ConnectFullRings(result, emberRing, blueUpperRing); ConnectFullRings(result, emberRing, blueLowerRing); BuildGreenRing(result, blueUpperRing, upperCap); BuildGreenRing(result, blueLowerRing, lowerCap); return(result); }
public AvidModelLink(AvidModelWindow endpointA, AvidModelWindow endpointB, int weight, bool isDiagonal, bool isPolarDiagonal) { if (endpointA == null || endpointB == null) { throw new ArgumentNullException(); } if (endpointA.Equals(endpointB)) { throw new ArgumentException("A window can't be connected to itself."); } if (weight < 0) { throw new ArgumentException("Link weight should be non-negative.", "weight"); } EndpointA = endpointA; EndpointB = endpointB; Weight = weight; IsDiagonal = isDiagonal; IsPolarDiagonal = isPolarDiagonal; AddLinkToEndpoints(); }
private AvidPathInfo TracePath(LinkedAvidNode leaf, AvidModelWindow start, AvidModelWindow destination) { var pathInfo = new AvidPathInfo(leaf.NodeDistance, start, destination); pathInfo.PathNodes.AddRange(leaf.GetBranch()); pathInfo.PathNodes.Reverse(); return pathInfo; }
private static bool WindowOccuredInPath(LinkedAvidNode node, AvidModelWindow window) { return node.GetBranch().Any(lan => lan.Window.Equals(window)); }
public AvidModelWindow GetLinkedNode(AvidModelWindow currentNode) { return EndpointA.Equals(currentNode) ? EndpointB : EndpointA; }
private void TraverseDescendants(List <LinkedAvidNode> result, LinkedAvidNode node, AvidModelWindow destination, AvidPathingOptions options) { var validTransitions = node.Window.AdjacentWindows.ToList(); // Create a new list validTransitions.AddRange(node.Window.DiagonalWindows); foreach (var transition in validTransitions) { var linkedWindow = transition.GetLinkedNode(node.Window); // We encountered an excluded window or we are in a loop! if (linkedWindow.Excluded || WindowOccuredInPath(node, linkedWindow)) { continue; } if (!CanDoTransition(node, transition, options)) { continue; } var newNode = new LinkedAvidNode(linkedWindow, node, transition); if (newNode.NodeDistance / 2 > MaximumDepth) { continue; } ProfferNewDistance(linkedWindow, newNode.NodeDistance); if (!linkedWindow.Equals(destination)) { TraverseDescendants(result, newNode, destination, options); continue; } //New node is destination and we the path is at least minDistance, but not over maxDistance. result.Add(newNode); } }
/// <summary> /// Builds straight and diagonal links between two full rings, from amber ring either up or down. /// </summary> private static void ConnectFullRings(AvidModel model, AvidModelWindow[] ringA, AvidModelWindow[] ringB) { //We take for granted that windows with the same index in both arrays have the same direction. for (int i = 0; i < 12; i++) { int previousIndex = i == 0 ? 11 : i - 1; int nextIndex = (i + 1) % 12; model.Links.Add(new AvidModelLink(ringA[i], ringB[i], 2, false, false)); model.Links.Add(new AvidModelLink(ringA[i], ringB[previousIndex], 2, true, false)); model.Links.Add(new AvidModelLink(ringA[i], ringB[nextIndex], 2, true, false)); } }
private static bool WindowOccuredInPath(LinkedAvidNode node, AvidModelWindow window) { return(node.GetBranch().Any(lan => lan.Window.Equals(window))); }