public EuclideanGraphTriangle <T>[] Subdivide(EuclideanGraphNode <T> point) { return(new EuclideanGraphTriangle <T>[] { new EuclideanGraphTriangle <T>(point, Corners[0], Corners[1]), new EuclideanGraphTriangle <T>(point, Corners[1], Corners[2]), new EuclideanGraphTriangle <T>(point, Corners[2], Corners[0]) }); }
private void AddEdge(EuclideanGraphNode <T> node1, EuclideanGraphNode <T> node2) { if (!ContainsEdge(node1, node2)) { EuclideanGraphEdge <T> newEdge = new EuclideanGraphEdge <T>(node1, node2); Edges.Add(newEdge); node1.Edges.Add(newEdge); node2.Edges.Add(newEdge); } }
private bool ContainsEdge(EuclideanGraphNode <T> node1, EuclideanGraphNode <T> node2) { foreach (EuclideanGraphEdge <T> edge in Edges) { if ((edge.Nodes[0] == node1 && edge.Nodes[1] == node2) || (edge.Nodes[0] == node2 && edge.Nodes[1] == node1)) { return(true); } } return(false); }
public EuclideanGraphNode <T> GetOppositeCorner(EuclideanGraphNode <T>[] edge) { EuclideanGraphNode <T> opposite = null; foreach (EuclideanGraphNode <T> corner in Corners) { if (edge[0] != corner && edge[1] != corner) { opposite = corner; } } return(opposite); }
/// <summary> /// Attempt to generate the Delaunay triangulation for this graph. /// Returns null on success. Otherwise returns the node which could not /// be traingulated. /// </summary> /// <returns></returns> private EuclideanGraphNode <T> AttemptDelaunayTriangulation() { // Create convex hull which spans the data EuclideanGraphNode <T> anchor1 = new EuclideanGraphNode <T>(new Vector2(0f, 2f * Radius)); EuclideanGraphNode <T> anchor2 = new EuclideanGraphNode <T>(new Vector2(Mathf.Sqrt(3f) * Radius, -Radius)); EuclideanGraphNode <T> anchor3 = new EuclideanGraphNode <T>(new Vector2(-Mathf.Sqrt(3f) * Radius, -Radius)); DelaunayTree.DelaunayTree <T> tree = new DelaunayTree.DelaunayTree <T>(new EuclideanGraphTriangle <T>(anchor1, anchor2, anchor3)); int nodesInserted = 0; // Insert one node at a time, always updating the delaunay triangulation foreach (EuclideanGraphNode <T> node in Nodes) { ProgressTracker.Instance.PushActivity("Inserting node " + (nodesInserted++).ToString() + "/" + Nodes.Count.ToString()); EuclideanGraphTriangle <T> entryTriangle = tree.GetTriangle(node.GetPosition()); if (entryTriangle == null) { ProgressTracker.Instance.PopActivity(); return(node); } EuclideanGraphTriangle <T>[] subdivisions = entryTriangle.Subdivide(node); tree.Subdivide(entryTriangle, subdivisions); Queue <EuclideanGraphNode <T>[]> edgesToVerify = entryTriangle.GetEdges(); while (edgesToVerify.Count > 0) { VerifyNextEdge(tree, edgesToVerify); } ProgressTracker.Instance.PopActivity(); } ProgressTracker.Instance.PushActivity("Gathering edges"); // Transfer to edge data structure List <EuclideanGraphTriangle <T> > triangles = tree.GetCurrentTriangles(); foreach (EuclideanGraphTriangle <T> triangle in triangles) { Queue <EuclideanGraphNode <T>[]> edges = triangle.GetEdges(); foreach (EuclideanGraphNode <T>[] edge in edges) { if (edge[0].HasData && edge[1].HasData) { AddEdge(edge[0], edge[1]); } } } ProgressTracker.Instance.PopActivity(); return(null); }
public EuclideanGraphNode <T>[][] GetOtherEdges(EuclideanGraphNode <T>[] edge) { EuclideanGraphNode <T> opposite = GetOppositeCorner(edge); EuclideanGraphNode <T>[][] otherEdges = new EuclideanGraphNode <T> [2][]; otherEdges[0] = new EuclideanGraphNode <T>[] { opposite, edge[0] }; otherEdges[1] = new EuclideanGraphNode <T>[] { opposite, edge[1] }; return(otherEdges); }
/// <summary> /// /// </summary> /// <returns></returns> public void GenerateDelaunayTriangulation() { ProgressTracker.Instance.PushActivity("Triangulating"); EuclideanGraphNode <T> node = AttemptDelaunayTriangulation(); int attempt = 2; while (node != null) { ProgressTracker.Instance.PushActivity("Attempt " + attempt++); Nodes.Remove(node); Nodes.AddFirst(node); node = AttemptDelaunayTriangulation(); ProgressTracker.Instance.PopActivity(); } ProgressTracker.Instance.PopActivity(); }
private void VerifyNextEdge(DelaunayTree.DelaunayTree <T> delaunayTree, Queue <EuclideanGraphNode <T>[]> edgesToVerify) { EuclideanGraphNode <T>[] edge = edgesToVerify.Dequeue(); EuclideanGraphTriangle <T> triangle1 = null; EuclideanGraphTriangle <T> triangle2 = null; delaunayTree.GetTrianglesOnEdge(edge, ref triangle1, ref triangle2); //There is only one triangle on an edge between anchor points (which cannot be flipped) if (triangle2 == null) { return; } float alpha = triangle1.GetOppositeAngle(edge); float beta = triangle2.GetOppositeAngle(edge); // If the sum of opposite angles is > 180 we need to flip if (alpha + beta > 180f) { // Enqueue other edges which may need to be flipped as a result of this flip EuclideanGraphNode <T>[][] otherEdges = triangle1.GetOtherEdges(edge); edgesToVerify.Enqueue(otherEdges[0]); edgesToVerify.Enqueue(otherEdges[1]); otherEdges = triangle2.GetOtherEdges(edge); edgesToVerify.Enqueue(otherEdges[0]); edgesToVerify.Enqueue(otherEdges[1]); // Create two new triangles EuclideanGraphNode <T> corner1 = triangle1.GetOppositeCorner(edge); EuclideanGraphNode <T> corner2 = triangle2.GetOppositeCorner(edge); EuclideanGraphTriangle <T> newTriangle1 = new EuclideanGraphTriangle <T>(corner1, corner2, edge[0]); EuclideanGraphTriangle <T> newTriangle2 = new EuclideanGraphTriangle <T>(corner1, corner2, edge[1]); // Update the Delaunay Tree delaunayTree.Replace(triangle1, triangle2, newTriangle1, newTriangle2); } }
private int PathLength(EuclideanGraphNode <T> node1, EuclideanGraphNode <T> node2, int maxIterations = int.MaxValue) { List <EuclideanGraphNode <T> > visited = new List <EuclideanGraphNode <T> >(); List <EuclideanGraphNode <T> > toVisitNow = new List <EuclideanGraphNode <T> >(); List <EuclideanGraphNode <T> > toVisitLater = new List <EuclideanGraphNode <T> >(); toVisitNow.Add(node1); int iterations = 0; while (toVisitNow.Count > 0 && iterations < maxIterations) { foreach (EuclideanGraphNode <T> node in toVisitNow) { if (node == node2) { return(iterations); } else { foreach (EuclideanGraphNode <T> neighbor in node.GetNeighbors()) { if (!visited.Contains(neighbor)) { toVisitLater.Add(neighbor); } } } } iterations++; visited.AddRange(toVisitNow); toVisitNow = toVisitLater; toVisitLater = new List <EuclideanGraphNode <T> >(); } return(-1); }
public EuclideanGraphTriangle(EuclideanGraphNode <T> corner1, EuclideanGraphNode <T> corner2, EuclideanGraphNode <T> corner3) { Corners = new EuclideanGraphNode <T>[] { corner1, corner2, corner3 }; }
public float GetOppositeAngle(EuclideanGraphNode <T>[] edge) { EuclideanGraphNode <T> opposite = GetOppositeCorner(edge); return(Vector2.Angle(edge[0].GetPosition() - opposite.GetPosition(), edge[1].GetPosition() - opposite.GetPosition())); }
public EuclideanGraphEdge(EuclideanGraphNode <T> node1, EuclideanGraphNode <T> node2) { Active = true; Nodes = new EuclideanGraphNode <T>[] { node1, node2 }; }