예제 #1
0
        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);
        }
예제 #2
0
        public float AngleAtVertex(int index)
        {
            var pt   = Vertices[index];
            var prev = GetPreviousVertex(index);
            var next = GetNextVertex(index);

            return(GeometryHelpers.AngleThreePoints(prev, pt, next));
        }
예제 #3
0
        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());
        }
예제 #4
0
        public Vector2 GetCenter()
        {
            var sum = new Vector2();

            Vertices.ForEach(v => sum += v);

            sum = GeometryHelpers.Scale(sum, 1f / Vertices.Count);
            return(sum);
        }
예제 #5
0
        public static float AngleThreePoints(Vector2 a, Vector2 b, Vector2 c)
        {
            var v1    = b - a;
            var v2    = c - b;
            var cross = GeometryHelpers.Cross(v1, v2);
            var dot   = Vector2.Dot(v1, v2);

            return((float)Math.Atan2(cross, dot));
        }
예제 #6
0
        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));
        }
예제 #7
0
        public Vector2 Center()
        {
            var c = new Vector2();

            foreach (var v in Vertices)
            {
                c = c + v.C;
            }
            return(GeometryHelpers.Scale(c, 1f / Vertices.Count));
        }
예제 #8
0
        public IEnumerable <Polygon> Bisect(Vector2 vertex, float ratio = 0.5f, float angle = 0.0f, float gap = 0.0f)
        {
            var next = GetNextVertex(vertex);

            var p1 = GeometryHelpers.Interpolate(vertex, next, ratio);
            var d  = next - vertex;

            var cosB = Math.Cos(angle);
            var sinB = Math.Sin(angle);
            var vx   = d.x * cosB - d.y * sinB;
            var vy   = d.y * cosB + d.x * sinB;
            var p2   = new Vector2((float)(p1.x - vy), (float)(p1.y + vx));

            return(Cut(p1, p2, gap));
        }
예제 #9
0
        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);
        }
예제 #10
0
        public Polygon SmoothVertices(float amount = 1f)
        {
            var len = Vertices.Count;
            var v1  = Vertices[len - 1];
            var v2  = Vertices[0];

            var newVertices = new List <Vector2> ();

            for (var v = 0; v < Vertices.Count; v++)
            {
                var v0 = v1;
                v1 = v2;
                v2 = Vertices[(v + 1) % len];
                newVertices.Add(GeometryHelpers.SmoothVertex(v1, v0, v2));
            }

            return(new Polygon(newVertices));
        }
예제 #11
0
 public static float Cross(Vector2 a, Vector2 b)
 {
     return(GeometryHelpers.CrossProduct(a.x, a.y, b.x, b.y));
 }
예제 #12
0
        public Polygon SortPointsClockwise()
        {
            var sortedVertices = Vertices.OrderBy(v => GeometryHelpers.Angle(v - Center)).ToList();

            return(new Polygon(sortedVertices));
        }
예제 #13
0
 public Polygon Rotate(float angle)
 {
     return(new Polygon(Vertices.Select(vertex => GeometryHelpers.RotateAoundPoint(vertex, Center, angle))));
 }
예제 #14
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) });
        }
예제 #15
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);
        }