public void ContainsInsideTest()
 {
     Assert.IsTrue(m_arrow.ContainsInside(new Vector2(1.5f, 0)));
     Assert.IsFalse(m_arrow.ContainsInside(new Vector2(0, 0)));
     Assert.IsTrue(m_diamond.ContainsInside(new Vector2(0, 0)));
     Assert.IsFalse(m_diamond.ContainsInside(new Vector2(-999, 999)));
     Assert.IsTrue(m_containsPoly.ContainsInside(new Vector2(1, 3)));
     Assert.IsFalse(m_containsPoly.ContainsInside(new Vector2(3, 1)));
 }
        /// <inheritdoc />
        public bool VisibleToOtherVertex(
            Vector2 vertex1,
            Vector2 vertex2,
            Polygon2D polygon)
        {
            LineSegment seg1 = new LineSegment(vertex1, vertex2);

            foreach (LineSegment lineSegment in polygon.Segments)
            {
                // Check if any of the line segments intersect with the
                // line segments between the two vertices. If they so then
                // the two vertices cannot see each other. With the exception
                // that an intersection with an endpoint does not count as
                // blocking visibility
                Vector2?intersection = seg1.IntersectProper(lineSegment);

                if (intersection != null)
                {
                    // Check if the two lines are parallel. We allow two vertices
                    // to see each other if they they are along a straight line
                    if (!seg1.IsParallel(lineSegment))
                    {
                        return(false);
                    }
                }
            }

            // Non of the line segments of the polygon intersect with the
            // visibility line between the two points. Next we need to check if
            // the visibility line is inside of the polygon
            // We take the midpoint of the line. If this is inside the polygon
            // then the two points can see each other
            return(polygon.ContainsInside(seg1.Midpoint));
        }
        /// <summary>
        /// Dirty method O(n^2)
        /// </summary>
        /// <param name="a_poly1"></param>
        /// <param name="a_poly2"></param>
        /// <returns></returns>
        public static Polygon2D IntersectConvex(Polygon2D a_poly1, Polygon2D a_poly2)
        {
            if (!(a_poly1.IsConvex()))
            {
                throw new GeomException("Method not defined for nonconvex polygons" + a_poly1);
            }
            if (!(a_poly2.IsConvex()))
            {
                throw new GeomException("Method not defined for nonconvex polygons" + a_poly2);
            }

            // obtain vertices that lie inside both polygons
            var resultVertices = a_poly1.Vertices
                                 .Where(v => a_poly2.ContainsInside(v))
                                 .Concat(a_poly2.Vertices.Where(v => a_poly1.ContainsInside(v)))
                                 .ToList();

            // add intersections between two polygon segments
            resultVertices.AddRange(a_poly1.Segments.SelectMany(seg => seg.Intersect(a_poly2.Segments)));

            // remove any duplicates
            resultVertices = resultVertices.Distinct().ToList();

            // retrieve convex hull of relevant vertices
            if (resultVertices.Count() >= 3)
            {
                var poly = ConvexHull.ComputeConvexHull(resultVertices);
                Debug.Assert(poly.IsConvex());
                return(poly);
            }

            return(null);
        }
Exemple #4
0
        public static int TrianglePoints(List <Vector2> pts, int Anum, int Bnum, int Cnum)
        {
            int cnt         = 0;
            var triangleABC = new Polygon2D();

            triangleABC.AddVertex(pts[Anum]);
            triangleABC.AddVertex(pts[Bnum]);
            triangleABC.AddVertex(pts[Cnum]);

            for (int i = 0; i < pts.Count; i++)
            {
                if ((i == Bnum) || (i == Anum) || (i == Cnum))
                {
                    continue;
                }
                if (triangleABC.ContainsInside(pts[i]))
                {
                    cnt++;
                }
            }


            //Debug.Log(cnt);
            triangleABC.Clear();
            return(cnt);
        }
Exemple #5
0
        private int HullRate()
        {
            m_selected_Hull = ConvexHull.ComputeConvexHull(m_selected_points.Select(v => v.Pos));

            if (m_selected_Hull.VertexCount < 3)
            {
                return(0);
            }

            int tot = m_selected_Hull.VertexCount;

            foreach (var point in m_points)
            {
                if (m_selected_Hull.ContainsInside(point.Pos))
                {
                    tot++;
                }
            }
            m_selected_Hull.SetPointNumber(tot);

            //Draw new convex hull line segments.
            foreach (var segmesh in lineMeshes)
            {
                Destroy(segmesh);
            }
            lineMeshes.Clear();
            foreach (var seg in m_selected_Hull.Segments)
            {
                //Add a line renderer
                // instantiate new road mesh
                var roadmesh = Instantiate(m_userLineMeshPrefab, Vector3.forward, Quaternion.identity) as GameObject;
                roadmesh.transform.parent = this.transform;
                instantObjects.Add(roadmesh);
                lineMeshes.Add(roadmesh);

                //roadmesh.GetComponent<P1HullSegment>().Segment =seg;

                var roadmeshScript = roadmesh.GetComponent <ReshapingMesh>();
                roadmeshScript.CreateNewMesh(seg.Point1, seg.Point2);
            }

            //Update current area in information panel
            GameObject.Find("PointsNumber").GetComponent <Text>().text = m_selected_Hull.PointNumber.ToString();

            // 60%, 80%, 95% pass level
            for (int i = 0; i < m_rateList.Count; i++)
            {
                if (m_selected_Hull.PointNumber < (int)(m_rateList[i] * m_solutionHull.PointNumber))
                {
                    return(i);
                }
            }

            return(m_rateList.Count - 1);
        }
Exemple #6
0
        public static int PolygonPoints(List <Vector2> pts, Polygon2D plg)
        {
            int tot = 0;

            foreach (var p in pts)
            {
                if (plg.ContainsInside(p) || plg.OnBoundary(p))
                {
                    tot++;
                }
            }
            return(tot);
        }
Exemple #7
0
        /// <summary>
        /// check if intersect
        /// </summary>
        /// <param name="a_poly1"></param>
        /// <param name="a_poly2"></param>
        /// <returns></returns>

        public static bool ifIntersect(Polygon2D a_poly1, Polygon2D a_poly2)
        {
            if (!(a_poly1.IsConvex()))
            {
                throw new GeomException("Method not defined for nonconvex polygons" + a_poly1);
            }
            if (!(a_poly2.IsConvex()))
            {
                throw new GeomException("Method not defined for nonconvex polygons" + a_poly2);
            }

            // obtain vertices that lie inside both polygons
            var resultVertices = a_poly1.Vertices
                                 .Where(v => a_poly2.ContainsInside(v))
                                 .Concat(a_poly2.Vertices.Where(v => a_poly1.ContainsInside(v)))
                                 .ToList();

            Debug.Log("result Vertices in Intersector: " + resultVertices.Count);

            return(resultVertices.Count > 0);
        }
Exemple #8
0
            public WeilerAtherton(Polygon2D a_subject, Polygon2D a_clip)
            {
                // initialize variables
                Subject            = a_subject;
                Clip               = a_clip;
                SubjectList        = new LinkedList <WAPoint>();
                ClipList           = new LinkedList <WAPoint>();
                SubjectNode        = new Dictionary <WAPoint, LinkedListNode <WAPoint> >();
                ClipNode           = new Dictionary <WAPoint, LinkedListNode <WAPoint> >();
                EntryIntersections = new HashSet <WAPoint>();

                // store intersections for clipping line segment
                // saves recomputation of intersections and entry-exit categorization
                var intersectSegmentsClip = new Dictionary <LineSegment, List <WAPoint> >();

                foreach (var seg in a_clip.Segments)
                {
                    intersectSegmentsClip.Add(seg, new List <WAPoint>());
                }

                // find all intersections and create subject list
                foreach (var seg1 in a_subject.Segments)
                {
                    // retrieve intersection list
                    var vertices = new List <WAPoint>();

                    var point = new WAPoint(seg1.Point1, WAList.Vertex);
                    var node  = SubjectList.AddLast(point);
                    SubjectNode.Add(point, node);

                    foreach (var seg2 in a_clip.Segments)
                    {
                        var intersect = seg1.Intersect(seg2);
                        if (intersect.HasValue)
                        {
                            // store intersection point
                            point = new WAPoint(intersect.Value, WAList.Ignore);
                            vertices.Add(point);
                            intersectSegmentsClip[seg2].Add(point);
                        }
                    }

                    // sort intersections on distance to start vertex
                    vertices.Sort(new ClosestToPointComparer(seg1.Point1));

                    foreach (var vertex in vertices)
                    {
                        node = SubjectList.AddLast(vertex);
                        SubjectNode.Add(vertex, node);
                    }
                }


                // remove duplicates
                for (var node = SubjectList.First; node != null; node = node.Next)
                {
                    var next = node.Next ?? SubjectList.First;
                    while (node != next && MathUtil.EqualsEps(node.Value.Pos, next.Value.Pos))
                    {
                        if (node.Value.Type == WAList.Vertex)
                        {
                            node.Value.Type = WAList.Ignore;
                            SubjectList.Remove(node);
                            EntryIntersections.Remove(node.Value);
                            node = next;
                        }
                        else
                        {
                            next.Value.Type = WAList.Ignore;
                            SubjectList.Remove(next);
                            EntryIntersections.Remove(next.Value);
                        }
                        next = node.Next ?? SubjectList.First;
                    }
                }

                // set entry/exit types correctly
                for (var node = SubjectList.First; node != null; node = node.Next)
                {
                    var prev   = node.Previous ?? SubjectList.Last;
                    var vertex = node.Value;

                    var inside1 = Clip.ContainsInside(prev.Value.Pos);
                    var inside2 = Clip.ContainsInside(vertex.Pos);

                    if (!inside1 && inside2)
                    {
                        vertex.Type = WAList.Entry;
                    }
                    else if (inside1 && !inside2)
                    {
                        prev.Value.Type = WAList.Exit;
                        EntryIntersections.Remove(vertex);
                    }

                    if (vertex.Type == WAList.Entry)
                    {
                        EntryIntersections.Add(vertex);
                    }
                }

                // create clip list and intersections
                foreach (var seg in a_clip.Segments)
                {
                    var vertices = intersectSegmentsClip[seg];

                    // sort intersections on distance to start vertex
                    intersectSegmentsClip[seg].Sort(new ClosestToPointComparer(seg.Point1));

                    vertices.Insert(0, new WAPoint(seg.Point1, WAList.Vertex));

                    // loop over intersections
                    foreach (var vertex in vertices)
                    {
                        if (vertex.Type == WAList.Ignore)
                        {
                            continue;
                        }

                        // add intersection to clipping list
                        var node = ClipList.AddLast(vertex);
                        ClipNode.Add(vertex, node);
                    }
                }
            }
        /// <summary>
        /// Computes the visibility polygon from the given point
        /// inside of a simple polygon (given as n vertices in CCW order) in O(n) time.
        /// Based on: https://cs.uwaterloo.ca/research/tr/1985/CS-85-38.pdf
        /// </summary>
        /// <param name="polygon"></param>
        /// <param name="z"></param>
        /// <returns></returns>
        public static Polygon2D Vision(Polygon2D polygon, Vector2 z)
        {
            // check for invalid polygon
            if (polygon.VertexCount < 3)
            {
                return(null);
            }

            if (!(polygon.ContainsInside(z) || polygon.OnBoundary(z)))
            {
                throw new ArgumentException("Visibility point must be inside polygon");
            }

            // list v, satisfies assumptions made in paper (section 2, paragraph 1
            // and 2).
            double initAngle;

            var vs = Preprocess(polygon, z, out initAngle);

            var       s   = new Stack <VertDispl>();
            var       i   = 0;
            VertDispl w   = null;
            var       ccw = true;

            var v0 = vs.Get(0);

            s.Push(v0);

            Debug.Assert(vs.n > 1);

            NextCall m_nextCall;

            if (MathUtil.GEQEps(vs.Get(1).alpha, v0.alpha))
            {
                m_nextCall = Advance(ref vs, ref s, ref i, ref w, ref ccw);
            }
            else
            {
                m_nextCall = Scan(ref vs, ref s, ref i, ref w, ref ccw);  // CounterClockWise
            }
            while (m_nextCall != NextCall.STOP)
            {
                switch (m_nextCall)
                {
                case NextCall.ADVANCE:
                    m_nextCall = Advance(ref vs, ref s, ref i, ref w, ref ccw);
                    break;

                case NextCall.RETARD:
                    m_nextCall = Retard(ref vs, ref s, ref i, ref w, ref ccw);
                    break;

                case NextCall.SCAN:
                    m_nextCall = Scan(ref vs, ref s, ref i, ref w, ref ccw);
                    break;
                }
            }

            var sList = s.ToList();

            // error occurred due to robustness
            if (sList.Count == 0)
            {
                return(new Polygon2D());
            }

            Debug.Assert(MathUtil.EqualsEps(sList[s.Count - 1].p.Cartesian, v0.p.Cartesian));

            var poly = Postprocess(sList, vs, z, initAngle);

            return(poly);
        }
Exemple #10
0
            public WeilerAtherton(Polygon2D a_subject, Polygon2D a_clip)
            {
                // initialize variables
                Subject     = a_subject;
                Clip        = a_clip;
                SubjectList = new LinkedList <WAPoint>(Subject.Vertices.Select(v => new WAPoint(v, WAList.Vertex)));
                ClipList    = new LinkedList <WAPoint>(Clip.Vertices.Select(v => new WAPoint(v, WAList.Vertex)));
                SubjectNode = new Dictionary <WAPoint, LinkedListNode <WAPoint> >();
                ClipNode    = new Dictionary <WAPoint, LinkedListNode <WAPoint> >();
                Entry       = new HashSet <WAPoint>();
                Exit        = new HashSet <WAPoint>();

                // find all intersections and create subject and clip list
                for (var node1 = SubjectList.First; node1 != null; node1 = node1.Next)
                {
                    // calculate subject segment
                    var next1 = node1.Next ?? SubjectList.First;
                    var seg1  = new LineSegment(node1.Value.Pos, next1.Value.Pos);

                    // obtain intersection lists
                    var intersections  = new List <Vector2>();
                    var intersectNodes = new Dictionary <Vector2, LinkedListNode <WAPoint> >();
                    for (var node2 = ClipList.Last; node2 != null; node2 = node2.Previous)
                    {
                        var prev2 = node2.Previous ?? ClipList.Last;
                        var seg2  = new LineSegment(node2.Value.Pos, prev2.Value.Pos);

                        var intersect = seg1.Intersect(seg2);
                        if (intersect.HasValue && !intersectNodes.ContainsKey(intersect.Value))
                        {
                            // store intersection point
                            intersectNodes.Add(intersect.Value, node2);
                            intersections.Add(intersect.Value);
                        }
                    }

                    // sort intersections on distance to start vertex
                    intersections.Sort(new ClosestToPointComparer(seg1.Point1));

                    // insert intersections into subject/clip lists
                    foreach (var vertex in intersections)
                    {
                        var point = new WAPoint(vertex, WAList.Ignore);

                        var newNode1 = SubjectList.AddAfter(node1, point);
                        SubjectNode.Add(point, newNode1);

                        var newNode2 = ClipList.AddBefore(intersectNodes[vertex], point);
                        ClipNode.Add(point, newNode2);

                        // increment node1 since we added a vertex
                        node1 = newNode1;
                    }
                }

                // remove duplicates of subject
                for (var node = SubjectList.First; node != null;)
                {
                    var next = node.Next ?? SubjectList.First;
                    while (MathUtil.EqualsEps(node.Value.Pos, next.Value.Pos, MathUtil.EPS * 10))
                    {
                        if (next.Value.Type != WAList.Vertex)
                        {
                            if (ClipNode.ContainsKey(node.Value))
                            {
                                ClipList.Remove(ClipNode[node.Value]);
                            }
                            SubjectList.Remove(node);
                            node = next;
                        }
                        else
                        {
                            SubjectList.Remove(next);
                        }
                        if (node == null)
                        {
                            break;
                        }
                        next = node.Next ?? SubjectList.First;
                    }
                    if (node != null)
                    {
                        node = node.Next;
                    }
                }

                // remove duplicates of clip
                for (var node = ClipList.Last; node != null;)
                {
                    var prev = node.Previous ?? ClipList.Last;
                    while (MathUtil.EqualsEps(node.Value.Pos, prev.Value.Pos, MathUtil.EPS * 10))
                    {
                        if (prev.Value.Type != WAList.Vertex)
                        {
                            if (SubjectNode.ContainsKey(node.Value))
                            {
                                SubjectList.Remove(SubjectNode[node.Value]);
                            }
                            ClipList.Remove(node);
                            node = prev;
                        }
                        else
                        {
                            ClipList.Remove(prev);
                        }
                        if (node == null)
                        {
                            break;
                        }
                        prev = node.Previous ?? ClipList.Last;
                    }
                    if (node != null)
                    {
                        node = node.Previous;
                    }
                }

                // set entry/exit types correctly
                for (var node = SubjectList.First; node != null; node = node.Next)
                {
                    if (node.Value.Type == WAList.Vertex)
                    {
                        continue;
                    }

                    var prev = node.Previous ?? SubjectList.Last;
                    var next = node.Next ?? SubjectList.First;

                    var inside1 = Clip.ContainsInside(prev.Value.Pos) || Clip.OnBoundary(prev.Value.Pos);
                    var inside2 = Clip.ContainsInside(next.Value.Pos) || Clip.OnBoundary(next.Value.Pos);

                    if (!inside1 && inside2)
                    {
                        node.Value.Type = WAList.Entry;
                        Entry.Add(node.Value);
                    }
                    else if (inside1 && !inside2)
                    {
                        node.Value.Type = WAList.Exit;
                        Exit.Add(node.Value);
                    }
                }
            }