/// <summary> /// Creates an edge if it does not exist, or retrieves an edge with v1 and v2 as points if it does exist /// </summary> /// <param name="v1"></param> /// <param name="v2"></param> /// <returns></returns> public Edge CreateOrGet(Vertex v1, Vertex v2) { var edge = v1.Edges.FirstOrDefault(o => o.v1 == v2 || o.v2 == v2); if (edge == null) edge = CreateEdge(v1, v2); return edge; }
/// <summary> /// Creates an edge /// </summary> /// <param name="v1"></param> /// <param name="v2"></param> /// <returns></returns> public Edge CreateEdge(Vertex v1, Vertex v2) { Edge result = new Edge() { v1 = v1, v2 = v2 }; v1.Edges.Add(result); v2.Edges.Add(result); return result; }
/// <summary> /// Retriangulate the given triangle with P /// Basically removes the conflicting edge from the graph and introduces a new one from the vertex that was not on the removed edge and P /// </summary> /// <param name="triangle"></param> /// <param name="P"></param> private void Retriangulate(Triangle triangle, Vertex P) { var otherVertex = triangle.GetVertices().Single(o => o != triangle.conflictingEdge.v1 && o != triangle.conflictingEdge.v2); GM.DestroyEdge(triangle.conflictingEdge); GM.CreateOrGet(otherVertex, P); }
/// <summary> /// Recursively retrieves all conflicting triangles with P based on their circumcircle /// This method should be O(S) where S is the number of conflicting triangles, which is constant for a convex polygon /// However due to a bug this seems to be untrue. /// </summary> /// <param name="P"></param> /// <param name="currentTriangle"></param> /// <param name="SearchNr"></param> /// <param name="conflicting"></param> /// <returns></returns> private List<Triangle> GetRecursiveConflicitingTriangles(Vertex P, Triangle currentTriangle, int SearchNr, Edge conflicting) { var result = new List<Triangle>(); if(currentTriangle == null) return result; currentTriangle.conflictingEdge = conflicting; var center = currentTriangle.CreateTriangle().GetCircumCentre(); if (center.Distance(P.Point) <= center.Distance(currentTriangle.Edges[0].v1.Point)) { //If the circumcircle contains P, add the triangle to the list result.Add(currentTriangle); //And continue over all triangles adjecent to the current triangles foreach (var edge in currentTriangle.Edges) { //If the edge was not visited yet, continue if (!edge.VisitedBy.ContainsKey(SearchNr) || !edge.VisitedBy[SearchNr]) { edge.VisitedBy[SearchNr] = true; result.AddRange(GetRecursiveConflicitingTriangles(P, edge.GetOtherTriangle(currentTriangle), SearchNr, edge)); } } } return result; }
/// <summary> /// Generate a random vertex within the given boundaries /// </summary> /// <param name="xMin"></param> /// <param name="xMax"></param> /// <param name="yMin"></param> /// <param name="yMax"></param> /// <returns></returns> public static Vertex RandomVertex(int xMin, int xMax, int yMin, int yMax) { var x = RandomGenerator.Next(xMin, xMax); var y = RandomGenerator.Next(yMin, yMax); var vertex = new Vertex() { Point = new C2DPoint(x, y)}; return vertex; }
/// <summary> /// Splits an edge on a convex polygon into two edges by adding a vertex on a random position /// While keeping the Convex constraint. /// </summary> /// <param name="gm"></param> /// <param name="e"></param> /// <param name="maxOffset"></param> /// <param name="index"></param> /// <returns></returns> public static List<Edge> SplitConvexEdge(GraphManager gm, Edge e, int maxOffset, int index) { var edgeLine = e.CreateLine(); List<Edge> result = new List<Edge>(); //Create random point on the edge var offset = Convert.ToDouble(RandomGenerator.Next(0, 100)) / 122 + 0.1; var point = edgeLine.GetPointOn(offset); //Calculate offsets var dx = e.v2.Point.x - e.v1.Point.x; var dy = e.v2.Point.y - e.v1.Point.y; //Note swapping offsets for X and Y. var offsetX = Math.Abs(dx) / (dy); var offsetY = Math.Abs(dy) / (dx * -1); //Calculate the maximum endpoint for the new node. var endPoint = new C2DPoint(offsetX * maxOffset + point.x, offsetY * maxOffset + point.y); var newLine = new C2DLine(point, endPoint); var otherVertex1 = e.v1; var otherVertex2 = e.v2; var otherEdge1 = otherVertex1.GetOther(e).CreateLine(); var otherEdge2 = otherVertex2.GetOther(e).CreateLine(); //Compare with both other edges, to check if the new vertex would still result in a convex polygon. //If not, update the maximum offset for the new vertex if (otherVertex1.GetOther(e) != otherVertex2.GetOther(e)) { var intersections = new List<C2DPoint>(); otherEdge1.GrowFromCentre(100000000);//Hack: to check if they intersect. The library does not support rays in this case if (newLine.Crosses(otherEdge1, intersections)) { var newEndpoint = intersections.Single(); newLine = new C2DLine(point, newEndpoint); } intersections = new List<C2DPoint>(); otherEdge2.GrowFromCentre(100000000); //Hack: to check if they intersect. The library does not support rays in this case if (newLine.Crosses(otherEdge2, intersections)) { var newEndpoint = intersections.Single(); newLine = new C2DLine(point, newEndpoint); } } //Select a random point on the line (which is bound) var newlineOffset = Convert.ToDouble(RandomGenerator.Next(0, 100)) / 122+0.1; var newPoint = newLine.GetPointOn(offset); var newVertex = new Vertex() { Point = newPoint }; //Indexof might be very slow? Note this is just used for the creation of a testvertex gm.AddVertexAt(newVertex, gm.Vertices.IndexOf(otherVertex2)); gm.DestroyEdge(e);//Unregister the old edge result.Add(gm.CreateEdge(otherVertex1, newVertex)); //Add the two new ones result.Add(gm.CreateEdge(newVertex, otherVertex2)); // :) return result; }
/// <summary> /// Creates a new triangle on the given vertices /// Creades the edges if needed /// Updates references on existing edges /// </summary> /// <param name="v1"></param> /// <param name="v2"></param> /// <param name="v3"></param> /// <returns></returns> public Triangle CreateTriangleAndEdges(Vertex v1, Vertex v2, Vertex v3) { var triangle = new Triangle(); var edge1 = CreateOrGet(v1, v2); var edge2 = CreateOrGet(v2, v3); var edge3 = CreateOrGet(v3, v1); triangle.Edges.Add(edge1); triangle.Edges.Add(edge2); triangle.Edges.Add(edge3); return triangle; }
/// <summary> /// Inserts a vertex into the list at a specific location /// </summary> /// <param name="vertex"></param> /// <param name="index"></param> public void AddVertexAt(Vertex vertex, int index) { Vertices.Insert(index, vertex); }
/// <summary> /// Adds a vertex to the end of the list /// </summary> /// <param name="vertex"></param> public void AddVertex(Vertex vertex) { Vertices.Add(vertex); }
public Edge <TData, TMetric> EdgeForVertex(Vertex <TData, TMetric> vertex) { return(Vertices[vertex]); }
public bool Contains(Vertex <TData, TMetric> vertex) { return(Vertices.ContainsKey(vertex)); }