public bool isConvexVertex(Point v1) { var v0 = prev(v1).vec; var v2 = next(v1).vec; return(GeomUtils.cross(v1.x - v0.x, v1.y - v0.y, v2.x - v1.x, v2.y - v1.y) > 0); }
public bool isConvexVertexi(int i) { var len = this.Count; var v0 = this[(i + len - 1) % len].vec; var v1 = this[i].vec; var v2 = this[(i + 1) % len].vec; return(GeomUtils.cross(v1.x - v0.x, v1.y - v0.y, v2.x - v1.x, v2.y - v1.y) > 0); }
public Point _centroid() { var x = 0.0; var y = 0.0; var a = 0.0; forEdge((Point v0, Point v1) => { var f = GeomUtils.cross(v0.x, v0.y, v1.x, v1.y); a += f; x += (v0.x + v1.x) * f; y += (v0.y + v1.y) * f; }); var s6 = 1 / (3 * a); return(new Point((float)(s6 * x), (float)(s6 * y))); }
public List <Polygon> cut(Point p1, Point p2, float gap = 0) { var x1 = p1.x; var y1 = p1.y; var dx1 = p2.x - x1; var dy1 = p2.y - y1; var len = this.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 = this[i]; var v1 = this[(i + 1) % len]; var x2 = v0.x; var y2 = v0.y; var dx2 = v1.x - x2; var dy2 = v1.y - y2; var t = GeomUtils.intersectLines(x1, y1, dx1, dy1, x2, y2, dx2, dy2); if (t != null && 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 = new Point(p1.vec + ((p2.vec - p1.vec) * (ratio1))); var point2 = new Point(p1.vec + ((p2.vec - p1.vec) * (ratio2))); var half1 = new Polygon(this.Skip(edge1 + 1).Take((edge2 + 1) - (edge1 + 1)).ToList()); half1.Insert(0, point1); half1.Add(point2); var half2 = new Polygon(this.Skip(edge2 + 1).Concat(this.Take(edge1 + 1)).ToList()); half2.Insert(0, point2); half2.Add(point1); if (gap > 0) { half1 = half1.peel(point2, gap / 2); half2 = half2.peel(point1, gap / 2); } var v = vectori(edge1); return(GeomUtils.cross(dx1, dy1, v.x, v.y) > 0 ? new List <Polygon> { half1, half2 } : new List <Polygon> { half2, half1 }); } else { return new List <Polygon> { new Polygon(this) } }; }
// This insets all edges by distances defined in an array. // It's kind of reliable for both convex and concave vertices, but only // if all distances are equal. Otherwise weird "steps" are created. // It does change the number of vertices. public Polygon buffer(List <float> d) { // Creating a polygon (probably invalid) with offset edges var q = new Polygon(); var k = 0; forEdge((Point v0, Point v1) => { var dd = d[k++]; if (dd == 0) { q.Add(v0); q.Add(v1); } else { // here we may want to do something fancier for nicer joints var v = v1.vec - v0.vec; var n = (Vector2)(Quaternion.Euler(0, 0, 90) * v.normalized * (dd)); q.Add(new Point(v0.vec + n)); q.Add(new Point(v1.vec + n)); } }); // Creating a valid polygon by dealing with self-intersection: // we need to find intersections of every edge with every other edge // and add intersection point (twice - for one edge and for the other) bool wasCut; var lastEdge = 0; do { wasCut = false; var n = q.Count; for (var ii = lastEdge; ii < n - 2; ii++) { lastEdge = ii; var p11 = q[ii]; var p12 = q[ii + 1]; var x1 = p11.x; var y1 = p11.y; var dx1 = p12.x - x1; var dy1 = p12.y - y1; for (var j = ii + 2; j < (ii > 0 ? n : n - 1); j++) { var p21 = q[j]; var p22 = j < n - 1 ? q[j + 1] : q[0]; var x2 = p21.x; var y2 = p21.y; var dx2 = p22.x - x2; var dy2 = p22.y - y2; var int1 = GeomUtils.intersectLines(x1, y1, dx1, dy1, x2, y2, dx2, dy2); if (int1 != null && int1?.x > DELTA && int1?.x < 1 - DELTA && int1?.y > DELTA && int1?.y < 1 - DELTA) { var pn = new Point(x1 + dx1 * int1.x, y1 + dy1 * int1.x); q.Insert(j + 1, pn); q.Insert(ii + 1, pn); wasCut = true; break; } } if (wasCut) { break; } } } while (wasCut); // Checking every part of the polygon to pick the biggest var regular = new List <int>(); for (var i = 0; i < q.Count; i++) { regular.Add(i); } var bestPart = new List <Point>(); var bestPartSq = Mathf.NegativeInfinity; 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) % q.Count; var v = q[next]; var next1 = q.IndexOf(v); if (next1 == next) { next1 = q.LastIndexOf(v); } i = (next1 == -1 ? next : next1); } while (i != start); var p = new Polygon(indices.Select(n => q[n]).ToList()); var s = p.square; if (s > bestPartSq) { bestPart = p; bestPartSq = s; } } return(new Polygon(bestPart)); }