Beispiel #1
0
        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);
        }
Beispiel #2
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);
        }
Beispiel #3
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)));
        }
Beispiel #4
0
        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)
                }
            };
        }
Beispiel #5
0
        // 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));
        }