internal EdgeKey(gVertex centre, gVertex end, gEdge e) { Centre = centre; Vertex = end; Edge = e; RayEdge = gEdge.ByStartVertexEndVertex(centre, end); }
public static Dictionary <string, object> ShortestPath(VisibilityGraph visGraph, DSPoint origin, DSPoint destination) { if (visGraph == null) { throw new ArgumentNullException("visGraph"); } if (origin == null) { throw new ArgumentNullException("origin"); } if (destination == null) { throw new ArgumentNullException("destination"); } gVertex gOrigin = gVertex.ByCoordinates(origin.X, origin.Y, origin.Z); gVertex gDestination = gVertex.ByCoordinates(destination.X, destination.Y, destination.Z); Graphical.Graphs.VisibilityGraph visibilityGraph = visGraph.graph as Graphical.Graphs.VisibilityGraph; BaseGraph baseGraph = new BaseGraph() { graph = Graphical.Graphs.VisibilityGraph.ShortestPath(visibilityGraph, gOrigin, gDestination) }; return(new Dictionary <string, object>() { { "graph", baseGraph }, { "length", baseGraph.graph.edges.Select(e => e.Length).Sum() } }); }
/// <summary> /// Radian angle from a centre to another point /// </summary> /// <param name="centre"></param> /// <param name="point"></param> /// <returns name="rad">Radians</returns> internal static double RadAngle(DSPoint centre, DSPoint point) { gVertex v1 = gVertex.ByCoordinates(centre.X, centre.Y, centre.Z); gVertex v2 = gVertex.ByCoordinates(point.X, point.Y, point.Z); return(gVertex.RadAngle(v1, v2)); }
public static Surface IsovistFromPoint(BaseGraph baseGraph, DSPoint point) { if (baseGraph == null) { throw new ArgumentNullException("graph"); } if (point == null) { throw new ArgumentNullException("point"); } gVertex origin = gVertex.ByCoordinates(point.X, point.Y, point.Z); List <gVertex> vertices = Graphical.Graphs.VisibilityGraph.VertexVisibility(origin, baseGraph.graph); List <DSPoint> points = vertices.Select(v => Points.ToPoint(v)).ToList(); Surface isovist; // TODO: Implement better way of checking if polygon is self intersectingç Polygon polygon = Polygon.ByPoints(points); if (polygon.SelfIntersections().Length > 0) { points.Add(point); polygon = Polygon.ByPoints(points); } return(Surface.ByPatch(polygon)); }
internal static bool DoesIntersect(Line line, DSPoint point) { gEdge edge = gEdge.ByStartVertexEndVertex(Points.ToVertex(line.StartPoint), Points.ToVertex(line.EndPoint)); gVertex vertex = Points.ToVertex(point); return(vertex.OnEdge(edge)); }
/// <summary> /// Method to check if a polygon contains a point. /// </summary> /// <param name="polygon"></param> /// <param name="point"></param> /// <returns></returns> public static bool ContainsPoint(Polygon polygon, Point point) { gPolygon gPol = gPolygon.ByVertices(polygon.Points.Select(p => gVertex.ByCoordinates(p.X, p.Y, p.Z)).ToList()); gVertex vertex = gVertex.ByCoordinates(point.X, point.Y, point.Z); return(gPol.ContainsVertex(vertex)); }
/// <summary> /// Radian angle between two points from a centre. /// </summary> /// <param name="centre"></param> /// <param name="start"></param> /// <param name="end"></param> /// <returns></returns> public static double StartEndRadiansFromCentre(DSPoint centre, DSPoint start, DSPoint end) { gVertex c = ToVertex(centre); gVertex s = ToVertex(start); gVertex e = ToVertex(end); return(gVertex.ArcRadAngle(c, s, e)); }
internal static bool PolygonContainsPoint(Polygon polygon, DSPoint point) { gVertex vertex = Points.ToVertex(point); var vertices = polygon.Points.Select(p => Points.ToVertex(p)).ToList(); gPolygon gPolygon = gPolygon.ByVertices(vertices, false); return(gPolygon.ContainsVertex(vertex)); }
/// <summary> /// Updates the edge and Pair event with a new gVertex /// </summary> /// <param name="newPairVertex"></param> public void UpdatePairVertex(gVertex newPairVertex) { this.Edge = gEdge.ByStartVertexEndVertex(this.Vertex, newPairVertex); this.Pair = new SweepEvent(newPairVertex, this.Edge) { Pair = this, IsLeft = !this.IsLeft, polygonType = this.polygonType }; }
public void ByTwoVerticesTest() { gVertex vertex1 = gVertex.ByCoordinates(10, 10, 10); gVertex vertex2 = gVertex.ByCoordinates(10, 14, 13); gVector v = gVector.ByTwoVertices(vertex1, vertex2); Assert.AreEqual(0, v.X); Assert.AreEqual(4, v.Y); Assert.AreEqual(3, v.Z); Assert.AreEqual(5, v.Length); }
public static List <gVertex> VertexVisibility(gVertex origin, Graph baseGraph) { gVertex o = origin; if (baseGraph.Contains(origin)) { o = baseGraph.vertices[baseGraph.vertices.IndexOf(origin)]; } var visibleVertices = VisibilityGraph.VisibleVertices(o, baseGraph, null, null, null, false, false, true); return(visibleVertices); }
internal static bool EdgeIntersect(gVertex start, gVertex end, gEdge edge) { //For simplicity, it only takes into acount the 2d projection to the xy plane, //so the result will be based on a porjection even if points have z values. bool intersects = EdgeIntersectProjection( start, end, edge.StartVertex, edge.EndVertex, "xy"); return(intersects); }
public List <gEdge> GetVertexEdges(gVertex vertex) { List <gEdge> edgesList = new List <gEdge>(); if (graph.TryGetValue(vertex, out edgesList)) { return(edgesList); } else { //graph.Add(vertex, new List<gEdge>()); return(new List <gEdge>()); } }
/// <summary> /// Implementation of IComparable interaface /// </summary> /// <param name="other"></param> /// <returns></returns> public int CompareTo(EdgeKey other) { if (other == null) { return(1); } if (Edge.Equals(other.Edge)) { return(1); } if (!VisibilityGraph.EdgeIntersect(RayEdge, other.Edge)) { return(-1); } double selfDist = DistanceToIntersection(Centre, Vertex, Edge); double otherDist = DistanceToIntersection(Centre, Vertex, other.Edge); if (selfDist > otherDist) { return(1); } else if (selfDist < otherDist) { return(-1); } else { gVertex sameVertex = null; if (other.Edge.Contains(Edge.StartVertex)) { sameVertex = Edge.StartVertex; } else if (other.Edge.Contains(Edge.EndVertex)) { sameVertex = Edge.EndVertex; } double aslf = gVertex.ArcRadAngle(Vertex, Centre, Edge.GetVertexPair(sameVertex)); double aot = gVertex.ArcRadAngle(Vertex, Centre, other.Edge.GetVertexPair(sameVertex)); if (aslf < aot) { return(-1); } else { return(1); } } }
public void IsCoplanarToTest() { gVertex v1 = gVertex.ByCoordinates(0, 0, 0); gVertex v2 = gVertex.ByCoordinates(0, 10, 0); gVertex v3 = gVertex.ByCoordinates(10, 10, 10); gVertex v4 = gVertex.ByCoordinates(-10, 10, 10); var a = gEdge.ByStartVertexEndVertex(v1, v2); // Vertical y axis var b = gEdge.ByStartVertexEndVertex(v1, v3); // angled coincident on origin var c = gEdge.ByStartVertexEndVertex(v3, v4); // parallel to xy plane Assert.IsTrue(a.IsCoplanarTo(b)); Assert.IsFalse(a.IsCoplanarTo(c)); Assert.IsTrue(b.IsCoplanarTo(c)); }
public void IntersectionTest() { gVertex a1 = gVertex.ByCoordinates(0, 0, 0); gVertex a2 = gVertex.ByCoordinates(10, 10, 10); gVertex b1 = gVertex.ByCoordinates(0, 10, 0); gVertex b2 = gVertex.ByCoordinates(10, 0, 10); gVertex c1 = gVertex.ByCoordinates(0, 10, 5); gVertex c2 = gVertex.ByCoordinates(10, 10, 5); gVertex d1 = gVertex.ByCoordinates(0, 15, 0); gVertex d2 = gVertex.ByCoordinates(10, 15, 10); gVertex e1 = gVertex.ByCoordinates(10, 0, 0); gVertex e2 = gVertex.ByCoordinates(10, 10, 0); gVertex f1 = a1; gVertex f2 = b1; var a = gEdge.ByStartVertexEndVertex(a1, a2); var b = gEdge.ByStartVertexEndVertex(b1, b2); var c = gEdge.ByStartVertexEndVertex(c1, c2); var d = gEdge.ByStartVertexEndVertex(d1, d2); var e = gEdge.ByStartVertexEndVertex(e1, e2); var f = gEdge.ByStartVertexEndVertex(f1, f2); var g = gEdge.ByStartVertexEndVertex(a1, e1); var h = gEdge.ByStartVertexEndVertex(b1, gVertex.ByCoordinates(2.5, 5, 0)); var xaligned = gEdge.ByStartVertexEndVertex(a1, gVertex.ByCoordinates(114.750, 0, 0)); var xCoincident = gEdge.ByStartVertexEndVertex(e1, b1); var side = gEdge.ByStartVertexEndVertex( gVertex.ByCoordinates(-17.950, 31.090, 0), gVertex.ByCoordinates(-7.650, 48.930, 0) ); var rayEdge = gEdge.ByStartVertexEndVertex( gVertex.ByCoordinates(-49.544, 39.031, 0), gVertex.ByCoordinates(5827.960, 39.031, 0) ); //gVertex ab = a.Intersection(b); // Intersecting //gVertex ac = a.Intersection(c); // Skew edges //gVertex ad = a.Intersection(d); // Coplanar but not intersecting //gVertex ef = e.Intersection(f); // Coplanar and parallel //gVertex gh = g.Intersection(h); // Coplanar, not intersecting and second edge shorter than first //Assert.NotNull(ab); //Assert.AreEqual(5, ab.X); //Assert.AreEqual(5, ab.Y); //Assert.IsNull(ac); //Assert.IsNull(ad); //Assert.IsNull(ef); //Assert.IsNull(gh); //Assert.NotNull(rayEdge.Intersection(side)); Assert.NotNull(xaligned.Intersection(xCoincident)); }
internal void UpdateEventPair(SweepEvent swEvent, gVertex newVertexPair) { var pairEvent = swEvent.Pair; int index = eventsQ.IndexOf(pairEvent); // Update event and its pair with the new pair vertex swEvent.UpdatePairVertex(newVertexPair); pairEvent.UpdatePairVertex(newVertexPair); // Update position of pairEvent in PriorityQ according to its new pair. eventsQ.UpdateAtIndex(index); // Add both new pairs to the PriorityQ eventsQ.Add(swEvent.Pair); eventsQ.Add(pairEvent.Pair); }
internal static bool EdgeInPolygon(gVertex v1, gVertex v2, Graph graph, double maxDistance) { //Not on the same polygon if (v1.polygonId != v2.polygonId) { return(false); } //At least one doesn't belong to any polygon if (v1.polygonId == -1 || v2.polygonId == -1) { return(false); } gVertex midVertex = gVertex.MidVertex(v1, v2); return(graph.polygons[v1.polygonId].ContainsVertex(midVertex)); }
internal static bool EdgeIntersectProjection( gVertex p1, gVertex q1, gVertex p2, gVertex q2, string plane = "xy") { //For more details https://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/ int o1 = gVertex.Orientation(p1, q1, p2, plane); int o2 = gVertex.Orientation(p1, q1, q2, plane); int o3 = gVertex.Orientation(p2, q2, p1, plane); int o4 = gVertex.Orientation(p2, q2, q1, plane); //General case if (o1 != o2 && o3 != o4) { return(true); } //Special Cases // p1, q1 and p2 are colinear and p2 lies on segment p1q1 if (o1 == 0 && gVertex.OnEdgeProjection(p1, p2, q1, plane)) { return(true); } // p1, q1 and p2 are colinear and q2 lies on segment p1q1 if (o2 == 0 && gVertex.OnEdgeProjection(p1, q2, q1, plane)) { return(true); } // p2, q2 and p1 are colinear and p1 lies on segment p2q2 if (o3 == 0 && gVertex.OnEdgeProjection(p2, p1, q2, plane)) { return(true); } // p2, q2 and q1 are colinear and q1 lies on segment p2q2 if (o4 == 0 && gVertex.OnEdgeProjection(p2, q1, q2, plane)) { return(true); } return(false); //Doesn't fall on any of the above cases }
internal static double DistanceToIntersection(gVertex centre, gVertex maxVertex, gEdge e) { var centreProj = gVertex.ByCoordinates(centre.X, centre.Y, 0); var maxProj = gVertex.ByCoordinates(maxVertex.X, maxVertex.Y, 0); var startProj = gVertex.ByCoordinates(e.StartVertex.X, e.StartVertex.Y, 0); var endProj = gVertex.ByCoordinates(e.EndVertex.X, e.EndVertex.Y, 0); gEdge rayEdge = gEdge.ByStartVertexEndVertex(centreProj, maxProj); gEdge edgeProj = gEdge.ByStartVertexEndVertex(startProj, endProj); gBase intersection = rayEdge.Intersection(edgeProj); if (intersection != null && intersection.GetType() == typeof(gVertex)) { return(centre.DistanceTo((gVertex)intersection)); } else { return(0); } }
/// <summary> /// Computes edges and creates polygons from those connected by vertices. /// </summary> public void BuildPolygons() { var computedVertices = new List <gVertex>(); foreach (gVertex v in vertices) { // If already belongs to a polygon or is not a polygon vertex or already computed if (computedVertices.Contains(v) || v.polygonId >= 0 || graph[v].Count > 2) { continue; } computedVertices.Add(v); gPolygon polygon = new gPolygon(GetNextId(), false); polygon.AddVertex(v); foreach (gEdge edge in GetVertexEdges(v)) { gEdge nextEdge = edge; gVertex nextVertex = edge.GetVertexPair(v); while (!polygon.vertices.Contains(nextVertex)) { computedVertices.Add(nextVertex); polygon.AddVertex(nextVertex); polygon.edges.Add(nextEdge); //It is extreme vertex, polygon not closed if (graph[nextVertex].Count < 2) { break; } nextEdge = graph[nextVertex].Where(e => !e.Equals(nextEdge)).First(); nextVertex = nextEdge.GetVertexPair(nextVertex); } if (!polygon.edges.Last().Equals(nextEdge)) { polygon.edges.Add(nextEdge); } } this.polygons.Add(polygon.id, polygon); } }
/// <summary> /// Creates a new Graph by a set of lines. /// </summary> /// <param name="lines">Lines</param> /// <returns name="baseGraph">Base Graph</returns> public static BaseGraph ByLines(List <Line> lines) { if (lines == null) { throw new NullReferenceException("lines"); } BaseGraph g = new BaseGraph() { graph = new Graphical.Graphs.Graph() }; foreach (Line line in lines) { gVertex start = Geometry.Points.ToVertex(line.StartPoint); gVertex end = Geometry.Points.ToVertex(line.EndPoint); g.graph.AddEdge(gEdge.ByStartVertexEndVertex(start, end)); } return(g); }
public static VisibilityGraph Merge(List <VisibilityGraph> graphs) { Graph graph = new Graph(); List <gEdge> edges = new List <gEdge>(); foreach (VisibilityGraph g in graphs) { Dictionary <int, int> oldNewIds = new Dictionary <int, int>(); foreach (gPolygon p in g.baseGraph.polygons.Values) { int nextId = graph.GetNextId(); oldNewIds.Add(p.id, nextId); gPolygon polygon = (gPolygon)p.Clone(); polygon.id = nextId; graph.polygons.Add(nextId, polygon); } foreach (gEdge e in g.edges) { gVertex start = (gVertex)e.StartVertex.Clone(); gVertex end = (gVertex)e.EndVertex.Clone(); //start.polygonId = oldNewIds[start.polygonId]; //end.polygonId = oldNewIds[end.polygonId]; edges.Add(gEdge.ByStartVertexEndVertex(start, end)); } } VisibilityGraph visibilityGraph = new VisibilityGraph() { baseGraph = new Graph(graph.polygons.Values.ToList()), }; foreach (gEdge edge in edges) { visibilityGraph.AddEdge(edge); } return(visibilityGraph); }
public static Graph ShortestPath(VisibilityGraph visibilityGraph, gVertex origin, gVertex destination) { Graph shortest; bool containsOrigin = visibilityGraph.Contains(origin); bool containsDestination = visibilityGraph.Contains(destination); if (containsOrigin && containsDestination) { shortest = Algorithms.Dijkstra(visibilityGraph, origin, destination); } else { gVertex gO = (!containsOrigin) ? origin : null; gVertex gD = (!containsDestination) ? destination : null; Graph tempGraph = new Graph(); if (!containsOrigin) { foreach (gVertex v in VisibleVertices(origin, visibilityGraph.baseGraph, null, gD, null, false, true)) { tempGraph.AddEdge(new gEdge(origin, v)); } } if (!containsDestination) { foreach (gVertex v in VisibleVertices(destination, visibilityGraph.baseGraph, gO, null, null, false, true)) { tempGraph.AddEdge(new gEdge(destination, v)); } } shortest = Algorithms.Dijkstra(visibilityGraph, origin, destination, tempGraph); } return(shortest); }
internal static Dictionary <gVertex, List <DSCurve> > CurvesDependency(List <DSCurve> curves) { Dictionary <gVertex, List <DSCurve> > graph = new Dictionary <gVertex, List <DSCurve> >(); foreach (DSCurve curve in curves) { gVertex start = Points.ToVertex(curve.StartPoint); gVertex end = Points.ToVertex(curve.EndPoint); List <DSCurve> startList = new List <DSCurve>(); List <DSCurve> endList = new List <DSCurve>(); if (graph.TryGetValue(start, out startList)) { startList.Add(curve); } else { graph.Add(start, new List <DSCurve>() { curve }); } if (graph.TryGetValue(end, out endList)) { endList.Add(curve); } else { graph.Add(end, new List <DSCurve>() { curve }); } } return(graph); }
internal static void AddColouredVertex(IRenderPackage package, gVertex vertex, DSCore.Color color) { package.AddPointVertex(vertex.X, vertex.Y, vertex.Z); package.AddPointVertexColor(color.Red, color.Green, color.Blue, color.Alpha); }
public static Graph Dijkstra(Graph graph, gVertex origin, gVertex destination, Graph tempGraph = null) { MinPriorityQ <gVertex, double> Q = new MinPriorityQ <gVertex, double>(); graph.vertices.ForEach(v => Q.Add(v, Double.PositiveInfinity)); //If tempGraph is not null, means graph doesn't contain origin and/or destination vertices. if (graph.Contains(origin)) { Q.UpdateValue(origin, 0); } else { Q.Add(origin, 0); } if (!graph.Contains(destination)) { Q.Add(destination, Double.PositiveInfinity); } Dictionary <gVertex, gVertex> ParentVertices = new Dictionary <gVertex, gVertex>(); List <gVertex> S = new List <gVertex>(); while (Q.Size > 0) { double minDistance = Q.PeekValue(); gVertex vertex = Q.Take(); S.Add(vertex); if (vertex.Equals(destination)) { break; } List <gEdge> edges = new List <gEdge>(); edges.AddRange(graph.GetVertexEdges(vertex)); if (tempGraph != null && tempGraph.edges.Any()) { edges.AddRange(tempGraph.GetVertexEdges(vertex)); } foreach (gEdge e in edges) { gVertex w = e.GetVertexPair(vertex); double newLength = minDistance + e.Length; if (!S.Contains(w) && newLength < Q.GetValue(w)) { Q.UpdateValue(w, newLength); //dist[w] = newLength; ParentVertices[w] = vertex; } } } Graph path = new Graph(); gVertex dest = destination; while (dest != origin) { gVertex parent = ParentVertices[dest]; path.AddEdge(new gEdge(dest, parent)); dest = parent; } return(path); }
internal void ProcessIntersection(SweepEvent next, SweepEvent prev, List <gBase> intersections = null) { gBase intersection = next.Edge.Intersection(prev.Edge); bool inserted = false; #region Is gVertex if (intersection is gVertex) { gVertex v = intersection as gVertex; // Intersection is between extremes vertices foreach (SweepEvent sw in new List <SweepEvent>() { next, prev }) { if (!sw.Edge.Contains(v)) { if (intersections != null && !inserted) { intersections.Add(v); inserted = true; } UpdateEventPair(sw, v); } } } #endregion #region Is gEdge else if (intersection is gEdge) { gEdge e = intersection as gEdge; // On Case 3 below, last half of prev event is added as intersection, // and on next loop it will be case 1 with the same edge, so this avoids duplicates if (intersections != null && (!intersections.Any() || !intersections.Last().Equals(e))) { intersections.Add(e); inserted = true; } // Case 1: events are coincident (same edge) // (prev)--------------------(prevPair) // (next)--------------------(nextPair) if (next.Equals(prev)) { // Setting nextEvent as not contributing instead of deleting it // as doing so will make it's pair a lonely poor thing. next.Label = SweepEventLabel.NoContributing; prev.Label = next.InOut == prev.InOut ? SweepEventLabel.SameTransition : SweepEventLabel.DifferentTransition; } // Case 2: same start point, prev will be always shorter // as on PriorityQ it must have been sorted before next // (prev)----------(prevPair) // (next)--------------------(nextPair) else if (prev.Vertex.Equals(next.Vertex)) { // TODO: check this is true in all cases gVertex dividingVtx = prev.Pair.Vertex; UpdateEventPair(next, dividingVtx); } // Case 3: same end point, next will be always shorter // as on PriorityQ it must have been sorted after next // (prev)--------------------(prevPair) // (next)-------------(nextPair) else if (prev.Pair.Vertex.Equals(next.Pair.Vertex)) { // TODO: check this is true in all cases gVertex dividingVtx = next.Vertex; UpdateEventPair(prev, dividingVtx); } // Case 4: events overlap // (prev)--------------------(prevPair) // (next)--------------------(nextPair) else if (prev < next && prev.Pair < next.Pair) { // TODO: check this is true in all cases gVertex prevDividingVtx = next.Vertex; gVertex nextDividingVtx = prev.Pair.Vertex; UpdateEventPair(prev, prevDividingVtx); UpdateEventPair(next, nextDividingVtx); } // Case 5: prev fully contains next // (prev)--------------------(prevPair) // (next)---(nextPair) else if (prev < next && prev.Pair > next.Pair) { next.Label = SweepEventLabel.NoContributing; gVertex dividingVtx = next.Vertex; gVertex pairDividingVtx = next.Pair.Vertex; // Storing reference to prevPair before updating it var prevPair = prev.Pair; UpdateEventPair(prev, dividingVtx); UpdateEventPair(prevPair, pairDividingVtx); } else { throw new Exception("Case not contemplated? Damm!"); } } #endregion #endregion }
//Vector-plane intersection https://math.stackexchange.com/questions/100439/determine-where-a-vector-will-intersect-a-plane #region Public Methods /// <summary> /// Returns the mid point between two points. /// </summary> /// <param name="point1"></param> /// <param name="point2"></param> /// <returns></returns> public static DSPoint MidPoint(DSPoint point1, DSPoint point2) { gVertex midVertex = gVertex.MidVertex(ToVertex(point1), ToVertex(point2)); return(ToPoint(midVertex)); }
internal static DSPoint ToPoint(this gVertex vertex) { return(DSPoint.ByCoordinates(vertex.X, vertex.Y, vertex.Z)); }