/// <summary> /// /// </summary> /// <param name="uRay"></param> /// <param name="tolerance"></param> /// <returns></returns> private Vector2?IntersectN(Ray uRay, double tolerance = GeometrySettings.DEFAULT_TOLERANCE) { var intersection = _infiniteLine.Intersection(uRay._infiniteLine, tolerance); if (intersection.HasValue) { //check if computed point lies on our line. if (Contains(intersection.Value, tolerance) || uRay.Contains(intersection.Value, tolerance)) { return(intersection); } } return(null); }
public bool TestContains(Ray ray, Point p) { return(ray.Contains(p)); }
/// <summary> /// /// </summary> /// <param name="centre"></param> /// <param name="baseGraph"></param> /// <param name="origin"></param> /// <param name="destination"></param> /// <param name="singleVertices"></param> /// <param name="halfScan"></param> /// <returns name="visibleVertices">List of Vertices visible from the analysed vertex</returns> private static List <Vertex> VisibleVertices( Vertex centre, Graph baseGraph, Vertex origin = null, Vertex destination = null, List <Vertex> singleVertices = null, bool halfScan = true, bool reducedGraph = true, bool maxVisibility = false) { #region Initialize variables and sort vertices List <Edge> edges = baseGraph.Edges; List <Vertex> vertices = baseGraph.Vertices; if (origin != null) { vertices.Add(origin); } if (destination != null) { vertices.Add(destination); } if (singleVertices != null) { vertices.AddRange(singleVertices); } vertices = Vertex.OrderByRadianAndDistance(vertices, centre); #endregion #region Initialize openEdges //Initialize openEdges with any intersecting Edge with a XAxis Ray from the centre List <EdgeKey> openEdges = new List <EdgeKey>(); Ray sweepRay = Ray.XAxis(centre); foreach (Edge e in edges) { if (centre.OnEdge(e)) { continue; } if (sweepRay.Intersects(e)) { if (sweepRay.Contains(e.StartVertex)) { continue; } if (sweepRay.Contains(e.EndVertex)) { continue; } EdgeKey k = EdgeKey.ByRayAndEdge(sweepRay, e); openEdges.AddItemSorted(k); } } #endregion List <Vertex> visibleVertices = new List <Vertex>(); Vertex prev = null; bool prevVisible = false; for (var i = 0; i < vertices.Count; i++) { Vertex vertex = vertices[i]; if (vertex.Equals(centre) || vertex.Equals(prev)) { continue; } // v == to centre or to previous when updating graph //Check only half of Vertices as eventually they will become 'v' if (halfScan && Vertex.RadAngle(centre, vertex) > Math.PI) { break; } // Update Ray to new vertex; sweepRay = Ray.ByTwoVertices(centre, vertex); //Removing clock wise Edges incident on v if (openEdges.Count > 0 && baseGraph._vertexEdgesDict.ContainsKey(vertex)) { foreach (Edge edge in baseGraph._vertexEdgesDict[vertex]) { int orientation = Vertex.Orientation(centre, vertex, edge.GetVertexPair(vertex)); if (orientation == -1) { EdgeKey k = EdgeKey.ByRayAndEdge(sweepRay, edge); int index = openEdges.BisectIndex(k) - 1; index = (index < 0) ? openEdges.Count - 1 : index; if (openEdges.Count > 0 && openEdges.ElementAt(index).Equals(k)) { openEdges.RemoveAt(index); } } } } //Checking if p is visible from p. bool isVisible = false; Polygon vertexPolygon = null; if (vertex.Parent is Polygon) { baseGraph._polygonsDict.TryGetValue(vertex.Parent.Id, out vertexPolygon); } // If centre is on an edge of a inner polygon vertex belongs, check if the centre-vertex edge lies inside // or if on one of vertex's Edges. if (vertexPolygon != null && !vertexPolygon.isBoundary && vertexPolygon.ContainsVertex(centre)) { Vertex mid = Vertex.MidVertex(centre, vertex); // If mid is on any edge of vertex, is visible, otherwise not. foreach (Edge edge in baseGraph._vertexEdgesDict[vertex]) { if (mid.OnEdge(edge)) { isVisible = true; break; } } } //No collinear Vertices else if (prev == null || !prev.OnEdge(centre, vertex)) { if (openEdges.Count == 0) { if (vertexPolygon != null && vertexPolygon.isBoundary && vertexPolygon.ContainsVertex(centre)) { isVisible = vertexPolygon.ContainsVertex(Vertex.MidVertex(centre, vertex)); } else { isVisible = true; } } else if (vertex.OnEdge(openEdges.First().Edge) || !openEdges.First().Edge.Intersects(Edge.ByStartVertexEndVertex(centre, vertex))) { isVisible = true; } } //For collinear Vertices, if previous was not visible, vertex is not either else if (!prevVisible) { isVisible = false; } //For collinear Vertices, if prev was visible need to check that //the edge from prev to vertex does not intersect with any open edge else { isVisible = true; foreach (EdgeKey k in openEdges) { //if (!k.edge.Contains(prev) && EdgeIntersect(prev, vertex, k.edge)) if (EdgeIntersect(prev, vertex, k.Edge) && !k.Edge.Contains(prev)) { isVisible = false; break; } } // If visible (doesn't intersect any open edge) and edge 'prev-vertex' // is in any polygon, vertex is visible if it belongs to a external boundary if (isVisible && EdgeInPolygon(prev, vertex, baseGraph)) { isVisible = IsBoundaryVertex(vertex, baseGraph); } // If still visible (not inside polygon or is boundary vertex), // if not on 'centre-prev' edge means there is a gap between prev and vertex if (isVisible && !vertex.OnEdge(centre, prev)) { isVisible = !IsBoundaryVertex(vertex, baseGraph); } } //If vertex is visible and centre belongs to any polygon, checks //if the visible edge is interior to its polygon if (isVisible && centre.Parent is Polygon && !baseGraph.GetAdjecentVertices(centre).Contains(vertex)) { if (IsBoundaryVertex(centre, baseGraph) && IsBoundaryVertex(vertex, baseGraph)) { isVisible = EdgeInPolygon(centre, vertex, baseGraph); } else { isVisible = !EdgeInPolygon(centre, vertex, baseGraph); } } prev = vertex; prevVisible = isVisible; if (isVisible) { // Check reducedGraph if Vertices belongs to different _polygonsDict // TODO: If using ConvexHull, most of this could be removed. if (reducedGraph && centre.Parent != vertex.Parent) { bool isOriginExtreme = true; bool isTargetExtreme = true; // For reduced graphs, it is checked if the edge is extrem or not. // For an edge to be extreme, the Edges coincident at the start and end vertex // will have the same orientation (both clock or counter-clock wise) // Vertex belongs to a polygon if (centre.Parent is Polygon && !IsBoundaryVertex(centre, baseGraph)) { var orientationsOrigin = baseGraph.GetAdjecentVertices(centre).Select(otherVertex => Vertex.Orientation(vertex, centre, otherVertex)).ToList(); isOriginExtreme = orientationsOrigin.All(o => o == orientationsOrigin.First()); } if (centre.Parent is Polygon && !IsBoundaryVertex(vertex, baseGraph)) { var orientationsTarget = baseGraph.GetAdjecentVertices(vertex).Select(otherVertex => Vertex.Orientation(centre, vertex, otherVertex)).ToList(); isTargetExtreme = orientationsTarget.All(o => o == orientationsTarget.First()); } if (isTargetExtreme || isOriginExtreme) { visibleVertices.Add(vertex); } } else { visibleVertices.Add(vertex); } } if (baseGraph.Contains(vertex)) { foreach (Edge e in baseGraph._vertexEdgesDict[vertex]) { if (!centre.OnEdge(e) && Vertex.Orientation(centre, vertex, e.GetVertexPair(vertex)) == 1) { EdgeKey k = EdgeKey.ByRayAndEdge(sweepRay, e); openEdges.AddItemSorted(k); } } } if (isVisible && maxVisibility && vertex.Parent is Polygon) { List <Vertex> vertexPairs = baseGraph.GetAdjecentVertices(vertex); int firstOrientation = Vertex.Orientation(centre, vertex, vertexPairs[0]); int secondOrientation = Vertex.Orientation(centre, vertex, vertexPairs[1]); bool isColinear = false; //if both Edges lie on the same side of the centre-vertex edge or one of them is colinear or centre is contained on any of the Edges if (firstOrientation == secondOrientation || firstOrientation == 0 || secondOrientation == 0) { Vertex projectionVertex = null; // if both orientation are not on the same side, means that one of them is colinear isColinear = firstOrientation != secondOrientation ? true : false; foreach (EdgeKey ek in openEdges) { Vertex intersection = sweepRay.Intersection(ek.Edge) as Vertex; if (intersection != null && !intersection.Equals(vertex)) { projectionVertex = intersection; Polygon polygon; if (baseGraph._polygonsDict.TryGetValue(vertex.Parent.Id, out polygon)) { // If polygon is internal, don't compute intersection if mid point lies inside the polygon but not on its Edges Vertex mid = Vertex.MidVertex(vertex, intersection); bool containsEdge = Vertex.Orientation(centre, vertex, mid) != 0 && polygon.ContainsVertex(mid); if (!polygon.isBoundary && containsEdge) { projectionVertex = null; } } break; } } if (projectionVertex != null) { // if Edges are before rayEdge, projection Vertex goes after vertex if (firstOrientation == -1 || secondOrientation == -1) { visibleVertices.Add(projectionVertex); } else { visibleVertices.Insert(visibleVertices.Count - 1, projectionVertex); } } } if (vertexPairs.Contains(centre) && !visibleVertices.Contains(centre)) { visibleVertices.Add(centre); } } } return(visibleVertices); }
/// <summary> /// /// </summary> /// <param name="uRay"></param> /// <param name="tolerance"></param> /// <returns></returns> private Vector2? IntersectN(Ray uRay, double tolerance = GeometrySettings.DEFAULT_TOLERANCE) { var intersection = _infiniteLine.Intersection(uRay._infiniteLine, tolerance); if (intersection.HasValue) { //check if computed point lies on our line. if (Contains(intersection.Value, tolerance) || uRay.Contains(intersection.Value, tolerance)) { return intersection; } } return null; }