public void RemoveHolesTest()
        {
            var poly = new Polygon2DWithHoles(m_squareWithHole.Outside, m_squareWithHole.Holes);

            poly.RemoveHoles();
            Assert.AreEqual(0, poly.Holes.Count);
        }
        public Polygon2DWithHolesTest()
        {
            m_diamondVertices = new List <Vector2>()
            {
                new Vector2(0, 1),
                new Vector2(1, 0),
                new Vector2(0, -1),
                new Vector2(-1, 0),
            };
            m_largeSquareVertices = new List <Vector2>()
            {
                new Vector2(2, 2),
                new Vector2(2, -2),
                new Vector2(-2, -2),
                new Vector2(-2, 2)
            };

            m_diamond     = new Polygon2D(m_diamondVertices);
            m_largeSquare = new Polygon2D(m_largeSquareVertices);

            //4x4 square with 1x1 diamond hole
            m_squareWithHole = new Polygon2DWithHoles(m_largeSquare,
                                                      new List <Polygon2D>()
            {
                m_diamond
            });
        }
        public void AddHoleTest()
        {
            var poly = new Polygon2DWithHoles();

            poly.AddHole(m_diamond);
            Assert.AreEqual(1, m_squareWithHole.Holes.Count);
        }
示例#4
0
    /// <summary>
    /// Computes a list of gridpoints indside the given polygon defined by outerpoints and holes.
    /// </summary>
    /// <param name="rect"></param>
    /// <param name="outerPoints"></param>
    /// <param name="holes"></param>
    /// <param name="n"></param>
    /// <returns></returns>
    private List <Vector2> ComputeGridPoints(Rect rect, List <Vector2> outerPoints, List <List <Vector2> > holes, int n)
    {
        var gridPoints = new List <Vector2>();

        Debug.Log(rect.xMin);
        Debug.Log(rect.xMax);
        Debug.Log(rect.yMin);
        Debug.Log(rect.yMax);
        Debug.Log(rect.width);
        Debug.Log(rect.height);

        for (float x = rect.xMin; x < rect.xMax; x += rect.width / (float)n)
        {
            for (float y = rect.yMin; y < rect.yMax; y += rect.height / (float)n)
            {
                gridPoints.Add(new Vector2(x, y));
            }
        }

        gridPoints = Normalize(rect, agSIZE, gridPoints);

        var tempPoly = new Polygon2DWithHoles(new Polygon2D(outerPoints), holes.Select(h => new Polygon2D(h)));

        for (int i = gridPoints.Count - 1; i >= 0; i--)
        {
            var point = gridPoints[i];
            if (!tempPoly.ContainsInside(point))
            {
                gridPoints.Remove(point);
            }
        }

        return(gridPoints);
    }
        public void IsConvexTest()
        {
            Assert.IsFalse(m_squareWithHole.IsConvex());
            var poly = new Polygon2DWithHoles(m_squareWithHole.Outside, m_squareWithHole.Holes);

            poly.RemoveHoles();
            Assert.IsTrue(poly.IsConvex());
        }
        public void ClockwiseTest()
        {
            Assert.IsTrue(m_squareWithHole.IsClockwise());
            var poly = new Polygon2DWithHoles(m_squareWithHole.Outside, m_squareWithHole.Holes);

            poly.Reverse();
            Assert.IsFalse(poly.IsClockwise());
        }
        public void RemoveLastTest()
        {
            var poly = new Polygon2DWithHoles(m_squareWithHole.Outside, m_squareWithHole.Holes);

            poly.RemoveLast();
            Assert.AreEqual(7, poly.VertexCount);
            Assert.IsFalse(poly.ContainsVertex(m_largeSquareVertices[3]));
        }
        public void AddVertexAfterTest()
        {
            var poly = new Polygon2DWithHoles(m_squareWithHole.Outside, m_squareWithHole.Holes);
            var pos  = new Vector2(0, 1);

            poly.AddVertexAfter(pos, m_largeSquareVertices[0]);
            Assert.AreEqual(5, poly.OuterVertices.Count);
            Assert.AreEqual(pos, poly.Outside.Vertices.ToList()[1]);
        }
        public void ClearTest()
        {
            var poly = new Polygon2DWithHoles(m_squareWithHole.Outside, m_squareWithHole.Holes);

            poly.Clear();
            Assert.AreEqual(0, poly.VertexCount);
            Assert.IsEmpty(poly.Vertices);
            Assert.IsEmpty(poly.Holes);
        }
        public void AddVertexFirstTest()
        {
            var poly = new Polygon2DWithHoles(m_squareWithHole.Outside);
            var pos  = new Vector2(-5, 5);

            poly.AddVertexFirst(pos);
            Assert.AreEqual(5, poly.VertexCount);
            var vertices = (System.Collections.ICollection)poly.Vertices;

            Assert.Contains(pos, vertices);
        }
示例#11
0
        public void InitLevel()
        {
            // clear old level
            m_solution.Clear();
            m_selectedLighthouse = null;
            m_advanceButton.Disable();

            // create new level
            var level = m_levels[m_levelCounter];

            LevelPolygon             = level.Polygon;
            m_maxNumberOfLighthouses = level.MaxNumberOfLighthouses;
            m_levelMesh.Polygon      = LevelPolygon;

            // update text box
            UpdateLighthouseText();
        }
        /// <summary>
        /// Given a polygon 2D with holes where none of the holes are overlapping, will create a contour polygon
        /// from it conforming to the requirements of the ContourPolygon.
        /// </summary>
        /// <param name="pol"></param>
        /// <returns></returns>
        public static ContourPolygon ToContourPolygon(this Polygon2DWithHoles pol)
        {
            var outside = new Contour((pol.IsClockwise()
                    ? pol.Vertices.Reverse()
                    : pol.Vertices).Select(v => new Vector2D(v)),
                                      Enumerable.Range(1,
                                                       pol.Holes.Count)); // The Polygon2D can be in cw order, while we need it in ccw order
            var result = new ContourPolygon();

            result.Add(outside);
            foreach (var hole in pol.Holes)
            {
                result.Add(new Contour((pol.IsClockwise()
                        ? pol.Vertices
                        : pol.Vertices.Reverse()).Select(v => new Vector2D(v)), Enumerable.Range(1, pol.Holes.Count),
                                       false)); // The Polygon2D can be in ccw order, while we need it in cc order for holes;
            }

            return(result);
        }
示例#13
0
        public static Polygon2D Vision(Polygon2DWithHoles polygon, Vector2 x)
        {
            if (!(polygon.ContainsInside(x) || polygon.OnBoundary(x)))
            {
                throw new ArgumentException(x + " is not inside polygon: " + polygon);
            }

            float initAngle;
            var   events = Preprocess(polygon, x, out initAngle);

            var status     = new AATree <StatusItem>();
            var visibility = new List <Vector2>();

            // create ray in positive x direction
            var ray = new Ray2D(Vector2.zero, new Vector2(1f, 0f));

            VisibilityEvent xEvent = null;

            // initialize the status
            foreach (var v in events)
            {
                if (MathUtil.EqualsEps(v.vertex, Vector2.zero))
                {
                    xEvent = v;
                    continue;
                }

                var seg = v.item1.seg;
                if (!seg.IsEndpoint(x))
                {
                    var intersect = seg.Intersect(ray);
                    if (intersect.HasValue && intersect.Value.x > 0 && (seg.Point1.y >= 0 != seg.Point2.y >= 0) &&
                        !MathUtil.EqualsEps(intersect.Value, Vector2.zero))
                    {
                        status.Insert(v.item1);
                    }
                }
            }

            if (xEvent != null)
            {
                if (!xEvent.isHole)
                {
                    status.Insert(xEvent.item1);
                }
                else
                {
                    status.Delete(xEvent.item1);
                }

                if (!xEvent.isHole)
                {
                    status.Delete(xEvent.item2);
                }
                else
                {
                    status.Insert(xEvent.item2);
                }

                if (!xEvent.isHole)
                {
                    visibility.Add(xEvent.item2.seg.Point2);
                    visibility.Add(Vector2.zero);
                    visibility.Add(xEvent.item1.seg.Point1);
                }
                else
                {
                    visibility.Add(xEvent.item2.seg.Point1);
                    visibility.Add(Vector2.zero);
                    visibility.Add(xEvent.item1.seg.Point2);
                }
            }

            // handle events
            StatusItem top        = null;
            var        insertions = new HashSet <StatusItem>();

            if (status.Count > 0)
            {
                status.FindMin(out top);
            }
            for (var i = 0; i < events.Count; i++)
            {
                var v = events[i];

                if (MathUtil.EqualsEps(v.vertex, Vector2.zero))
                {
                    continue;
                }

                ray = new Ray2D(Vector2.zero, v.vertex);

                // first handle deletions

                // handle first segment
                if (status.Contains(v.item1))
                {
                    status.Delete(v.item1);
                }
                else if (insertions.Contains(v.item1))
                {
                    insertions.Remove(v.item1);
                }
                else
                {
                    insertions.Add(v.item1);
                }

                // handle second segment
                if (status.Contains(v.item2))
                {
                    status.Delete(v.item2);
                }
                else if (insertions.Contains(v.item2))
                {
                    insertions.Remove(v.item2);
                }
                else
                {
                    insertions.Add(v.item2);
                }

                // skip if next event colinear with current
                if (i < events.Count - 1 && Line.Colinear(Vector2.zero, v.vertex, events[i + 1].vertex))
                {
                    // skip until all colinear events are handled
                    continue;
                }

                // handle insertions (after potential skip for colinear events
                foreach (var item in insertions)
                {
                    status.Insert(item);
                }
                insertions.Clear();

                StatusItem newTop;
                status.FindMin(out newTop);

                // do stuff if current top different from previous
                if (top != newTop)
                {
                    // add intersections with previous top segment
                    if (top != null)
                    {
                        HandleTopSegment(ref visibility, top.seg, ray);
                    }

                    // add intersections with new top segment
                    if (newTop != null)
                    {
                        HandleTopSegment(ref visibility, newTop.seg, ray);
                    }

                    top = newTop;
                }
            }

            return(Postprocess(visibility, x, initAngle));
        }
示例#14
0
        private static List <VisibilityEvent> Preprocess(Polygon2DWithHoles poly, Vector2 x, out float initAngle)
        {
            // copy polygon
            var polygon = new Polygon2DWithHoles(poly.Outside, poly.Holes);

            // shift such that x is at origin
            polygon.ShiftToOrigin(x);
            x = Vector2.zero;

            var  angle        = 0f;
            bool rot          = false;
            var  segments     = polygon.Outside.Segments.ToList();
            var  holeSegments = polygon.Holes.Select(h => h.Segments.ToList()).ToList();

            // insert x if on segment
            var xSeg = segments.FirstOrDefault(seg => seg.IsOnSegment(x) && !seg.IsEndpoint(x));

            if (xSeg != null)
            {
                var i = segments.IndexOf(xSeg);
                segments.Insert(i + 1, new LineSegment(x, xSeg.Point2));
                segments[i] = new LineSegment(xSeg.Point1, x);
                xSeg        = segments[i];
            }
            else
            {
                for (var i = 0; i < holeSegments.Count; i++)
                {
                    var hsegs = holeSegments[i];
                    xSeg = hsegs.FirstOrDefault(seg => seg.IsOnSegment(x) && !seg.IsEndpoint(x));
                    if (xSeg != null)
                    {
                        var j = hsegs.IndexOf(xSeg);
                        hsegs.Insert(j + 1, new LineSegment(x, xSeg.Point2));
                        xSeg = new LineSegment(xSeg.Point1, x);
                        break;
                    }
                }
            }

            // find if rotation is needed
            xSeg = segments.FirstOrDefault(seg => MathUtil.EqualsEps(seg.Point2, x));
            if (xSeg != null)
            {
                angle = (float)new PolarPoint2D(xSeg.Point1).Theta;
                rot   = true;
            }
            else
            {
                for (var i = 0; i < holeSegments.Count; i++)
                {
                    var hsegs = holeSegments[i];
                    xSeg = hsegs.FirstOrDefault(seg => MathUtil.EqualsEps(seg.Point1, x));
                    if (xSeg != null)
                    {
                        angle = (float)new PolarPoint2D(xSeg.Point2).Theta;
                        rot   = true;
                        break;
                    }
                }
            }

            if (rot)
            {
                segments = segments.Select(seg => new LineSegment(MathUtil.Rotate(seg.Point1, -angle),
                                                                  MathUtil.Rotate(seg.Point2, -angle))).ToList();

                for (var i = 0; i < holeSegments.Count; i++)
                {
                    holeSegments[i] = holeSegments[i].Select(seg => new LineSegment(MathUtil.Rotate(seg.Point1, -angle),
                                                                                    MathUtil.Rotate(seg.Point2, -angle))).ToList();
                }
            }

            // initialize events
            // one for each Vector2 in the Polygon2D (+ holes)
            var events = CreateEvents(segments, false);

            foreach (var hsegs in holeSegments)
            {
                events.AddRange(CreateEvents(hsegs, true));
            }

            events.Sort();

            initAngle = angle;
            return(events);
        }