ContainsVertex() private method

private ContainsVertex ( Vector3 p ) : bool
p Vector3
return bool
Beispiel #1
0
        public void ContainsVertex_Pass_WhenIsPolygonVertex([Values(true, false)] bool ccw)
        {
            Polygon polygon = GetPolygon(ccw);
            Vertex  vertex1 = Vertex.ByCoordinates(10, 0);
            Vertex  vertex2 = Vertex.ByCoordinates(0, 10);

            Assert.IsTrue(polygon.ContainsVertex(vertex1));
            Assert.IsTrue(polygon.ContainsVertex(vertex2));
        }
Beispiel #2
0
        public void ContainsVertex_Pass_WhenIsOutside([Values(true, false)] bool ccw)
        {
            Polygon polygon = GetPolygon(ccw);
            Vertex  vertex1 = Vertex.ByCoordinates(-5, 5);
            Vertex  vertex2 = Vertex.ByCoordinates(0, 20);

            Assert.IsFalse(polygon.ContainsVertex(vertex1));
            Assert.IsFalse(polygon.ContainsVertex(vertex2));
        }
Beispiel #3
0
        public void ContainsVertex_Pass_WhenNotInsideButAlignedWithPolygonVertex([Values(true, false)] bool ccw)
        {
            Polygon polygon = GetPolygon(ccw);
            Vertex  vertex  = Vertex.ByCoordinates(0, 15);

            Assert.IsFalse(polygon.ContainsVertex(vertex));
        }
Beispiel #4
0
        public void ContainsVertex_Pass_WhenInsidePolygon([Values(true, false)] bool ccw)
        {
            Polygon polygon = GetPolygon(ccw);
            Vertex  vertex  = Vertex.ByCoordinates(0, 5);

            Assert.IsTrue(polygon.ContainsVertex(vertex));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="centre"></param>
        /// <param name="baseGraph"></param>
        /// <param name="origin"></param>
        /// <param name="destination"></param>
        /// <param name="singleVertices"></param>
        /// <param name="scan"></param>
        /// <returns name="visibleVertices">List of vertices visible from the analysed vertex</returns>
        public 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);
            }


            Vertex maxVertex   = vertices.OrderByDescending(v => v.DistanceTo(centre)).First();
            double maxDistance = centre.DistanceTo(maxVertex) * 1.5;
            //vertices = vertices.OrderBy(v => Point.RadAngle(centre.point, v.point)).ThenBy(v => centre.DistanceTo(v)).ToList();
            vertices = Vertex.OrderByRadianAndDistance(vertices, centre);

            #endregion

            #region Initialize openEdges
            //Initialize openEdges with any intersection edges on the half line
            //from centre to maxDistance on the XAxis
            List <EdgeKey> openEdges = new List <EdgeKey>();
            double         xMax      = Math.Abs(centre.X) + 1.5 * maxDistance;
            Edge           halfEdge  = Edge.ByStartVertexEndVertex(centre, Vertex.ByCoordinates(xMax, centre.Y, centre.Z));
            foreach (Edge e in edges)
            {
                if (centre.OnEdge(e))
                {
                    continue;
                }
                if (halfEdge.Intersects(e))
                {
                    if (e.StartVertex.OnEdge(halfEdge))
                    {
                        continue;
                    }
                    if (e.EndVertex.OnEdge(halfEdge))
                    {
                        continue;
                    }
                    EdgeKey k = new EdgeKey(halfEdge, 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;
                }
                //Removing clock wise edges incident on v
                if (openEdges.Count > 0 && baseGraph.graph.ContainsKey(vertex))
                {
                    foreach (Edge edge in baseGraph.graph[vertex])
                    {
                        int orientation = Vertex.Orientation(centre, vertex, edge.GetVertexPair(vertex));

                        if (orientation == -1)
                        {
                            EdgeKey k     = new EdgeKey(centre, vertex, 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.polygonId >= 0)
                {
                    baseGraph.polygons.TryGetValue(vertex.polygonId, 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.graph[vertex])
                    {
                        if (mid.OnEdge(edge))
                        {
                            isVisible = true;
                            break;
                        }
                    }
                }
                //No collinear vertices
                else if (prev == null || Vertex.Orientation(centre, prev, vertex) != 0 || !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(new Edge(centre, vertex))) //TODO: Change this intersection to Edge.Intersects
                    {
                        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, maxDistance))
                    {
                        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.polygonId >= 0 && !baseGraph.GetAdjecentVertices(centre).Contains(vertex))
                {
                    if (IsBoundaryVertex(centre, baseGraph) && IsBoundaryVertex(vertex, baseGraph))
                    {
                        isVisible = EdgeInPolygon(centre, vertex, baseGraph, maxDistance);
                    }
                    else
                    {
                        isVisible = !EdgeInPolygon(centre, vertex, baseGraph, maxDistance);
                    }
                }


                prev        = vertex;
                prevVisible = isVisible;


                if (isVisible)
                {
                    // Check reducedGraph if vertices belongs to different polygons
                    if (reducedGraph && centre.polygonId != vertex.polygonId)
                    {
                        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.polygonId >= 0 && !IsBoundaryVertex(centre, baseGraph))
                        {
                            var orientationsOrigin = baseGraph.GetAdjecentVertices(centre).Select(otherVertex => Vertex.Orientation(vertex, centre, otherVertex)).ToList();
                            isOriginExtreme = orientationsOrigin.All(o => o == orientationsOrigin.First());
                        }

                        if (vertex.polygonId >= 0 && !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.graph[vertex])
                    {
                        if (!centre.OnEdge(e) && Vertex.Orientation(centre, vertex, e.GetVertexPair(vertex)) == 1)
                        {
                            EdgeKey k = new EdgeKey(centre, vertex, e);
                            openEdges.AddItemSorted(k);
                        }
                    }
                }

                if (isVisible && maxVisibility && vertex.polygonId >= 0)
                {
                    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 rayVertex        = vertex.Translate(Vector.ByTwoVertices(centre, vertex), maxDistance);
                        Edge   rayEdge          = Edge.ByStartVertexEndVertex(centre, rayVertex);
                        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 = rayEdge.Intersection(ek.Edge) as Vertex;
                            if (intersection != null && !intersection.Equals(vertex))
                            {
                                projectionVertex = intersection;
                                Polygon polygon = null;
                                baseGraph.polygons.TryGetValue(vertex.polygonId, out polygon);
                                if (polygon != null)
                                {
                                    // 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);
        }