/// <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 ContainsInsideTest() { Assert.IsTrue(m_squareWithHole.ContainsInside(new Vector2(1.5f, 0))); Assert.IsFalse(m_squareWithHole.ContainsInside(new Vector2(0, 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)); }