/// <summary> /// Gets a list of node pairs that represent unique edges in the graph /// </summary> /// <returns>List of unordered pairs containing boundary nodes</returns> public List <UnorderedPair <BoundaryGraphNode, BoundaryGraphNode> > getEdgesAsUniquePairs() { // Find each unique edge as a pair of nodes using hashset HashSet <UnorderedPair <BoundaryGraphNode, BoundaryGraphNode> > edges = new HashSet <UnorderedPair <BoundaryGraphNode, BoundaryGraphNode> >(); foreach (BoundaryGraphNode node1 in this) { foreach (BoundaryGraphNode node2 in this) { // If they are equal skip if (node1 == node2) { continue; } // If they are not neighbors, skip if (!node1.HasNeighbor(node2)) { continue; } UnorderedPair <BoundaryGraphNode, BoundaryGraphNode> temp = new UnorderedPair <BoundaryGraphNode, BoundaryGraphNode>(node1, node2); edges.Add(temp); } } // Convert to list and return return(new List <UnorderedPair <BoundaryGraphNode, BoundaryGraphNode> >(edges)); }
// Follows MSDN spec public override bool Equals(object obj) { // If null or non castable, return false if (obj == null) { return(false); } UnorderedPair <T1, T2> other = obj as UnorderedPair <T1, T2>; if (other == null) { return(false); } return((item1.Equals(other.item1) && item2.Equals(other.item2)) || (item2.Equals(other.item1) && item1.Equals(other.item2))); }
// Checks existing graph for any intersections, then splits the edges that intersect // By a node with a parent to each boundary that caused the intersection public void Unify() { List <UnorderedPair <BoundaryGraphNode, BoundaryGraphNode> > edges = getEdgesAsUniquePairs(); // Intersect each edge using Line2D and split the edges int i, j; for (i = 0; i < edges.Count; i++) { UnorderedPair <BoundaryGraphNode, BoundaryGraphNode> edge1 = edges[i]; // Build the first line Line2D line1 = new Line2D(edge1.item1.position, edge1.item2.position); for (j = i; j < edges.Count; j++) { UnorderedPair <BoundaryGraphNode, BoundaryGraphNode> edge2 = edges[j]; // Skip if they are the same edge if (i == j) { continue; } // Skip if these edges are already neighbors (share a common vertex) // because they already intersect at that common vertex if (edge1.item1 == edge2.item1 || edge1.item1 == edge2.item2 || edge1.item2 == edge2.item1 || edge1.item2 == edge2.item2) { continue; } // NOTE: no need to equals test since this is a set of unique unordered pairs Line2D line2 = new Line2D(edge2.item1.position, edge2.item2.position); // test for intersection Vector2 intersection; if (line1.Intersect(line2, out intersection)) { // Create intersection node and split edges BoundaryGraphNode intersectionNode = new BoundaryGraphNode(intersection); intersectionNode.AddParentBoundary(edge1.item1.GetParentBoundaries()[0]); intersectionNode.AddParentBoundary(edge2.item1.GetParentBoundaries()[0]); AddNode(intersectionNode); // Remove neighbors edge1.item1.RemoveNeighbor(edge1.item2); // Method auto removes the reciprical relation too edge2.item1.RemoveNeighbor(edge2.item2); // Rejoin the verticies to intersection intersectionNode.AddNeighbor(edge1.item1); intersectionNode.AddNeighbor(edge1.item2); intersectionNode.AddNeighbor(edge2.item1); intersectionNode.AddNeighbor(edge2.item2); // Now we need to update our edges list so future runs of the loop interact with the new edges not the old ones edges.Remove(edge1); edges.Remove(edge2); // Decrement outter loop because we are removing the current index i--; // Add in the new edges we just formed. edges.Add(new UnorderedPair <BoundaryGraphNode, BoundaryGraphNode>(edge1.item1, intersectionNode)); edges.Add(new UnorderedPair <BoundaryGraphNode, BoundaryGraphNode>(edge1.item2, intersectionNode)); edges.Add(new UnorderedPair <BoundaryGraphNode, BoundaryGraphNode>(edge2.item1, intersectionNode)); edges.Add(new UnorderedPair <BoundaryGraphNode, BoundaryGraphNode>(edge2.item2, intersectionNode)); /* Deeper explanation: * We are removing the edge at index i, meaning that i+1 will become i. In order to not skip over i+1, * we decrement i by 1 so when the loop restarts, new i = i + 1 = old i * then we must immediately break the current inner loop since we are no longer matching intersections * against edge i, since we just found one and removed that edge from the list */ break; } } } }