public static Polygon PolygonWithPolygon(Polygon polygon)
        {
            Polygon rootPolygon = null;

            // Compose with sub-olygons (if any).
            polygon.EnumeratePolygons((Polygon eachPolygon) =>
            {
                if (rootPolygon == null)
                {
                    rootPolygon = Polygon.PolygonWithPoints(eachPolygon.points);
                }
                else
                {
                    rootPolygon.AddPolygon(Polygon.PolygonWithPoints(eachPolygon.points));
                }
            });

            return(rootPolygon);
        }
        public static Polygon PolygonWithPointTransforms(Transform[] pointTransforms, Source.Polygon.Coordinates coordinates)
        {
            // Create points array.
            Vector2[] points = new Vector2[pointTransforms.Length];
            for (int index = 0; index < pointTransforms.Length; index++)
            {
                Transform eachPointTransform = pointTransforms[index];

                if (coordinates == Source.Polygon.Coordinates.World)
                {
                    points[index] = eachPointTransform.position.xy();
                }

                if (coordinates == Source.Polygon.Coordinates.Local)
                {
                    points[index] = eachPointTransform.localPosition.xy();
                }
            }

            return(Polygon.PolygonWithPoints(points));
        }
 public static Polygon PolygonWithPointList(List <Vector2> pointList)
 {
     return(Polygon.PolygonWithPoints(pointList.ToArray()));
 }
        public Polygon UnionPolygon()
        {
            // Calculate Polygon-Clipper scale.
            float maximum      = Mathf.Max(bounds.width, bounds.height);
            float maximumScale = (float)Int32.MaxValue / maximum;
            float scale        = Mathf.Min(clipperScale, maximumScale);

            // Convert to Clipper.
            Paths subjectPaths = new Paths();
            Paths clipPaths    = new Paths();

            {
                Path path = new Path();
                EnumeratePoints((Vector2 eachPoint) =>
                {
                    path.Add(new IntPoint(eachPoint.x * scale, eachPoint.y * scale));
                });
                subjectPaths.Add(path);
            }
            foreach (Polygon eachPolygon in polygons)
            {
                Path path = new Path();
                eachPolygon.EnumeratePoints((Vector2 eachPoint) =>
                {
                    path.Add(new IntPoint(eachPoint.x * scale, eachPoint.y * scale));
                });
                clipPaths.Add(path);
            }

            // Clipper union.
            Paths   unionPaths = new Paths();
            Clipper clipper    = new Clipper();

            clipper.AddPaths(subjectPaths, PolyType.ptSubject, true);
            clipper.AddPaths(clipPaths, PolyType.ptClip, true);
            clipper.Execute(ClipType.ctUnion, unionPaths);

            // Remove self intersections.
            Paths simplifiedUnionPaths = new Paths();

            simplifiedUnionPaths = Clipper.SimplifyPolygons(unionPaths);

            // Convert from Cipper.
            Polygon simplifiedUnionPolygon = null;

            for (int index = 0; index < simplifiedUnionPaths.Count; index++)
            {
                Path    eachSolutionPath    = simplifiedUnionPaths[index];
                Polygon eachSolutionPolygon = PolygonFromClipperPath(eachSolutionPath, scale);

                if (index == 0)
                {
                    simplifiedUnionPolygon = Polygon.PolygonWithPoints(eachSolutionPolygon.points);                     // Copy
                }
                else
                {
                    simplifiedUnionPolygon.AddPolygon(eachSolutionPolygon);
                }
            }

            // Back to Polygon.
            return(simplifiedUnionPolygon);
        }
        Polygon OffsetPolygon(float offset, bool simplify, bool rounded)
        {
            // Calculate Polygon-Clipper scale.
            float maximum      = Mathf.Max(bounds.width, bounds.height) + offset * 2.0f + offset;
            float maximumScale = (float)Int32.MaxValue / maximum;
            float scale        = Mathf.Min(clipperScale, maximumScale);


            // Convert to Clipper.
            Paths paths = new Paths();

            {
                Path path = new Path();
                EnumeratePoints((Vector2 eachPoint) =>
                {
                    path.Add(new IntPoint(eachPoint.x * scale, eachPoint.y * scale));
                });
                paths.Add(path);
            }
            foreach (Polygon eachPolygon in polygons)
            {
                Path path = new Path();
                eachPolygon.EnumeratePoints((Vector2 eachPoint) =>
                {
                    path.Add(new IntPoint(eachPoint.x * scale, eachPoint.y * scale));
                });
                paths.Add(path);
            }

            // Mode.
            JoinType joinType = (rounded) ? JoinType.jtRound : JoinType.jtMiter;

            // Clipper offset.
            Paths         offsetPaths   = new Paths();
            ClipperOffset clipperOffset = new ClipperOffset();

            if (rounded)
            {
                clipperOffset.ArcTolerance = 0.25 * clipperArcTolerance;
            }                                                                                     // "The default ArcTolerance is 0.25 units." from http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/ClipperOffset/Properties/ArcTolerance.htm
            clipperOffset.AddPaths(paths, joinType, EndType.etClosedPolygon);
            clipperOffset.Execute(ref offsetPaths, (double)offset * scale);

            // Remove self intersections (if requested).
            if (simplify)
            {
                offsetPaths = Clipper.SimplifyPolygons(offsetPaths);
            }

            // Convert from Clipper.
            Polygon offsetPolygon = null;

            for (int index = 0; index < offsetPaths.Count; index++)
            {
                Path    eachSolutionPath    = offsetPaths[index];
                Polygon eachSolutionPolygon = PolygonFromClipperPath(eachSolutionPath, scale);

                if (index == 0)
                {
                    offsetPolygon = Polygon.PolygonWithPoints(eachSolutionPolygon.points);                     // Copy
                }
                else
                {
                    offsetPolygon.AddPolygon(eachSolutionPolygon);
                }
            }

            // Back to Polygon.
            return(offsetPolygon);
        }