コード例 #1
0
ファイル: Curves.cs プロジェクト: alvpickmans/GraphicalDynamo
        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));
        }
コード例 #2
0
 internal EdgeKey(gVertex centre, gVertex end, gEdge e)
 {
     Centre  = centre;
     Vertex  = end;
     Edge    = e;
     RayEdge = gEdge.ByStartVertexEndVertex(centre, end);
 }
コード例 #3
0
        private void AddNewEvent(gEdge edge, PolygonType polType = PolygonType.None)
        {
            SweepEvent swStart = new SweepEvent(edge.StartVertex, edge)
            {
                Label = SweepEventLabel.Normal
            };
            SweepEvent swEnd = new SweepEvent(edge.EndVertex, edge)
            {
                Label = SweepEventLabel.Normal
            };

            swStart.Pair   = swEnd;
            swEnd.Pair     = swStart;
            swStart.IsLeft = swStart < swEnd;
            swEnd.IsLeft   = !swStart.IsLeft;

            if (polType != PolygonType.None)
            {
                swStart.polygonType = polType;
                swEnd.polygonType   = polType;
            }

            eventsList.AddItemSorted(swStart);
            eventsList.AddItemSorted(swEnd);
        }
コード例 #4
0
 internal EdgeKey(gEdge rayEdge, gEdge e)
 {
     RayEdge = rayEdge;
     Edge    = e;
     Centre  = RayEdge.StartVertex;
     Vertex  = RayEdge.EndVertex;
 }
コード例 #5
0
ファイル: Base.cs プロジェクト: alvpickmans/GraphicalDynamo
        internal static void AddColouredEdge(IRenderPackage package, gEdge edge, DSCore.Color color)
        {
            package.AddLineStripVertex(edge.StartVertex.X, edge.StartVertex.Y, edge.StartVertex.Z);
            package.AddLineStripVertex(edge.EndVertex.X, edge.EndVertex.Y, edge.EndVertex.Z);

            package.AddLineStripVertexColor(color.Red, color.Green, color.Blue, color.Alpha);
            package.AddLineStripVertexColor(color.Red, color.Green, color.Blue, color.Alpha);

            package.AddLineStripVertexCount(2);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        internal List <gEdge> VisibilityAnalysis(Graph baseGraph, List <gVertex> vertices, bool reducedGraph, bool halfScan)
        {
            List <gEdge> visibleEdges = new List <gEdge>();

            foreach (gVertex v in vertices)
            {
                foreach (gVertex v2 in VisibleVertices(v, baseGraph, null, null, null, halfScan, reducedGraph))
                {
                    gEdge newEdge = new gEdge(v, v2);
                    if (!visibleEdges.Contains(newEdge))
                    {
                        visibleEdges.Add(newEdge);
                    }
                }
            }

            return(visibleEdges);
        }
コード例 #8
0
ファイル: Graph.cs プロジェクト: bulutkartal/Graphical
        /// <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);
            }
        }
コード例 #9
0
        /// <summary>
        /// Adds specific points as gVertices to the VisibilityGraph Graph
        /// </summary>
        /// <param name="visibilityGraph">VisibilityGraph Graph</param>
        /// <param name="vertices">Points to add as gVertices</param>
        /// <returns></returns>
        public static VisibilityGraph AddVertices(VisibilityGraph visibilityGraph, List <gVertex> vertices, bool reducedGraph = true)
        {
            //TODO: Seems that original graph gets updated as well
            if (vertices == null)
            {
                throw new NullReferenceException("vertices");
            }

            VisibilityGraph newVisGraph    = (VisibilityGraph)visibilityGraph.Clone();
            List <gVertex>  singleVertices = new List <gVertex>();

            foreach (gVertex v in vertices)
            {
                if (newVisGraph.Contains(v))
                {
                    continue;
                }
                gEdge closestEdge = newVisGraph.baseGraph.edges.OrderBy(e => e.DistanceTo(v)).First();

                if (!gBase.Threshold(closestEdge.DistanceTo(v), 0))
                {
                    singleVertices.Add(v);
                }
                else if (v.OnEdge(closestEdge.StartVertex, closestEdge.EndVertex))
                {
                    v.polygonId = closestEdge.StartVertex.polygonId;
                    newVisGraph.baseGraph.polygons[v.polygonId] = newVisGraph.baseGraph.polygons[v.polygonId].AddVertex(v, closestEdge);
                    singleVertices.Add(v);
                }
            }

            newVisGraph.baseGraph.ResetEdgesFromPolygons();

            foreach (gVertex centre in singleVertices)
            {
                foreach (gVertex v in VisibleVertices(centre, newVisGraph.baseGraph, null, null, singleVertices, false, reducedGraph))
                {
                    newVisGraph.AddEdge(new gEdge(centre, v));
                }
            }

            return(newVisGraph);
        }
コード例 #10
0
        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);
            }
        }
コード例 #11
0
ファイル: Graph.cs プロジェクト: bulutkartal/Graphical
        /// <summary>
        /// Add edge to the analisys graph
        /// </summary>
        /// <param name="edge">New edge</param>
        public void AddEdge(gEdge edge)
        {
            List <gEdge> startEdgesList = new List <gEdge>();
            List <gEdge> endEdgesList   = new List <gEdge>();

            if (graph.TryGetValue(edge.StartVertex, out startEdgesList))
            {
                if (!startEdgesList.Contains(edge))
                {
                    startEdgesList.Add(edge);
                }
            }
            else
            {
                graph.Add(edge.StartVertex, new List <gEdge>()
                {
                    edge
                });
            }

            if (graph.TryGetValue(edge.EndVertex, out endEdgesList))
            {
                if (!endEdgesList.Contains(edge))
                {
                    endEdgesList.Add(edge);
                }
            }
            else
            {
                graph.Add(edge.EndVertex, new List <gEdge>()
                {
                    edge
                });
            }

            if (!edges.Contains(edge))
            {
                edges.Add(edge);
            }
        }
コード例 #12
0
ファイル: Curves.cs プロジェクト: alvpickmans/GraphicalDynamo
        internal static bool DoesIntersect(Line line1, Line line2)
        {
            gEdge edge1 = gEdge.ByStartVertexEndVertex(Points.ToVertex(line1.StartPoint), Points.ToVertex(line1.EndPoint));
            gEdge edge2 = gEdge.ByStartVertexEndVertex(Points.ToVertex(line2.StartPoint), Points.ToVertex(line2.EndPoint));

            if (edge1.Intersects(edge2))
            {
                if (edge2.StartVertex.OnEdge(edge1))
                {
                    return(false);
                }
                if (edge2.EndVertex.OnEdge(edge1))
                {
                    return(false);
                }
                return(true);
            }
            else
            {
                return(false);
            }
        }
コード例 #13
0
ファイル: Graph.cs プロジェクト: bulutkartal/Graphical
 /// <summary>
 /// Contains method for edges in graph
 /// </summary>
 /// <param name="edge"></param>
 /// <returns></returns>
 public bool Contains(gEdge edge)
 {
     return(edges.Contains(edge));
 }
コード例 #14
0
        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
        }
コード例 #15
0
ファイル: Graph.cs プロジェクト: bulutkartal/Graphical
        public Graph(List <gPolygon> gPolygonsSet)
        {
            edges   = new List <gEdge>();
            graphID = Guid.NewGuid();
            //Setting up Graph instance by adding vertices, edges and polygons
            foreach (gPolygon gPolygon in gPolygonsSet)
            {
                List <gVertex> vertices = gPolygon.vertices;

                // Clear pre-existing edges in the case this is an updating process.
                gPolygon.edges.Clear();

                //If there is only one polygon, treat it as boundary
                if (gPolygonsSet.Count() == 1)
                {
                    gPolygon.isBoundary = true;
                }

                //If first and last point of vertices list are the same, remove last.
                if (vertices.First().Equals(vertices.Last()) && vertices.Count() > 1)
                {
                    vertices = vertices.Take(vertices.Count() - 1).ToList();
                }

                //For each point, creates vertex and associated edge and adds them
                //to the polygons Dictionary
                int vertexCount = vertices.Count();

                // If valid polygon
                if (vertexCount >= 3)
                {
                    int newId = GetNextId();
                    for (var j = 0; j < vertexCount; j++)
                    {
                        int     next_index  = (j + 1) % vertexCount;
                        gVertex vertex      = vertices[j];
                        gVertex next_vertex = vertices[next_index];
                        gEdge   edge        = new gEdge(vertex, next_vertex);

                        //If is a valid polygon, add id to vertex and
                        //edge to vertices dictionary
                        if (vertexCount > 2)
                        {
                            vertex.polygonId      = newId;
                            next_vertex.polygonId = newId;
                            gPolygon gPol = new gPolygon();
                            if (polygons.TryGetValue(newId, out gPol))
                            {
                                gPol.edges.Add(edge);
                            }
                            else
                            {
                                gPolygon.edges.Add(edge);
                                gPolygon.id = newId;
                                polygons.Add(newId, gPolygon);
                            }
                        }
                        AddEdge(edge);
                    }
                }
            }
        }
コード例 #16
0
 /// <summary>
 /// SweepEvent default constructor
 /// </summary>
 /// <param name="vertex"></param>
 /// <param name="edge"></param>
 public SweepEvent(gVertex vertex, gEdge edge)
 {
     this.Vertex = vertex;
     this.Edge   = edge;
 }
コード例 #17
0
        /// <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 <gVertex> VisibleVertices(
            gVertex centre,
            Graph baseGraph,
            gVertex origin                = null,
            gVertex destination           = null,
            List <gVertex> singleVertices = null,
            bool halfScan      = true,
            bool reducedGraph  = true,
            bool maxVisibility = false)
        {
            #region Initialize variables and sort vertices
            List <gEdge>   edges    = baseGraph.edges;
            List <gVertex> vertices = baseGraph.vertices;


            if (origin != null)
            {
                vertices.Add(origin);
            }
            if (destination != null)
            {
                vertices.Add(destination);
            }
            if (singleVertices != null)
            {
                vertices.AddRange(singleVertices);
            }


            gVertex 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 = gVertex.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;
            gEdge          halfEdge  = gEdge.ByStartVertexEndVertex(centre, gVertex.ByCoordinates(xMax, centre.Y, centre.Z));
            foreach (gEdge e in edges)
            {
                if (e.Contains(centre))
                {
                    continue;
                }
                if (halfEdge.Intersects(e))
                {
                    if (e.StartVertex.OnEdge(halfEdge))
                    {
                        continue;
                    }
                    if (e.EndVertex.OnEdge(halfEdge))
                    {
                        continue;
                    }
                    EdgeKey k = new EdgeKey(halfEdge, e);
                    Core.List.AddItemSorted(openEdges, k);
                }
            }

            #endregion

            List <gVertex> visibleVertices = new List <gVertex>();
            gVertex        prev            = null;
            bool           prevVisible     = false;
            for (var i = 0; i < vertices.Count; i++)
            {
                gVertex 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 && gVertex.RadAngle(centre, vertex) > Math.PI)
                {
                    break;
                }
                //Removing clock wise edges incident on v
                if (openEdges.Count > 0 && baseGraph.graph.ContainsKey(vertex))
                {
                    foreach (gEdge edge in baseGraph.graph[vertex])
                    {
                        int orientation = gVertex.Orientation(centre, vertex, edge.GetVertexPair(vertex));

                        if (orientation == -1)
                        {
                            EdgeKey k     = new EdgeKey(centre, vertex, edge);
                            int     index = Core.List.Bisect(openEdges, 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;

                //No collinear vertices
                if (prev == null || gVertex.Orientation(centre, prev, vertex) != 0 || !prev.OnEdge(centre, vertex))
                {
                    if (openEdges.Count == 0)
                    {
                        isVisible = true;
                    }
                    else if (!EdgeIntersect(centre, vertex, openEdges[0].Edge))
                    {
                        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 => gVertex.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 => gVertex.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 (gEdge e in baseGraph.graph[vertex])
                    {
                        if (!e.Contains(centre) && gVertex.Orientation(centre, vertex, e.GetVertexPair(vertex)) == 1)
                        {
                            EdgeKey k = new EdgeKey(centre, vertex, e);
                            Core.List.AddItemSorted(openEdges, k);
                        }
                    }
                }

                if (isVisible && maxVisibility && vertex.polygonId >= 0)
                {
                    List <gVertex> vertexPairs       = baseGraph.GetAdjecentVertices(vertex);
                    int            firstOrientation  = gVertex.Orientation(centre, vertex, vertexPairs[0]);
                    int            secondOrientation = gVertex.Orientation(centre, vertex, vertexPairs[1]);

                    //if both edges lie on the same side of the centre-vertex edge or one of them is colinear
                    if (firstOrientation == secondOrientation || firstOrientation == 0 || secondOrientation == 0)
                    {
                        gVertex rayVertex        = vertex.Translate(gVector.ByTwoVertices(centre, vertex), maxDistance);
                        gEdge   rayEdge          = gEdge.ByStartVertexEndVertex(centre, rayVertex);
                        gVertex projectionVertex = null;
                        foreach (EdgeKey ek in openEdges)
                        {
                            gBase intersection = rayEdge.Intersection(ek.Edge);
                            if (intersection != null && intersection is gVertex && !(intersection as gVertex).Equals(vertex))
                            {
                                projectionVertex = intersection as gVertex;
                                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);
                            }
                        }
                    }
                }
            }

            return(visibleVertices);
        }