public Polygon RectangleInside() { var p1 = Vector2.zero; var p2 = Vector2.zero; var maxLength = float.MinValue; ForEachEdge((a, b, i) => { var len = (a - b).magnitude; if (len > maxLength) { p1 = a; p2 = b; maxLength = len; } }); var rotated = Rotate(GeometryHelpers.Angle(p1 - p2)); var minY = rotated.Vertices.Min(v => v.y); var greatestDistance = rotated.Vertices.Max(v => v.y - minY); var normal = GeometryHelpers.Rotate90(p2 - p1).normalized; var newHouse = new Polygon(p1, p2, p2 - GeometryHelpers.Scale(normal, greatestDistance), p1 - GeometryHelpers.Scale(normal, greatestDistance)).ZoomShrink(0.2f); newHouse = newHouse.Translate(newHouse.Center - Center); return(newHouse); }
public Polygon Peel(Vector2 v1, float amount) { var v2 = GetNextVertex(v1); var n = GeometryHelpers.Scale(GeometryHelpers.Normalize(GeometryHelpers.Rotate90(v2 - v1)), amount); return(Cut(v1 + n, v2 + n, 0).First()); }
public Vector2 GetCenter() { var sum = new Vector2(); Vertices.ForEach(v => sum += v); sum = GeometryHelpers.Scale(sum, 1f / Vertices.Count); return(sum); }
public Polygon ZoomShrink(float amount) { var newVertices = Vertices.Select(v => { var d = Center - v; return(v + GeometryHelpers.Scale(d, amount)); }).ToList(); return(new Polygon(newVertices)); }
public Vector2 Center() { var c = new Vector2(); foreach (var v in Vertices) { c = c + v.C; } return(GeometryHelpers.Scale(c, 1f / Vertices.Count)); }
public Polygon Shrink(IList <float> shrinkAmounts) { var newPoly = new Polygon(this); ForEachEdge((p1, p2, index) => { var amount = shrinkAmounts[index]; if (amount > 0) { var n = GeometryHelpers.Scale(GeometryHelpers.Normalize(GeometryHelpers.Rotate90(p2 - p1)), amount); newPoly = newPoly.Cut(p1 + n, p2 + n, 0).First(); } }); return(newPoly); }
public IEnumerable <Polygon> Cut(Vector2 p1, Vector2 p2, float gap) { var x1 = p1.x; var y1 = p1.y; var dx1 = p2.x - x1; var dy1 = p2.y - y1; var len = Vertices.Count; var edge1 = 0; var ratio1 = 0.0f; var edge2 = 0; var ratio2 = 0.0f; var count = 0; for (var i = 0; i < len; i++) { var v0 = Vertices[i]; var v1 = Vertices[(i + 1) % len]; var x2 = v0.x; var y2 = v0.y; var dx2 = v1.x - x2; var dy2 = v1.y - y2; var t = GeometryHelpers.IntersectLines(x1, y1, dx1, dy1, x2, y2, dx2, dy2); if (t.y >= 0 && t.y <= 1) { switch (count) { case 0: edge1 = i; ratio1 = t.x; break; case 1: edge2 = i; ratio2 = t.x; break; } count++; } } if (count == 2) { var point1 = p1 + GeometryHelpers.Scale(p2 - p1, ratio1); var point2 = p1 + GeometryHelpers.Scale(p2 - p1, ratio2); var half1 = new Polygon(Vertices.GetRange(edge1 + 1, edge2 - edge1)); half1.Vertices.Insert(0, point1); half1.Vertices.Add(point2); var half2 = new Polygon(Vertices.GetRange(edge2 + 1, Vertices.Count - edge2 - 1).Concat(Vertices.GetRange(0, edge1 + 1))); half2.Vertices.Insert(0, point2); half2.Vertices.Add(point1); if (gap > 0) { half1 = half1.Peel(point2, gap / 2); half2 = half2.Peel(point1, gap / 2); } var v = VectorI(edge1); return(GeometryHelpers.CrossProduct(dx1, dy1, v.x, v.y) > 0 ? new [] { half1, half2 } : new [] { half2, half1 }); } return(new [] { new Polygon(this) }); }
public Polygon Buffer(IList <float> shrinkAmounts) { var newPoly = new Polygon(); ForEachEdge((p1, p2, index) => { var amount = shrinkAmounts[index]; if (amount <= 0.01) { newPoly.Vertices.Add(p1); newPoly.Vertices.Add(p2); } else { var n = GeometryHelpers.Scale(GeometryHelpers.Normalize(GeometryHelpers.Rotate90(p2 - p1)), amount); newPoly.Vertices.Add(p1 + n); newPoly.Vertices.Add(p2 + n); } }); bool wasCut; var lastEdge = 0; do { wasCut = false; var n = newPoly.Vertices.Count; for (var i = lastEdge; i < n - 2; i++) { lastEdge = i; var p11 = newPoly.Vertices[i]; var p12 = newPoly.Vertices[i + 1]; var x1 = p11.x; var y1 = p11.y; var dx1 = p12.x - x1; var dy1 = p12.y - y1; var maxJ = i > 0 ? n : n - 1; for (var j = i + 2; j < maxJ; j++) { var p21 = newPoly.Vertices[j]; var p22 = j < n - 1 ? newPoly.Vertices[j + 1] : newPoly.Vertices[0]; var x2 = p21.x; var y2 = p21.y; var dx2 = p22.x - x2; var dy2 = p22.y - y2; var intersect = GeometryHelpers.IntersectLines(x1, y1, dx1, dy1, x2, y2, dx2, dy2); if (intersect.x > Delta && intersect.x < (1 - Delta) && intersect.y > Delta && intersect.y < (1 - Delta)) { var pn = new Vector2(x1 + dx1 * intersect.x, y1 + dy1 * intersect.x); newPoly.Vertices.Insert(j + 1, pn); newPoly.Vertices.Insert(i + 1, pn); wasCut = true; break; } } } } while (wasCut); var regular = Enumerable.Range(0, newPoly.Vertices.Count).ToList(); Polygon bestPart = null; var bestPartSq = float.MinValue; while (regular.Count > 0) { var indices = new List <int> (); var start = regular[0]; var i = start; do { indices.Add(i); regular.Remove(i); var next = (i + 1) % newPoly.Vertices.Count; var v = newPoly.Vertices[next]; var next1 = newPoly.Vertices.IndexOf(v); if (next1 == next) { next1 = newPoly.Vertices.LastIndexOf(v); } i = next1 == -1 ? next : next1; } while (i != start && indices.Count < 1000); if (indices.Count >= 999) { indices = indices.Take(4).ToList(); } var poly = new Polygon(indices.Select(v => newPoly.Vertices[v])); var s = poly.Area(); if (s > bestPartSq) { bestPart = poly; bestPartSq = s; } } return(bestPart); }