Exemplo n.º 1
0
        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) });
        }
Exemplo n.º 2
0
        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);
        }