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); }
/// <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); }
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); }
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)); }
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); }