Inheritance: ClipperBase
Exemplo n.º 1
0
        /// <summary>
        ///  Conduct a clip operation on this profile.
        /// </summary>
        internal void Clip(IEnumerable <Profile> additionalHoles = null, double tolerance = Vector3.EPSILON)
        {
            var clipper = new ClipperLib.Clipper();

            clipper.AddPath(this.Perimeter.ToClipperPath(tolerance), ClipperLib.PolyType.ptSubject, true);
            if (this.Voids != null)
            {
                clipper.AddPaths(this.Voids.Select(p => p.ToClipperPath(tolerance)).ToList(), ClipperLib.PolyType.ptClip, true);
            }
            if (additionalHoles != null)
            {
                clipper.AddPaths(additionalHoles.Select(h => h.Perimeter.ToClipperPath(tolerance)).ToList(), ClipperLib.PolyType.ptClip, true);
            }
            var solution = new List <List <ClipperLib.IntPoint> >();
            var result   = clipper.Execute(ClipperLib.ClipType.ctDifference, solution, ClipperLib.PolyFillType.pftEvenOdd);

            // Completely disjoint polygons like a circular pipe
            // profile will result in an empty solution.
            if (solution.Count > 0)
            {
                var polys = solution.Select(s => s.ToPolygon(tolerance)).ToArray();
                this.Perimeter = polys[0];
                this.Voids     = polys.Skip(1).ToArray();
            }
        }
Exemplo n.º 2
0
    public static XYPolygon GetIntersection(XYPolygon pol1, XYPolygon pol2)
    {



      List<List<IntPoint>> subj = new List<List<IntPoint>>();
  subj.Add(new List<IntPoint>(pol1.Points.Count));
      foreach(var p in pol1.Points)
        subj[0].Add(new IntPoint(p.X, p.Y));


      List<List<IntPoint>> clip = new List<List<IntPoint>>();
      clip.Add(new List<IntPoint>(pol2.Points.Count));
  foreach (var p in pol2.Points)
    clip[0].Add(new IntPoint(p.X, p.Y));


  List<List<IntPoint>> solution = new List<List<IntPoint>>();

	Clipper c = new Clipper();
	c.AddPaths(subj, PolyType.ptSubject, true);
	c.AddPaths(clip, PolyType.ptClip, true);
	c.Execute(ClipType.ctIntersection, solution, 
	  PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

  XYPolygon ToReturn = new XYPolygon();
  if (solution.Count > 0) 
  foreach (var p in solution[0])
    ToReturn.Points.Add(new XYPoint(p.X,p.Y));

          return ToReturn;
    }
Exemplo n.º 3
0
        private double ClippedArea()
        {
            if (this.Voids == null || this.Voids.Count == 0)
            {
                return(this.Perimeter.Area());
            }

            var clipper = new ClipperLib.Clipper();
            var normal  = Perimeter.Normal();

            if (normal.IsAlmostEqualTo(Vector3.ZAxis))
            {
                clipper.AddPath(Perimeter.ToClipperPath(), ClipperLib.PolyType.ptSubject, true);
                clipper.AddPaths(this.Voids.Select(p => p.ToClipperPath()).ToList(), ClipperLib.PolyType.ptClip, true);
            }
            else
            {
                var transform = new Transform(Perimeter.Start, normal);
                transform.Invert();
                var perimeter = Perimeter.TransformedPolygon(transform);
                clipper.AddPath(perimeter.ToClipperPath(), ClipperLib.PolyType.ptSubject, true);
                clipper.AddPaths(this.Voids.Select(p => p.TransformedPolygon(transform).ToClipperPath()).ToList(), ClipperLib.PolyType.ptClip, true);
            }

            var solution = new List <List <ClipperLib.IntPoint> >();

            clipper.Execute(ClipperLib.ClipType.ctDifference, solution, ClipperLib.PolyFillType.pftEvenOdd);
            return(solution.Sum(s => ClipperLib.Clipper.Area(s)) / Math.Pow(1.0 / Vector3.EPSILON, 2));
        }
    //Apply a polygon clipper operation on subject vertices using cut vertices
    public static List<Vector2[]> ClipPoly(Vector2[] subject, Vector2[] cut, ClipType operation)
    {
        List<Vector2[]> cutPolygons = new List<Vector2[]>();

        Paths subj = new Paths(1);
        subj.Add(Vector2ToIntList(subject));

        Paths clip = new Paths(1);
        clip.Add(Vector2ToIntList(cut));

        Paths solution = new Paths();

        Clipper c = new Clipper();
        c.AddPaths(subj, PolyType.ptSubject, true);
        c.AddPaths(clip, PolyType.ptClip, true);

        c.Execute(operation,solution,
              PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

        /*
        for(int i = 0; i<solution.Count; i++){
        if( Mathf.Abs((float)Clipper.Area(solution[i])) > ignoreArea){
            cutPolygons.Add( IntListToVector2( solution[i] ));
        }
        }
        */
        return IntListsToVector2(solution);
    }
    public static List<List<Vector2>> clip(List<Vector2> boundary, List<Vector2> region)
    {
        Polygons boundaryPoly = createPolygons(boundary);
        Polygons regionPoly = createPolygons(region);

        //clip triangular polygon against the boundary polygon
        Polygons result = new Polygons();
        Clipper c = new Clipper();
        c.AddPaths(regionPoly, PolyType.ptClip, true);
        c.AddPaths(boundaryPoly, PolyType.ptSubject, true);
        c.Execute(ClipType.ctIntersection, result, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

        List<List<Vector2>> clippedPolygons = new List<List<Vector2>>();

        foreach (Polygon poly in result)
        {
            List<Vector2> clippedPoly = new List<Vector2>();
            foreach (IntPoint p in poly)
            {
                clippedPoly.Add(new Vector2(p.X, p.Y) / multiplier);
            }
            clippedPolygons.Add(clippedPoly);

        }
        return clippedPolygons;
    }
Exemplo n.º 6
0
 public List<List<IntPoint>> Run (List<List<IntPoint>> subject, double scale)
 {
   var c = ToClipper (scale, clip);
   var clipper = new Clipper ();
   clipper.AddPaths (subject, PolyType.ptSubject, subjectClosed);
   clipper.AddPaths (c, PolyType.ptClip, true);
   var solution = new List<List<IntPoint>> ();
   clipper.Execute (type, solution, subjectFill, clipFill);
   return solution;
 }
Exemplo n.º 7
0
    List<IntPoint> GetArea(Mesh mesh)
    {
        int[] triangles = mesh.triangles;
        Vector3[] vertices = mesh.vertices;

        List<Vector2> list = new List<Vector2>();

        //Debug.Log("ver count: " + vertices.Length + " triangle: " + triangles.Length);

        float y = float.MinValue;
        for(int i=0; i < triangles.Length; i = i+3){
            Vector3 p0 = vertices[triangles[i]];
            Vector3 p1 = vertices[triangles[i+1]];
            Vector3 p2 = vertices[triangles[i+2]];

            if(Approximately(p0.y, p1.y) && Approximately(p0.y, p2.y)){
                //Debug.Log(string.Format("({0}, {1}, {2})", p0, p1, p2));

                if(y == float.MinValue){
                    y = p0.y;
                }

                if(Approximately(p0.y, y)){
                    list.Add(new Vector2(p0.x, p0.z));
                    list.Add(new Vector2(p1.x, p1.z));
                    list.Add(new Vector2(p2.x, p2.z));
                }
            }
        }

        //Debug.Log("list: " + list.Count);

        List<List<IntPoint>> paths = new List<List<IntPoint>>();
        for(int i=0; i < list.Count; i = i+3){
            List<IntPoint> path = new List<IntPoint>();

            for(int j=0; j < 3; j++){
                path.Add(new IntPoint(list[i+j].x * clipScalling, list[i+j].y * clipScalling));
            }

            paths.Add(path);
        }

        Clipper clipper = new Clipper();

        List<List<IntPoint>> solution = new List<List<IntPoint>>();
        clipper.AddPaths(paths, PolyType.ptSubject, true);
        clipper.Execute(ClipType.ctUnion, solution);

        if(solution.Count > 0){
            return solution[0];
        }

        return null;
    }
            public double FitnessFunctionG()
            {
                // return 3;
                double fitnessFunctionVar = 0;
                int    precision          = 100;

                Clipper cc = new ClipperLib.Clipper();

                Paths solution = new Paths();
                Paths subjects = new Paths();
                Paths clips    = new Paths();



                foreach (Room room in collection)
                {
                    subjects.Add(new Path(room.GetClipperLibPath(precision)));
                }

                IntPoint boundaryA = new IntPoint(
                    (int)((boundary.GetBoundingBox(false).Center.X - boundary.GetBoundingBox(false).Diagonal.X / 2) * precision)
                    , (int)((boundary.GetBoundingBox(false).Center.Y - boundary.GetBoundingBox(false).Diagonal.Y / 2) * precision));

                IntPoint boundaryB = new IntPoint(
                    (int)((boundary.GetBoundingBox(false).Center.X - boundary.GetBoundingBox(false).Diagonal.X / 2) * precision)
                    , (int)((boundary.GetBoundingBox(false).Center.Y + boundary.GetBoundingBox(false).Diagonal.Y / 2) * precision));

                IntPoint boundaryC = new IntPoint(
                    (int)((boundary.GetBoundingBox(false).Center.X + boundary.GetBoundingBox(false).Diagonal.X / 2) * precision)
                    , (int)((boundary.GetBoundingBox(false).Center.Y + boundary.GetBoundingBox(false).Diagonal.Y / 2) * precision));

                IntPoint boundaryD = new IntPoint(
                    (int)((boundary.GetBoundingBox(false).Center.X + boundary.GetBoundingBox(false).Diagonal.X / 2) * precision)
                    , (int)((boundary.GetBoundingBox(false).Center.Y - boundary.GetBoundingBox(false).Diagonal.Y / 2) * precision));


                clips.Add(new Path(new List <IntPoint>()
                {
                    boundaryA, boundaryB, boundaryC, boundaryD
                }));

                cc.AddPaths(subjects, PolyType.ptSubject, true);
                cc.AddPaths(clips, PolyType.ptClip, true);


                cc.Execute(ClipType.ctIntersection, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

                foreach (Path path in solution)
                {
                    fitnessFunctionVar += Clipper.Area(path);
                }


                return(fitnessFunctionVar);
            }
Exemplo n.º 9
0
        public void DoCircleClipping(Vector2 pos, float radius)
        {
            List<VertexPosition[]> shape_old = shape;
            bool isCleared = false;
            int sc = 0;
            for (sc = 0; sc < shape_old.Count; sc++)
            {
                ClippingPolygons subj = new ClippingPolygons(1);
                subj.Add(new ClippingPolygon(shape_old[sc].Length));
                foreach (VertexPosition point in shape_old[sc])
                {
                    subj[0].Add(new IntPoint((int)((point.Position.X) * accuracy), (int)((point.Position.Y) * accuracy)));
                }

                ClippingPolygons clip = new ClippingPolygons(1);
                clip.Add(new ClippingPolygon());
                for (int alpha = 0; alpha < 360; alpha += 10)
                {
                    clip[0].Add(new IntPoint((int)(((Math.Sin((alpha) * Math.PI / 180.0) * radius) + pos.X) * accuracy), (int)(((Math.Cos((alpha) * Math.PI / 180.0) * radius) + pos.Y) * accuracy)));
                    //log.Log(pos.ToString());
                }

                ClippingPolygons solution = new ClippingPolygons();

                Clipper c = new Clipper();
                c.AddPolygons(subj, PolyType.ptSubject);
                c.AddPolygons(clip, PolyType.ptClip);

                if (c.Execute(ClipType.ctDifference, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd))
                {
                    if (!isCleared)
                    {
                        shape = new List<VertexPosition[]>();
                        drawer.Clear();
                        isCleared = true;
                    }

                    for (int f = 0; f < solution.Count; f++)
                    {

                        shape.Add(new VertexPosition[solution[f].Count]);
                        drawer.Add(new ChunkDrawer(ref log));

                        for (int i = 0; i < solution[f].Count; i++)
                        {

                            shape[shape.Count-1][i] = new VertexPosition(solution[f][i].X / accuracy, solution[f][i].Y / accuracy, 0);
                        }
                        drawer[shape.Count-1].BufferVertices(shape[shape.Count - 1]);
                    }

                }
            }
        }
Exemplo n.º 10
0
 public double RelativeAreaDiff (List<List<IntPoint>> actual, List<List<IntPoint>>expected)
 {
   var expectedArea = expected.Sum (path => Clipper.Area (path));
   var difference = new List<List<IntPoint>> ();
   var clipper = new Clipper ();
   clipper.AddPaths (actual, PolyType.ptSubject, true);
   clipper.AddPaths (expected, PolyType.ptClip, true);
   clipper.Execute (ClipType.ctXor, difference, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
   var differenceArea = difference.Sum (path => Clipper.Area (path));
   return Math.Abs (differenceArea) / Math.Abs (expectedArea);
 }
Exemplo n.º 11
0
 // perform xor
 public static Paths ClipperXor(this Polygon clip, Polygon subject)
 {
     var subj = new Paths();
     subj.Add(subject.ToClipperPath());
     var clp = new Paths();
     clp.Add(clip.ToClipperPath());
     var result = new Paths();
     var c = new Clipper();
     c.Execute(ClipType.ctXor, result, PolyFillType.pftPositive, PolyFillType.pftPositive);
     return result;
 }
Exemplo n.º 12
0
        /// <summary>
        /// Checks if polygons are intersecting
        /// </summary>
        /// <param name="p1">Subject polygon</param>
        /// <param name="p2">Clip polygon(s)</param>
        /// <returns>true if intersects</returns>
        public static bool IsIntersects(Paths p1, params Paths[] p2)
        {
            Clipper c = new Clipper();
            Paths solution = new Paths();
            c.AddPaths(p1, PolyType.ptSubject, true);

            for(int i = 0; i < p2.Length; i++)
                c.AddPaths(p2[i], PolyType.ptClip, true);

            c.Execute(ClipType.ctIntersection, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            return solution.Count != 0;
        }
Exemplo n.º 13
0
    public static Vector3[] MeshDifference(Vector3[] mesh1, Vector3[] mesh2)
    {
        List<IntPoint> subj = MeshToPath3D(mesh1);
        List<IntPoint> clip = MeshToPath3D(mesh2);
        List<List<IntPoint>> solution = new List<List<IntPoint>>();

        Clipper c = new Clipper();
        c.AddPath(subj, PolyType.ptSubject, true);
        c.AddPath(clip, PolyType.ptClip, true);
        c.Execute(ClipType.ctDifference, solution,
          PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

        return PathToMesh3D(solution[0]);
    }
Exemplo n.º 14
0
        public Paths BuildOutlines(float growamt = 5 *3)
        {
            ClipperLib.Clipper cp = new ClipperLib.Clipper();
            Path pp = new Path();

            pp.AddRange(Vertices);
            Paths pps = new Paths();

            pps.Add(pp);
            var Res = Clipper.OffsetPolygons(pps, growamt, JoinType.jtRound);


            return(Res);
        }
Exemplo n.º 15
0
 // perform union on a list of polygons
 public static Paths ClipperUnion(this List<Polygon> polygons)
 {
     var subj = new Paths(polygons.Count);
     var clip = new Paths(polygons.Count);
     foreach (var polygon in polygons)
     {
         subj.Add(polygon.ToClipperPath());
         clip.Add(polygon.ToClipperPath());
     }
     var solution = new Paths();
     var c = new Clipper();
     c.AddPaths(subj, PolyType.ptSubject, true);
     c.AddPaths(clip, PolyType.ptClip, true);
     c.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
     return solution;
 }
Exemplo n.º 16
0
 public static List<List<IntPoint>> ClipPolygons(List<Polygon> polygons)
 {
     var subj = new List<List<IntPoint>>(polygons.Count);
     var clip = new List<List<IntPoint>>(polygons.Count);
     foreach (var polygon in polygons)
     {
         subj.Add(polygon.ToClipperPath());
         clip.Add(polygon.ToClipperPath());
     }
     var solution = new List<List<IntPoint>>();
     var c = new Clipper();
     c.AddPaths(subj, PolyType.ptSubject, true);
     c.AddPaths(clip, PolyType.ptClip, true);
     c.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftEvenOdd);
     return solution;
 }
Exemplo n.º 17
0
        private double ClippedArea()
        {
            if (this.Voids == null || this.Voids.Count == 0)
            {
                return(this.Perimeter.Area());
            }

            var clipper = new ClipperLib.Clipper();

            clipper.AddPath(this.Perimeter.ToClipperPath(), ClipperLib.PolyType.ptSubject, true);
            clipper.AddPaths(this.Voids.Select(p => p.ToClipperPath()).ToList(), ClipperLib.PolyType.ptClip, true);
            var solution = new List <List <ClipperLib.IntPoint> >();

            clipper.Execute(ClipperLib.ClipType.ctDifference, solution, ClipperLib.PolyFillType.pftEvenOdd);
            return(solution.Sum(s => ClipperLib.Clipper.Area(s)) / Math.Pow(1.0 / Vector3.EPSILON, 2));
        }
        public static List<Vector2> Add(this Shape shape, Shape secondShape, Action<Shape> completed)
        {
            List<Vector2> points = new List<Vector2>();

            Clipper c = new Clipper();

            List<List<IntPoint>> subj = new List<List<IntPoint>>();
            List<List<IntPoint>> clip = new List<List<IntPoint>>();
            List<List<IntPoint>> solution = new List<List<IntPoint>>();
            List<IntPoint> p1 = new List<IntPoint>();
            List<IntPoint> p2 = new List<IntPoint>();
            int i = 0, l = shape.Points.Length;
            Vector2 pos = shape.BuiltGameObject.transform.position;
            for(;i<l;++i)
            {
                IntPoint ip = new IntPoint(shape.Points[i].x + pos.x,shape.Points[i].y + pos.y);
                p1.Add(ip);
            }
            p1.Add(p1[0]);

            pos = secondShape.BuiltGameObject.transform.position;
            i = 0; l = secondShape.Points.Length;
            for(;i<l;++i)
            {
                IntPoint ip = new IntPoint(secondShape.Points[i].x + pos.x,secondShape.Points[i].y + pos.y);
                p2.Add(ip);
            }
            p2.Add(p2[0]);

            subj.Add(p1);
            clip.Add(p2);

            c.AddPaths(subj,PolyType.ptSubject,true);
            c.AddPaths(clip,PolyType.ptClip,true);
            c.Execute(ClipType.ctUnion,solution);

            i = 0; l = solution[0].Count;
            for(;i<l;++i)
            {
                float x = System.Convert.ToSingle(solution[0][i].X);
                float y = System.Convert.ToSingle(solution[0][i].Y);
                points.Add(new Vector2(x,y));
            }

            Mesh2D.Instance.ReBuild(shape.BuiltGameObject,points,completed,shape.Col);
            return points;
        }
        public List<Polygon> Clip(Polygon p1, Polygon p2, OpType operation)
        {
            List<IntPoint> pol1 = new List<IntPoint>();
            List<IntPoint> pol2 = new List<IntPoint>();
            List<List<IntPoint>> res = new List<List<IntPoint>>();

            foreach (Point point in p1.Points) {
                pol1.Add(new IntPoint(point.X, point.Y));
            }
            foreach (Point point in p2.Points) {
                pol2.Add(new IntPoint(point.X, point.Y));
            }

            Clipper clipper = new Clipper();
            clipper.AddPolygon(pol1, PolyType.ptSubject);
            clipper.AddPolygon(pol2, PolyType.ptClip);

            switch (operation) {
                case OpType.Difference:
                    clipper.Execute(ClipType.ctDifference, res);
                    break;
                case OpType.Intersection:
                    clipper.Execute(ClipType.ctIntersection, res);
                    break;
                case OpType.Union:
                    clipper.Execute(ClipType.ctUnion, res);
                    break;
                case OpType.Xor:
                    clipper.Execute(ClipType.ctXor, res);
                    break;
            }
            List<Polygon> ret = new List<Polygon>();

            foreach (var poly in res) {
                Polygon pol = new Polygon() { Points = new List<Point>() };

                foreach (var poi in poly) {
                    pol.Points.Add(new Point() { X = poi.X, Y = poi.Y });
                }

                ret.Add(pol);
            }
            return ret;
        }
Exemplo n.º 20
0
		private PathStorage CombinePaths(IVertexSource a, IVertexSource b, ClipType clipType)
		{
			List<List<IntPoint>> aPolys = VertexSourceToClipperPolygons.CreatePolygons(a);
			List<List<IntPoint>> bPolys = VertexSourceToClipperPolygons.CreatePolygons(b);

			Clipper clipper = new Clipper();

			clipper.AddPaths(aPolys, PolyType.ptSubject, true);
			clipper.AddPaths(bPolys, PolyType.ptClip, true);

			List<List<IntPoint>> intersectedPolys = new List<List<IntPoint>>();
			clipper.Execute(clipType, intersectedPolys);

			PathStorage output = VertexSourceToClipperPolygons.CreatePathStorage(intersectedPolys);

			output.Add(0, 0, ShapePath.FlagsAndCommand.CommandStop);

			return output;
		}
Exemplo n.º 21
0
        /// <summary>
        /// Perform a union operation, returning a new profile that is the union of the current profile with the other profile
        /// <param name="profile">The profile with which to create a union.</param>
        /// <param name="tolerance">An optional tolerance.</param>
        /// </summary>
        public Profile Union(Profile profile, double tolerance = Vector3.EPSILON)
        {
            var clipper = new ClipperLib.Clipper();

            clipper.AddPath(this.Perimeter.ToClipperPath(tolerance), PolyType.ptSubject, true);
            clipper.AddPath(profile.Perimeter.ToClipperPath(tolerance), PolyType.ptClip, true);

            if (this.Voids != null && this.Voids.Count > 0)
            {
                clipper.AddPaths(this.Voids.Select(v => v.ToClipperPath(tolerance)).ToList(), PolyType.ptSubject, true);
            }
            if (profile.Voids != null && profile.Voids.Count > 0)
            {
                clipper.AddPaths(profile.Voids.Select(v => v.ToClipperPath(tolerance)).ToList(), PolyType.ptClip, true);
            }
            var solution = new List <List <ClipperLib.IntPoint> >();

            clipper.Execute(ClipType.ctUnion, solution);
            return(new Profile(solution.Select(s => s.ToPolygon(tolerance)).ToList()));
        }
Exemplo n.º 22
0
        public void DoCircleClipping(Vector2 pos, float radius)
        {
            ClippingPolygons subj = new ClippingPolygons(1);
            subj.Add(new ClippingPolygon(shape.Length));
            foreach(VertexPosition point in shape){
                subj[0].Add(new IntPoint((int)((point.Position.X) * accuracy), (int)((point.Position.Y) * accuracy)));
            }

            ClippingPolygons clip = new ClippingPolygons(1);
            clip.Add(new ClippingPolygon());
            for (int alpha = 0; alpha < 360; alpha += 10)
            {
                clip[0].Add(new IntPoint((int)(((Math.Sin((alpha) * Math.PI / 180.0) * radius)+pos.X) * accuracy), (int)(((Math.Cos((alpha) * Math.PI / 180.0) * radius)+pos.Y) * accuracy)));
                //log.Log(pos.ToString());
            }

            ClippingPolygons solution = new ClippingPolygons();

            Clipper c = new Clipper();
            c.AddPolygons(subj, PolyType.ptSubject);
            c.AddPolygons(clip, PolyType.ptClip);

            if (c.Execute(ClipType.ctDifference, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd))
            {

                for (int f = 0; f < solution.Count; f++)
                {
                    if (f == 0)
                    {
                        shape = new VertexPosition[solution[f].Count];
                        for (int i = 0; i < solution[f].Count; i++)
                        {

                            shape[i] = new VertexPosition(solution[f][i].X / accuracy, solution[f][i].Y / accuracy, 0);
                        }
                    }

                }
            }
            BufferVertices(ref shape);
        }
Exemplo n.º 23
0
        public void Clip(double x0, double x1, double y0, double y1)
        {
            var p00 = new Point3d(x0, y0, 0.0);
            var p01 = new Point3d(x0, y1, 0.0);
            var p11 = new Point3d(x1, y1, 0.0);
            var p10 = new Point3d(x1, y0, 0.0);

            var clip = new[] { p00, p10, p11, p01, p00 }.ToPolygon(Plane.WorldXY, Unit);

            var clipper = new Clipper();

            clipper.AddPaths(Polygons, PolyType.ptSubject, true);
            clipper.AddPath(clip, PolyType.ptClip, true);

            var solution = new List<List<IntPoint>>();

            clipper.Execute(ClipType.ctIntersection, solution, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero);

            Polygons = solution;
            Curves = Polygons.ToCurves(Plane, Unit);
        }
Exemplo n.º 24
0
		public static void GenerateLinePaths(Polygons polygonToInfill, ref Polygons infillLinesToPrint, int lineSpacing, int infillExtendIntoPerimeter_um, double rotation, long rotationOffset = 0)
		{
			if (polygonToInfill.Count > 0)
			{
				Polygons outlines = polygonToInfill.Offset(infillExtendIntoPerimeter_um);
				if (outlines.Count > 0)
				{
					PointMatrix matrix = new PointMatrix(-(rotation + 90)); // we are rotating the part so we rotate by the negative so the lines go the way we expect

					outlines.ApplyMatrix(matrix);

					Aabb boundary = new Aabb(outlines);

					boundary.min.X = ((boundary.min.X / lineSpacing) - 1) * lineSpacing - rotationOffset;
					int xLineCount = (int)((boundary.max.X - boundary.min.X + (lineSpacing - 1)) / lineSpacing);
					Polygons unclipedPatern = new Polygons();

					long firstX = boundary.min.X / lineSpacing * lineSpacing;
					for (int lineIndex = 0; lineIndex < xLineCount; lineIndex++)
					{
						Polygon line = new Polygon();
						line.Add(new IntPoint(firstX + lineIndex * lineSpacing, boundary.min.Y));
						line.Add(new IntPoint(firstX + lineIndex * lineSpacing, boundary.max.Y));
						unclipedPatern.Add(line);
					}

					PolyTree ret = new PolyTree();
					Clipper clipper = new Clipper();
					clipper.AddPaths(unclipedPatern, PolyType.ptSubject, false);
					clipper.AddPaths(outlines, PolyType.ptClip, true);
					clipper.Execute(ClipType.ctIntersection, ret, PolyFillType.pftPositive, PolyFillType.pftEvenOdd);

					Polygons newSegments = Clipper.OpenPathsFromPolyTree(ret);
					PointMatrix inversematrix = new PointMatrix((rotation + 90));
					newSegments.ApplyMatrix(inversematrix);

					infillLinesToPrint.AddRange(newSegments);
				}
			}
		}
Exemplo n.º 25
0
        public JsonResult GetBySponsor(ObjectId id)
        {
            var spots = Context.SponsorSpots.GetSpotsBySponsors(id);

            Clipper clipper = new Clipper();
            var polygons = new List<List<IntPoint>>();
            var scale = 100000000.0;

            foreach (var spot in spots)
            {
                var polygon = new List<IntPoint>();

                foreach (var coord in spot.SpotShape)
                {
                    polygon.Add(new IntPoint(coord.Longitude * scale, coord.Latitude * scale));
                }
                polygons.Add(polygon);
            }

            var solution = new List<List<IntPoint>>();

            clipper.AddPaths(polygons, PolyType.ptSubject, true);
            clipper.Execute(ClipType.ctUnion, solution,
                PolyFillType.pftNonZero, PolyFillType.pftNonZero);

            var results = new List<Spot>();

            foreach (var shape in solution)
            {
                var resultShape = new Spot();
                foreach (var item in shape)
                {
                    resultShape.SpotShape.Add(new Coordinate { Latitude = item.Y / scale, Longitude = item.X / scale });
                }
                results.Add(resultShape);
            }

            return Json(new { success = true, results = results }, JsonRequestBehavior.AllowGet);
        }
Exemplo n.º 26
0
		private PathStorage CombinePaths(IVertexSource a, IVertexSource b, ClipType clipType)
		{
			List<List<IntPoint>> aPolys = CreatePolygons(a);
			List<List<IntPoint>> bPolys = CreatePolygons(b);

			Clipper clipper = new Clipper();

			clipper.AddPaths(aPolys, PolyType.ptSubject, true);
			clipper.AddPaths(bPolys, PolyType.ptClip, true);

			List<List<IntPoint>> intersectedPolys = new List<List<IntPoint>>();
			clipper.Execute(clipType, intersectedPolys);

			PathStorage output = new PathStorage();

			foreach (List<IntPoint> polygon in intersectedPolys)
			{
				bool first = true;
				foreach (IntPoint point in polygon)
				{
					if (first)
					{
						output.Add(point.X / 1000.0, point.Y / 1000.0, ShapePath.FlagsAndCommand.CommandMoveTo);
						first = false;
					}
					else
					{
						output.Add(point.X / 1000.0, point.Y / 1000.0, ShapePath.FlagsAndCommand.CommandLineTo);
					}
				}

				output.ClosePolygon();
			}

			output.Add(0, 0, ShapePath.FlagsAndCommand.CommandStop);

			return output;
		}
Exemplo n.º 27
0
        public void OriginalClipperFileBasedTest()
        {
            var testData = LoadTestHelper.LoadFromFile("TestData/tests.txt");

            foreach (var test in testData.Values)
            {
                var subjects = test.Subjects.ToOriginal();
                var clips    = test.Clips.ToOriginal();

                var clipper = new ClipperLib.Clipper();
                clipper.AddPaths(subjects, PolyType.ptSubject, true);
                clipper.AddPaths(clips, PolyType.ptClip, true);

                var originalSolution = new List <List <ClipperLib.IntPoint> >();
                var clipType         = (ClipType)Enum.Parse(typeof(ClipType), $"ct{test.ClipOperation}", true);
                var fillType         = (PolyFillType)Enum.Parse(typeof(PolyFillType), $"pft{test.FillType}", true);
                Assert.IsTrue(clipper.Execute(clipType, originalSolution, fillType));
                Assert.AreEqual(test.Solution.Count, originalSolution.Count, test.Caption);

                var solution = originalSolution.ToNew();

                // TODO: reinclude these tests once test data is verified.
                var ignoreTestNumbers = new[] { 36, 38, 39, 44, 46, 48, 51, 52, 59, 64, 67, 69 };
                if (ignoreTestNumbers.Contains(test.TestNumber))
                {
                    continue;
                }

                Assert.AreEqual(test.Solution.Count, solution.Count, $"{test.TestNumber}: {test.Caption}");

                // Match points, THIS IS DESTRUCTIVE TO BOTH THE TEST DATA AND RESULT DATA.
                Assert.IsTrue(AreSame(test, solution));

                // If we had an exact match then both solutions should now be empty.
                Assert.AreEqual(0, test.Solution.Count, $"{test.TestNumber}: {test.Caption}");
                Assert.AreEqual(0, solution.Count, $"{test.TestNumber}: {test.Caption}");
            }
        }
Exemplo n.º 28
0
        private static void TestCliper()
        {
            Paths subj = new Paths(2);
            subj.Add(new Path(4));
            subj[0].Add(new IntPoint(180, 200));
            subj[0].Add(new IntPoint(260, 200));
            subj[0].Add(new IntPoint(260, 150));
            subj[0].Add(new IntPoint(180, 150));

            subj.Add(new Path(3));
            subj[1].Add(new IntPoint(215, 160));
            subj[1].Add(new IntPoint(230, 190));
            subj[1].Add(new IntPoint(200, 190));

            Paths clip = new Paths(1);
            clip.Add(new Path(4));
            clip[0].Add(new IntPoint(190, 210));
            clip[0].Add(new IntPoint(240, 210));
            clip[0].Add(new IntPoint(240, 130));
            clip[0].Add(new IntPoint(190, 130));

            //DrawPolygons(subj, Color.FromArgb(0x16, 0, 0, 0xFF),
            //  Color.FromArgb(0x60, 0, 0, 0xFF));
            //DrawPolygons(clip, Color.FromArgb(0x20, 0xFF, 0xFF, 0),
            //  Color.FromArgb(0x30, 0xFF, 0, 0));

            Paths solution = new Paths();

            Clipper c = new Clipper();
            c.AddPaths(subj, PolyType.ptSubject, true);
            c.AddPaths(clip, PolyType.ptClip, true);
            c.Execute(ClipType.ctIntersection, solution,
              PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
            //DrawPolygons(solution, Color.FromArgb(0x30, 0, 0xFF, 0),
            //  Color.FromArgb(0xFF, 0, 0x66, 0));
        }
Exemplo n.º 29
0
        /// <summary>
        ///     Joins all the polygones.
        ///     ClipType: http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/ClipType.htm
        ///     PolyFillType: http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/PolyFillType.htm
        /// </summary>
        /// <param name="sList">The s list.</param>
        /// <param name="cType">Type of the c.</param>
        /// <param name="pType">Type of the p.</param>
        /// <param name="pFType1">The p f type1.</param>
        /// <param name="pFType2">The p f type2.</param>
        /// <returns></returns>
        public static List<Polygon> ELJoinPolygons(this List<Polygon> sList, ClipType cType,
            PolyType pType = PolyType.ptClip, PolyFillType pFType1 = PolyFillType.pftNonZero,
            PolyFillType pFType2 = PolyFillType.pftNonZero)
        {
            var p = ELClipPolygons(sList);
            var tList = new List<List<IntPoint>>();

            var c = new Clipper();
            c.AddPaths(p, pType, true);
            c.Execute(cType, tList, pFType1, pFType2);

            return ToPolygons(tList);
        }
Exemplo n.º 30
0
        /// <summary>
        ///     Joins all the polygones in the list in one polygone if they interect.
        /// </summary>
        /// <param name="sList">The polygon list.</param>
        /// <returns></returns>
        public static List<Polygon> ELJoinPolygons(this List<Polygon> sList)
        {
            var p = ELClipPolygons(sList);
            var tList = new List<List<IntPoint>>();

            var c = new Clipper();
            c.AddPaths(p, PolyType.ptClip, true);
            c.Execute(ClipType.ctUnion, tList, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

            return ToPolygons(tList);
        }
Exemplo n.º 31
0
        private static void InterceptionQ(Obj_AI_Hero Enemy)
        {
            Geometry.Polygon.Circle Qspellpoly = new Geometry.Polygon.Circle(PreCastPos(Enemy, 0.6f), 130f);

            Paths subjs = new Paths();
            foreach (var bla in WPPolygon(Enemy).ToPolygons())
            {
                subjs.Add(bla.ToClipperPath());
            }

            Paths clips = new Paths(1);
            clips.Add(Qspellpoly.ToClipperPath());

            Paths solution = new Paths();
            Clipper c = new Clipper();
            c.AddPaths(subjs, PolyType.ptSubject, true);
            c.AddPaths(clips, PolyType.ptClip, true);
            c.Execute(ClipType.ctIntersection, solution);

            foreach (var bli in solution.ToPolygons())
            {
                bli.Draw(System.Drawing.Color.Blue);
            }
        }
Exemplo n.º 32
0
        /// <summary>
        /// Applies a buoyant force, drag and lift to an object submerged in the water.
        /// </summary>
        /// <param name="subjectPoly"> The polygon of the object in the water.</param>
        /// <param name="minIndex"> The min index for a value in the "waterLinePoints" list. </param>
        /// <param name="maxIndex"> The max index for a value in the "waterLinePoints" list. </param>
        /// <param name="isIntersecting"> Are the subject and clipping polygon intersecting?. </param>
        private List<List<Vector2>> GetIntersectionPolygon(Vector2[] subjectPoly, int minIndex, int maxIndex, out bool isIntersecting)
        {
            Vector2 bottomHandleGlobalPos = transform.TransformPoint(water2D.handlesPosition[1]);
            List<List<Vector2>> intersectionPoly = new List<List<Vector2>>();
            List<Vector2> clipPolygon = new List<Vector2>();
            Clipper clipper = new Clipper();
            Paths solutionPath = new Paths();
            Path subjPath = new Path();
            Path clipPath = new Path();
            int len, len2, min, max;
            isIntersecting = true;

            if (surfaceVertsCount > meshSegmentsPerWaterLineSegment)
            {
                min = (int)Mathf.Floor(minIndex / meshSegmentsPerWaterLineSegment);
                max = (int)Mathf.Floor(maxIndex / meshSegmentsPerWaterLineSegment) + 1;

                if (max > waterLinePoints.Count - 2)
                    max = waterLinePoints.Count - 2;

                for (int i = min; i <= max; i++)
                {
                    clipPolygon.Add(waterLinePoints[i]);
                }

                int last = clipPolygon.Count - 1;
                clipPolygon.Add(new Vector2(clipPolygon[last].x, bottomHandleGlobalPos.y));
                clipPolygon.Add(new Vector2(clipPolygon[0].x, bottomHandleGlobalPos.y));
            }
            else
            {
                Vector2 vertGlobalPos = transform.TransformPoint(vertices[surfaceVertsCount]);
                clipPolygon.Add(vertGlobalPos);
                vertGlobalPos = transform.TransformPoint(vertices[surfaceVertsCount + surfaceVertsCount - 1]);
                clipPolygon.Add(new Vector2(vertGlobalPos.x, vertGlobalPos.y));

                int last = clipPolygon.Count - 1;
                clipPolygon.Add(new Vector2(clipPolygon[last].x, bottomHandleGlobalPos.y));
                clipPolygon.Add(new Vector2(clipPolygon[0].x, bottomHandleGlobalPos.y));
            }

            if (showClippingPlolygon)
            {
                for (int i = 0; i < clipPolygon.Count; i++)
                {
                    if (i < clipPolygon.Count - 1)
                        Debug.DrawLine(clipPolygon[i], clipPolygon[i + 1], Color.green);
                    else
                        Debug.DrawLine(clipPolygon[i], clipPolygon[0], Color.green);
                }
            }

            len = subjectPoly.Length;
            for (int i = 0; i < len; i++)
            {
                subjPath.Add(new IntPoint(subjectPoly[i].x * scaleFactor, subjectPoly[i].y * scaleFactor));
            }

            len = clipPolygon.Count;
            for (int i = 0; i < len; i++)
            {
                clipPath.Add(new IntPoint(clipPolygon[i].x * scaleFactor, clipPolygon[i].y * scaleFactor));
            }

            clipper.AddPath(subjPath, PolyType.ptSubject, true);
            clipper.AddPath(clipPath, PolyType.ptClip, true);
            clipper.Execute(ClipType.ctIntersection, solutionPath, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            if (solutionPath.Count != 0)
            {
                len = solutionPath.Count;

                for (int i = 0; i < len; i++)
                {
                    len2 = solutionPath[i].Count;
                    List<Vector2> list = new List<Vector2>();

                    for (int j = 0; j < len2; j++)
                    {
                        list.Add(new Vector2(solutionPath[i][j].X / scaleFactor, solutionPath[i][j].Y / scaleFactor));
                    }

                    intersectionPoly.Add(list);
                }
                return intersectionPoly;
            }
            else
            {
                isIntersecting = false;
                return null;
            }
        }
Exemplo n.º 33
0
        public static NFP simplifyFunction(NFP polygon, bool inside)
        {
            var tolerance = 4 * Config.curveTolerance;

            // give special treatment to line segments above this length (squared)
            var fixedTolerance = 40 * Config.curveTolerance * 40 * Config.curveTolerance;
            int i, j, k;


            if (Config.simplify)
            {
                /*
                 *              // use convex hull
                 *              var hull = new ConvexHullGrahamScan();
                 *              for(var i=0; i<polygon.length; i++){
                 *                      hull.addPoint(polygon[i].x, polygon[i].y);
                 *              }
                 *
                 *              return hull.getHull();*/
                var hull = Background.getHull(polygon);
                if (hull != null)
                {
                    return(hull);
                }
                else
                {
                    return(polygon);
                }
            }

            var cleaned = cleanPolygon2(polygon);

            if (cleaned != null && cleaned.length > 1)
            {
                polygon = cleaned;
            }
            else
            {
                return(polygon);
            }
            // polygon to polyline
            var copy = polygon.slice(0);

            copy.push(copy[0]);
            // mark all segments greater than ~0.25 in to be kept
            // the PD simplification algo doesn't care about the accuracy of long lines, only the absolute distance of each point
            // we care a great deal
            for (i = 0; i < copy.length - 1; i++)
            {
                var p1  = copy[i];
                var p2  = copy[i + 1];
                var sqd = (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y);
                if (sqd > fixedTolerance)
                {
                    p1.marked = true;
                    p2.marked = true;
                }
            }

            var simple = Simplify.simplify(copy, tolerance, true);

            // now a polygon again
            //simple.pop();
            simple.Points = simple.Points.Take(simple.Points.Count() - 1).ToArray();

            // could be dirty again (self intersections and/or coincident points)
            simple = cleanPolygon2(simple);

            // simplification process reduced poly to a line or point
            if (simple == null)
            {
                simple = polygon;
            }



            var offsets = polygonOffsetDeepNest(simple, inside ? -tolerance : tolerance);

            NFP        offset     = null;
            double     offsetArea = 0;
            List <NFP> holes      = new List <NFP>();

            for (i = 0; i < offsets.Length; i++)
            {
                var area = GeometryUtil.polygonArea(offsets[i]);
                if (offset == null || area < offsetArea)
                {
                    offset     = offsets[i];
                    offsetArea = area;
                }
                if (area > 0)
                {
                    holes.Add(offsets[i]);
                }
            }

            // mark any points that are exact
            for (i = 0; i < simple.length; i++)
            {
                var seg = new NFP();
                seg.AddPoint(simple[i]);
                seg.AddPoint(simple[i + 1 == simple.length ? 0 : i + 1]);

                var index1 = find(seg[0], polygon);
                var index2 = find(seg[1], polygon);

                if (index1 + 1 == index2 || index2 + 1 == index1 || (index1 == 0 && index2 == polygon.length - 1) || (index2 == 0 && index1 == polygon.length - 1))
                {
                    seg[0].exact = true;
                    seg[1].exact = true;
                }
            }
            var numshells = 4;

            NFP[] shells = new NFP[numshells];

            for (j = 1; j < numshells; j++)
            {
                var delta = j * (tolerance / numshells);
                delta = inside ? -delta : delta;
                var shell = polygonOffsetDeepNest(simple, delta);
                if (shell.Count() > 0)
                {
                    shells[j] = shell.First();
                }
                else
                {
                    //shells[j] = shell;
                }
            }

            if (offset == null)
            {
                return(polygon);
            }
            // selective reversal of offset
            for (i = 0; i < offset.length; i++)
            {
                var o      = offset[i];
                var target = getTarget(o, simple, 2 * tolerance);

                // reverse point offset and try to find exterior points
                var test = clone(offset);
                test.Points[i] = new SvgPoint(target.x, target.y);

                if (!exterior(test, polygon, inside))
                {
                    o.x = target.x;
                    o.y = target.y;
                }
                else
                {
                    // a shell is an intermediate offset between simple and offset
                    for (j = 1; j < numshells; j++)
                    {
                        if (shells[j] != null)
                        {
                            var shell = shells[j];
                            var delta = j * (tolerance / numshells);
                            target         = getTarget(o, shell, 2 * delta);
                            test           = clone(offset);
                            test.Points[i] = new SvgPoint(target.x, target.y);
                            if (!exterior(test, polygon, inside))
                            {
                                o.x = target.x;
                                o.y = target.y;
                                break;
                            }
                        }
                    }
                }
            }

            // straighten long lines
            // a rounded rectangle would still have issues at this point, as the long sides won't line up straight

            var straightened = false;

            for (i = 0; i < offset.length; i++)
            {
                var p1 = offset[i];
                var p2 = offset[i + 1 == offset.length ? 0 : i + 1];

                var sqd = (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y);

                if (sqd < fixedTolerance)
                {
                    continue;
                }
                for (j = 0; j < simple.length; j++)
                {
                    var s1 = simple[j];
                    var s2 = simple[j + 1 == simple.length ? 0 : j + 1];

                    var sqds = (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y);

                    if (sqds < fixedTolerance)
                    {
                        continue;
                    }

                    if ((GeometryUtil._almostEqual(s1.x, s2.x) || GeometryUtil._almostEqual(s1.y, s2.y)) && // we only really care about vertical and horizontal lines
                        GeometryUtil._withinDistance(p1, s1, 2 * tolerance) &&
                        GeometryUtil._withinDistance(p2, s2, 2 * tolerance) &&
                        (!GeometryUtil._withinDistance(p1, s1, Config.curveTolerance / 1000) ||
                         !GeometryUtil._withinDistance(p2, s2, Config.curveTolerance / 1000)))
                    {
                        p1.x         = s1.x;
                        p1.y         = s1.y;
                        p2.x         = s2.x;
                        p2.y         = s2.y;
                        straightened = true;
                    }
                }
            }

            //if(straightened){

            var Ac = _Clipper.ScaleUpPaths(offset, 10000000);
            var Bc = _Clipper.ScaleUpPaths(polygon, 10000000);

            var combined = new List <List <IntPoint> >();
            var clipper  = new ClipperLib.Clipper();

            clipper.AddPath(Ac.ToList(), ClipperLib.PolyType.ptSubject, true);
            clipper.AddPath(Bc.ToList(), ClipperLib.PolyType.ptSubject, true);

            // the line straightening may have made the offset smaller than the simplified
            if (clipper.Execute(ClipperLib.ClipType.ctUnion, combined, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero))
            {
                double?largestArea = null;
                for (i = 0; i < combined.Count; i++)
                {
                    var n     = Background.toNestCoordinates(combined[i].ToArray(), 10000000);
                    var sarea = -GeometryUtil.polygonArea(n);
                    if (largestArea == null || largestArea < sarea)
                    {
                        offset      = n;
                        largestArea = sarea;
                    }
                }
            }
            //}

            cleaned = cleanPolygon2(offset);
            if (cleaned != null && cleaned.length > 1)
            {
                offset = cleaned;
            }

            // mark any points that are exact (for line merge detection)
            for (i = 0; i < offset.length; i++)
            {
                var seg    = new SvgPoint[] { offset[i], offset[i + 1 == offset.length ? 0 : i + 1] };
                var index1 = find(seg[0], polygon);
                var index2 = find(seg[1], polygon);
                if (index1 == null)
                {
                    index1 = 0;
                }
                if (index2 == null)
                {
                    index2 = 0;
                }
                if (index1 + 1 == index2 || index2 + 1 == index1 ||
                    (index1 == 0 && index2 == polygon.length - 1) ||
                    (index2 == 0 && index1 == polygon.length - 1))
                {
                    seg[0].exact = true;
                    seg[1].exact = true;
                }
            }

            if (!inside && holes != null && holes.Count > 0)
            {
                offset.children = holes;
            }

            return(offset);
        }
 //------------------------------------------------------------------------------
 public static Polygons SimplifyPolygons(Polygons polys)
 {
     Polygons result = new Polygons();
     Clipper c = new Clipper();
     c.AddPolygons(polys, PolyType.ptSubject);
     c.Execute(ClipType.ctUnion, result);
     return result;
 }
Exemplo n.º 35
0
        public static PolyTree ExecuteClipper(TmxMap tmxMap, TmxLayer tmxLayer, TransformPointFunc xfFunc, ProgressFunc progFunc)
        {
            // The "fullClipper" combines the clipper results from the smaller pieces
            ClipperLib.Clipper fullClipper = new ClipperLib.Clipper();

            // From the perspective of Clipper lines are polygons too
            // Closed paths == polygons
            // Open paths == lines
            var polygonGroups = from y in Enumerable.Range(0, tmxLayer.Height)
                                from x in Enumerable.Range(0, tmxLayer.Width)
                                let rawTileId = tmxLayer.GetRawTileIdAt(x, y)
                                                let tileId = TmxMath.GetTileIdWithoutFlags(rawTileId)
                                                             where tileId != 0
                                                             let tile = tmxMap.Tiles[tileId]
                                                                        from polygon in tile.ObjectGroup.Objects
                                                                        where (polygon as TmxHasPoints) != null
                                                                        let groupX = x / LayerClipper.GroupBySize
                                                                                     let groupY = y / LayerClipper.GroupBySize
                                                                                                  group new
            {
                PositionOnMap         = tmxMap.GetMapPositionAt(x, y, tile),
                HasPointsInterface    = polygon as TmxHasPoints,
                TmxObjectInterface    = polygon,
                IsFlippedDiagnoally   = TmxMath.IsTileFlippedDiagonally(rawTileId),
                IsFlippedHorizontally = TmxMath.IsTileFlippedHorizontally(rawTileId),
                IsFlippedVertically   = TmxMath.IsTileFlippedVertically(rawTileId),
                TileCenter            = new PointF(tile.TileSize.Width * 0.5f, tile.TileSize.Height * 0.5f),
            }
            by Tuple.Create(groupX, groupY);

            int groupIndex = 0;
            int groupCount = polygonGroups.Count();

            foreach (var polyGroup in polygonGroups)
            {
                if (groupIndex % 5 == 0)
                {
                    progFunc(String.Format("Clipping '{0}' polygons: {1}%", tmxLayer.UniqueName, (groupIndex / (float)groupCount) * 100));
                }
                groupIndex++;

                // The "groupClipper" clips the polygons in a smaller part of the world
                ClipperLib.Clipper groupClipper = new ClipperLib.Clipper();

                // Add all our polygons to the Clipper library so it can reduce all the polygons to a (hopefully small) number of paths
                foreach (var poly in polyGroup)
                {
                    // Create a clipper library polygon out of each and add it to our collection
                    ClipperPolygon clipperPolygon = new ClipperPolygon();

                    // Our points may be transformed due to tile flipping/rotation
                    // Before we transform then we put all the points into local space relative to the tile
                    SizeF    offset            = new SizeF(poly.TmxObjectInterface.Position);
                    PointF[] transformedPoints = poly.HasPointsInterface.Points.Select(pt => PointF.Add(pt, offset)).ToArray();

                    // Now transform the points relative to the tile
                    TmxMath.TransformPoints(transformedPoints, poly.TileCenter, poly.IsFlippedDiagnoally, poly.IsFlippedHorizontally, poly.IsFlippedVertically);

                    foreach (var pt in transformedPoints)
                    {
                        float x = poly.PositionOnMap.X + pt.X;
                        float y = poly.PositionOnMap.Y + pt.Y;

                        ClipperLib.IntPoint point = xfFunc(x, y);
                        clipperPolygon.Add(point);
                    }

                    // Because of Unity's cooridnate system, the winding order of the polygons must be reversed
                    clipperPolygon.Reverse();

                    // Add the "subject"
                    groupClipper.AddPath(clipperPolygon, ClipperLib.PolyType.ptSubject, poly.HasPointsInterface.ArePointsClosed());
                }

                // Get a solution for this group
                ClipperLib.PolyTree solution = new ClipperLib.PolyTree();
                groupClipper.Execute(ClipperLib.ClipType.ctUnion, solution);

                // Combine the solutions into the full clipper
                fullClipper.AddPaths(Clipper.ClosedPathsFromPolyTree(solution), PolyType.ptSubject, true);
                fullClipper.AddPaths(Clipper.OpenPathsFromPolyTree(solution), PolyType.ptSubject, false);
            }
            progFunc(String.Format("Clipping '{0}' polygons: 100%", tmxLayer.UniqueName));

            ClipperLib.PolyTree fullSolution = new ClipperLib.PolyTree();
            fullClipper.Execute(ClipperLib.ClipType.ctUnion, fullSolution);

            return(fullSolution);
        }
Exemplo n.º 36
0
        private void SetTest()
        {
            if (!_testData.ContainsKey(_testNumber))
            {
                return;
            }

            // Get test of interest.
            var test = _testData[_testNumber];

            _testSubject  = test.Subjects.FirstOrDefault();
            _testClip     = test.Clips.FirstOrDefault();
            _testSolution = test.Solution;

            _newClipperSolution = new PolygonPath();

            var clipper = new Clipper.Clipper();

            clipper.AddPath(test.Subjects, PolygonKind.Subject);
            clipper.AddPath(test.Clips, PolygonKind.Clip);
            clipper.Execute(ClipOperation.Union, _newClipperSolution);

            _testBoundary = _testSolution.Any()
                ? BoundaryBuilder
                            .BuildPolygonBoundary(_testSolution.First(), PolygonKind.Subject)
                            .ToList()
                : null;

            _newClipperBoundary = _newClipperSolution.Any()
                ? BoundaryBuilder
                                  .BuildPolygonBoundary(_newClipperSolution.First(), PolygonKind.Subject)
                                  .ToList()
                : null;

            var originalClipperSolution = new List <List <IntPoint> >();
            var originalClipper         = new ClipperLib.Clipper();

            originalClipper.AddPaths(test.Subjects.ToOriginal(), PolyType.ptSubject, true);
            originalClipper.AddPaths(test.Clips.ToOriginal(), PolyType.ptClip, true);
            originalClipper.Execute(ClipType.ctUnion, originalClipperSolution);
            _originalClipperSolution = originalClipperSolution.ToNew();

            _originalClipperBoundary = _originalClipperSolution.Any()
                ? BoundaryBuilder
                                       .BuildPolygonBoundary(_originalClipperSolution.First(), PolygonKind.Subject)
                                       .ToList()
                : null;

            Program.VisualizerForm.ClipperViewControl.Subjects = new[]
            {
                new PolygonViewModel
                {
                    IsOpen      = false,
                    EdgeColor   = Color.LawnGreen,
                    VertexColor = Color.DarkGreen,
                    Items       = _testSubject?.ToVertices()
                }
            };

            Program.VisualizerForm.ClipperViewControl.Clips = new[]
            {
                new PolygonViewModel
                {
                    IsOpen      = false,
                    EdgeColor   = Color.Blue,
                    VertexColor = Color.DarkBlue,
                    Items       = _testClip?.ToVertices()
                }
            };

            _solutionType = SolutionType.Test;
            SetSolution();
            solutionComboBox.SelectedIndex = 0;
        }
Exemplo n.º 37
0
		static public PolyTree FindDistictObjectBounds(ImageBuffer image)
		{
			MarchingSquaresByte marchingSquaresData = new MarchingSquaresByte(image, 5, 0);
			marchingSquaresData.CreateLineSegments();
			Polygons lineLoops = marchingSquaresData.CreateLineLoops(1);

			if (lineLoops.Count == 1)
			{
				return null;
			}

			// create a bounding polygon to clip against
			IntPoint min = new IntPoint(long.MaxValue, long.MaxValue);
			IntPoint max = new IntPoint(long.MinValue, long.MinValue);
			foreach (Polygon polygon in lineLoops)
			{
				foreach (IntPoint point in polygon)
				{
					min.X = Math.Min(point.X - 10, min.X);
					min.Y = Math.Min(point.Y - 10, min.Y);
					max.X = Math.Max(point.X + 10, max.X);
					max.Y = Math.Max(point.Y + 10, max.Y);
				}
			}

			Polygon boundingPoly = new Polygon();
			boundingPoly.Add(min);
			boundingPoly.Add(new IntPoint(min.X, max.Y));
			boundingPoly.Add(max);
			boundingPoly.Add(new IntPoint(max.X, min.Y));

			// now clip the polygons to get the inside and outside polys
			Clipper clipper = new Clipper();
			clipper.AddPaths(lineLoops, PolyType.ptSubject, true);
			clipper.AddPath(boundingPoly, PolyType.ptClip, true);

			PolyTree polyTreeForPlate = new PolyTree();
			clipper.Execute(ClipType.ctIntersection, polyTreeForPlate);

			return polyTreeForPlate;
		}
            public PolyOffsetBuilder(Polygons pts, Polygons solution, double delta, JoinType jointype, double MiterLimit = 2)
            {
                //precondtion: solution != pts

                if (delta == 0)
                {
                    solution = pts;
                    return;
                }

                this.pts = pts;
                this.delta = delta;
                if (MiterLimit <= 1) MiterLimit = 1;
                double RMin = 2/(MiterLimit*MiterLimit);

                normals = new List<DoublePoint>();

                double deltaSq = delta*delta;
                solution.Clear();
                solution.Capacity = pts.Count;
                for (m_i = 0; m_i < pts.Count; m_i++)
                {
                    int len = pts[m_i].Count;
                    if (len > 1 && pts[m_i][0].X == pts[m_i][len - 1].X &&
                        pts[m_i][0].Y == pts[m_i][len - 1].Y) len--;

                    if (len == 0 || (len < 3 && delta <= 0))
                        continue;
                    else if (len == 1)
                    {
                        Polygon arc;
                        arc = BuildArc(pts[m_i][len - 1], 0, 2 * Math.PI, delta);
                        solution.Add(arc);
                        continue;
                    }

                    //build normals ...
                    normals.Clear();
                    normals.Capacity = len;
                    for (int j = 0; j < len -1; ++j)
                        normals.Add(GetUnitNormal(pts[m_i][j], pts[m_i][j+1]));
                    normals.Add(GetUnitNormal(pts[m_i][len - 1], pts[m_i][0]));

                    currentPoly = new Polygon();
                    m_k = len - 1;
                    for (m_j = 0; m_j < len; ++m_j)
                    {
                        switch (jointype)
                        {
                            case JoinType.jtMiter:
                            {
                                m_R = 1 + (normals[m_j].X*normals[m_k].X +
                                    normals[m_j].Y*normals[m_k].Y);
                                if (m_R >= RMin) DoMiter(); else DoSquare(MiterLimit);
                                break;
                            }
                            case JoinType.jtRound:
                                DoRound();
                                break;
                            case JoinType.jtSquare:
                                DoSquare(1);
                                break;
                        }
                        m_k = m_j;
                    }
                    solution.Add(currentPoly);
                }

                //finally, clean up untidy corners ...
                Clipper clpr = new Clipper();
                clpr.AddPolygons(solution, PolyType.ptSubject);
                if (delta > 0)
                {
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
                }
                else
                {
                    IntRect r = clpr.GetBounds();
                    Polygon outer = new Polygon(4);

                    outer.Add(new IntPoint(r.left - 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.top - 10));
                    outer.Add(new IntPoint(r.left - 10, r.top - 10));

                    clpr.AddPolygon(outer, PolyType.ptSubject);
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                    if (solution.Count > 0)
                    {
                        solution.RemoveAt(0);
                        for (int i = 0; i < solution.Count; i++)
                            solution[i].Reverse();
                    }
                }
            }
Exemplo n.º 39
0
        public static PolyTree ExecuteClipper(TmxMap map, TmxChunk chunk, TransformPointFunc xfFunc)
        {
            ////for(int i=0;i<chunk.Height;i++)
            //// {
            ////     for(int j=0; j<chunk.Width;j++)
            ////     {
            ////         var raw = chunk.GetRawTileIdAt(j, i);
            ////      if(raw!=0)
            ////         {
            ////             var tid = TmxMath.GetTileIdWithoutFlags(raw);
            ////             var tile = map.Tiles[tid];
            ////             foreach(var p in tile.ObjectGroup.Objects)
            ////             {
            ////                 if(p is TmxHasPoints)
            ////                 {
            ////                     p.ToEnumerable().Where((x) =>
            ////                     {
            ////                         if (!usingUnityLayerOverride)
            ////                         {


            ////                             return string.Compare(tuple.Item1.Type, chunk.ParentData.ParentLayer.Name, true) == 0;
            ////                         }

            ////                         return true;
            ////                     });
            ////                 }

            ////             }
            ////         }
            ////     }
            //// }

            //     Clipper clipper = new Clipper(0);
            //     Tuple<TmxObject, TmxTile, uint> tuple = new Tuple<TmxObject, TmxTile, uint>(null, null, 0);
            //     bool usingUnityLayerOverride = !string.IsNullOrEmpty(chunk.ParentData.ParentLayer.UnityLayerOverrideName);
            //     foreach (var item2 in from h__TransparentIdentifier4 in (from y in Enumerable.Range(0, chunk.Height)
            //                                                              from x in Enumerable.Range(0, chunk.Width)
            //                                                              let rawTileId = chunk.GetRawTileIdAt(x, y)
            //                                                              where rawTileId != 0
            //                                                              let tileId = TmxMath.GetTileIdWithoutFlags(rawTileId)
            //                                                              let tile = map.Tiles[tileId]

            //                                                              from polygon in tile.ObjectGroup.Objects
            //                                                              where polygon is TmxHasPoints

            //                                                              select polygon.ToEnumerable().ToList().TrueForAll
            //                                                              (h__TransparentIdentifier4 =>

            //                    {
            //                        UnityEngine.Debug.Log("liudaodelh");
            //                        tuple = new Tuple<TmxObject, TmxTile, uint>(polygon, tile, rawTileId);
            //                        if (!usingUnityLayerOverride)
            //                        {


            //                            return string.Compare(tuple.Item1.Type, chunk.ParentData.ParentLayer.Name, true) == 0;
            //                        }

            //                        return true;
            //                    }))
            //                           select new
            //                           {

            //                               PositionOnMap = map.GetMapPositionAt((int)tuple.Item1.Position.X + chunk.X, (int)tuple.Item1.Position.Y + chunk.Y, tuple.Item2),
            //                               HasPointsInterface = (tuple.Item1 as TmxHasPoints),
            //                               TmxObjectInterface = tuple.Item1,
            //                               IsFlippedDiagnoally = TmxMath.IsTileFlippedDiagonally(tuple.Item3),
            //                               IsFlippedHorizontally = TmxMath.IsTileFlippedHorizontally(tuple.Item3),
            //                               IsFlippedVertically = TmxMath.IsTileFlippedVertically(tuple.Item3),
            //                               TileCenter = new PointF((float)tuple.Item2.TileSize.Width * 0.5f, (float)tuple.Item2.TileSize.Height * 0.5f)
            //                           })
            //     {
            //         List<IntPoint> list = new List<IntPoint>();
            //         SizeF offset = new SizeF(item2.TmxObjectInterface.Position);
            //         PointF[] array = item2.HasPointsInterface.Points.Select((PointF pt) => PointF.Add(pt, offset)).ToArray();
            //         TmxMath.TransformPoints(array, item2.TileCenter, item2.IsFlippedDiagnoally, item2.IsFlippedHorizontally, item2.IsFlippedVertically);
            //         PointF[] array2 = array;
            //         for (int i = 0; i < array2.Length; i++)
            //         {
            //             PointF pointF = array2[i];
            //             float x2 = (float)item2.PositionOnMap.X + pointF.X;
            //             float y2 = (float)item2.PositionOnMap.Y + pointF.Y;
            //             IntPoint item = xfFunc(x2, y2);
            //             list.Add(item);
            //         }
            //         list.Reverse();
            //         clipper.AddPath(list, PolyType.ptSubject, item2.HasPointsInterface.ArePointsClosed());
            //     }
            //     PolyTree polyTree = new PolyTree();
            //     clipper.Execute(ClipType.ctUnion, polyTree, SubjectFillRule, ClipFillRule);

            //     return polyTree;


            ClipperLib.Clipper clipper = new ClipperLib.Clipper();

            // Limit to polygon "type" that matches the collision layer name (unless we are overriding the whole layer to a specific Unity Layer Name)
            bool usingUnityLayerOverride = !String.IsNullOrEmpty(chunk.ParentData.ParentLayer.UnityLayerOverrideName);

            var polygons = from y in Enumerable.Range(0, chunk.Height)
                           from x in Enumerable.Range(0, chunk.Width)
                           let rawTileId = chunk.GetRawTileIdAt(x, y)
                                           where rawTileId != 0
                                           let tileId                       = TmxMath.GetTileIdWithoutFlags(rawTileId)
                                                                   let tile = map.Tiles[tileId]
                                                                              from polygon in tile.ObjectGroup.Objects
                                                                              where (polygon as TmxHasPoints) != null
                                                                              where usingUnityLayerOverride || String.Compare(polygon.Type, chunk.ParentData.ParentLayer.Name, true) == 0
                                                                              select new
            {
                PositionOnMap         = map.GetMapPositionAt(x + chunk.X, y + chunk.Y, tile),
                HasPointsInterface    = polygon as TmxHasPoints,
                TmxObjectInterface    = polygon,
                IsFlippedDiagnoally   = TmxMath.IsTileFlippedDiagonally(rawTileId),
                IsFlippedHorizontally = TmxMath.IsTileFlippedHorizontally(rawTileId),
                IsFlippedVertically   = TmxMath.IsTileFlippedVertically(rawTileId),
                TileCenter            = new PointF(tile.TileSize.Width * 0.5f, tile.TileSize.Height * 0.5f),
            };

            // Add all our polygons to the Clipper library so it can reduce all the polygons to a (hopefully small) number of paths
            foreach (var poly in polygons)
            {
                // Create a clipper library polygon out of each and add it to our collection
                ClipperPolygon clipperPolygon = new ClipperPolygon();

                // Our points may be transformed due to tile flipping/rotation
                // Before we transform them we put all the points into local space relative to the tile
                SizeF    offset            = new SizeF(poly.TmxObjectInterface.Position);
                PointF[] transformedPoints = poly.HasPointsInterface.Points.Select(pt => PointF.Add(pt, offset)).ToArray();

                // Now transform the points relative to the tile
                TmxMath.TransformPoints(transformedPoints, poly.TileCenter, poly.IsFlippedDiagnoally, poly.IsFlippedHorizontally, poly.IsFlippedVertically);

                foreach (var pt in transformedPoints)
                {
                    float x = poly.PositionOnMap.X + pt.X;
                    float y = poly.PositionOnMap.Y + pt.Y;

                    ClipperLib.IntPoint point = xfFunc(x, y);
                    clipperPolygon.Add(point);
                }

                // Because of Unity's cooridnate system, the winding order of the polygons must be reversed
                clipperPolygon.Reverse();

                // Add the "subject"
                clipper.AddPath(clipperPolygon, ClipperLib.PolyType.ptSubject, poly.HasPointsInterface.ArePointsClosed());
            }

            ClipperLib.PolyTree solution = new ClipperLib.PolyTree();
            clipper.Execute(ClipperLib.ClipType.ctUnion, solution, LayerClipper.SubjectFillRule, LayerClipper.ClipFillRule);
            return(solution);
        }
Exemplo n.º 40
0
        //---------------------------------------------------------------------------
        private void DrawBitmap(bool justClip = false)
        {
            if (!justClip)
            {
                if (rbTest2.Checked)
                    GenerateAustPlusRandomEllipses((int)nudCount.Value);
                else
                    GenerateRandomPolygon((int)nudCount.Value);
            }

            Cursor.Current = Cursors.WaitCursor;
            Graphics newgraphic;
            newgraphic = Graphics.FromImage(mybitmap);
            newgraphic.SmoothingMode = SmoothingMode.AntiAlias;
            newgraphic.Clear(Color.White);

            GraphicsPath path = new GraphicsPath();
            if (rbNonZero.Checked) path.FillMode = FillMode.Winding;

            //draw subjects ...
            foreach (Polygon pg in subjects)
            {
                PointF[] pts = PolygonToPointFArray(pg, scale);
                path.AddPolygon(pts);
                pts = null;
            }
            Pen myPen = new Pen(Color.FromArgb(196, 0xC3, 0xC9, 0xCF), (float)0.6);
            SolidBrush myBrush = new SolidBrush(Color.FromArgb(127, 0xDD, 0xDD, 0xF0));
            newgraphic.FillPath(myBrush, path);
            newgraphic.DrawPath(myPen, path);
            path.Reset();

            //draw clips ...
            if (rbNonZero.Checked) path.FillMode = FillMode.Winding;
            foreach (Polygon pg in clips)
            {
                PointF[] pts = PolygonToPointFArray(pg, scale);
                path.AddPolygon(pts);
                pts = null;
            }
            myPen.Color = Color.FromArgb(196, 0xF9, 0xBE, 0xA6);
            myBrush.Color = Color.FromArgb(127, 0xFF, 0xE0, 0xE0);
            newgraphic.FillPath(myBrush, path);
            newgraphic.DrawPath(myPen, path);

            //do the clipping ...
            if ((clips.Count > 0 || subjects.Count > 0) && !rbNone.Checked)
            {
                Polygons solution2 = new Polygons();
                Clipper c = new Clipper();
                c.AddPolygons(subjects, PolyType.ptSubject);
                c.AddPolygons(clips, PolyType.ptClip);
                exSolution.Clear();
                solution.Clear();
                bool succeeded = c.Execute(GetClipType(), solution, GetPolyFillType(), GetPolyFillType());
                if (succeeded)
                {
                    myBrush.Color = Color.Black;
                    path.Reset();

                    //It really shouldn't matter what FillMode is used for solution
                    //polygons because none of the solution polygons overlap.
                    //However, FillMode.Winding will show any orientation errors where
                    //holes will be stroked (outlined) correctly but filled incorrectly  ...
                    path.FillMode = FillMode.Winding;

                    //or for something fancy ...
                    if (nudOffset.Value != 0)
                        solution2 = Clipper.OffsetPolygons(solution, (double)nudOffset.Value * scale, JoinType.jtMiter);
                    else
                        solution2 = new Polygons(solution);
                    foreach (Polygon pg in solution2)
                    {
                        PointF[] pts = PolygonToPointFArray(pg, scale);
                        if (pts.Count() > 2)
                            path.AddPolygon(pts);
                        pts = null;
                    }
                    myBrush.Color = Color.FromArgb(127, 0x66, 0xEF, 0x7F);
                    myPen.Color = Color.FromArgb(255, 0, 0x33, 0);
                    myPen.Width = 1.0f;
                    newgraphic.FillPath(myBrush, path);
                    newgraphic.DrawPath(myPen, path);

                    //now do some fancy testing ...
                    Font f = new Font("Arial", 8);
                    SolidBrush b = new SolidBrush(Color.Navy);
                    double subj_area = 0, clip_area = 0, int_area = 0, union_area = 0;
                    c.Clear();
                    c.AddPolygons(subjects, PolyType.ptSubject);
                    c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType());
                    foreach (Polygon pg in solution2) subj_area += Clipper.Area(pg);
                    c.Clear();
                    c.AddPolygons(clips, PolyType.ptClip);
                    c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType());
                    foreach (Polygon pg in solution2) clip_area += Clipper.Area(pg);
                    c.AddPolygons(subjects, PolyType.ptSubject);
                    c.Execute(ClipType.ctIntersection, solution2, GetPolyFillType(), GetPolyFillType());
                    foreach (Polygon pg in solution2) int_area += Clipper.Area(pg);
                    c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType());
                    foreach (Polygon pg in solution2) union_area += Clipper.Area(pg);

                    StringFormat lftStringFormat = new StringFormat();
                    lftStringFormat.Alignment = StringAlignment.Near;
                    lftStringFormat.LineAlignment = StringAlignment.Near;
                    StringFormat rtStringFormat = new StringFormat();
                    rtStringFormat.Alignment = StringAlignment.Far;
                    rtStringFormat.LineAlignment = StringAlignment.Near;
                    Rectangle rec = new Rectangle(pictureBox1.ClientSize.Width - 108,
                        pictureBox1.ClientSize.Height - 116, 104, 106);
                    newgraphic.FillRectangle(new SolidBrush(Color.FromArgb(196, Color.WhiteSmoke)), rec);
                    newgraphic.DrawRectangle(myPen, rec);
                    rec.Inflate(new Size(-2, 0));
                    newgraphic.DrawString("Areas", f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 14));
                    newgraphic.DrawString("subj: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((subj_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 12));
                    newgraphic.DrawString("clip: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((clip_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 12));
                    newgraphic.DrawString("intersect: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((int_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 12));
                    newgraphic.DrawString("---------", f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("s + c - i: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString(((subj_area + clip_area - int_area) / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("---------", f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("union: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((union_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("---------", f, b, rec, rtStringFormat);
                } //end if succeeded
            } //end if something to clip

            pictureBox1.Image = mybitmap;
            newgraphic.Dispose();
            Cursor.Current = Cursors.Default;
        }
Exemplo n.º 41
0
		public static Polygons GetCorrectedWinding(this Polygons polygonsToFix)
		{
			polygonsToFix = Clipper.CleanPolygons(polygonsToFix);
			Polygon boundsPolygon = new Polygon();
			IntRect bounds = Clipper.GetBounds(polygonsToFix);
			bounds.left -= 10;
			bounds.bottom += 10;
			bounds.right += 10;
			bounds.top -= 10;

			boundsPolygon.Add(new IntPoint(bounds.left, bounds.top));
			boundsPolygon.Add(new IntPoint(bounds.right, bounds.top));
			boundsPolygon.Add(new IntPoint(bounds.right, bounds.bottom));
			boundsPolygon.Add(new IntPoint(bounds.left, bounds.bottom));

			Clipper clipper = new Clipper();

			clipper.AddPaths(polygonsToFix, PolyType.ptSubject, true);
			clipper.AddPath(boundsPolygon, PolyType.ptClip, true);

			PolyTree intersectionResult = new PolyTree();
			clipper.Execute(ClipType.ctIntersection, intersectionResult);

			Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult);

			return outputPolygons;
		}
Exemplo n.º 42
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Clipper"/> class.
 /// </summary>
 public Clipper()
 {
     this.innerClipper = new ClipperLib.Clipper();
 }
Exemplo n.º 43
0
        /// <summary>
        /// Performs the Boolean Operations from the Clipper Library
        /// </summary>
        /// <param name="clipType"></param>
        /// <param name="subject"></param>
        /// <param name="clip"></param>
        /// <param name="simplifyPriorToBooleanOperation"></param>
        /// <param name="scale"></param>
        /// <param name="fillMethod"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        private static List <Polygon> BooleanViaClipper(PolyFillType fillMethod, ClipType clipType, IEnumerable <Polygon> subject,
                                                        IEnumerable <Polygon> clip = null, bool subjectIsClosed = true, bool clipIsClosed = true)
        {
            //Remove any polygons that are only a line.
            //subject = subject.Where(p => p.Count > 2);
            //clip = clip?.Where(p => p.Count > 2);
            var simplifyPriorToBooleanOperation = true;

            if (simplifyPriorToBooleanOperation)
            {
                //subject = subject.Select(p=>SimplifyFuzzy(p));
                subject = subject.Select(p => Simplify(p, 0.0000003));
            }
            if (simplifyPriorToBooleanOperation)
            {
                //If not null
                //clip = clip?.Select(p => SimplifyFuzzy(p));
                clip = clip?.Select(p => Simplify(p, 0.0000003));
            }
            if (!subject.Any())
            {
                if (clip == null || !clip.Any())
                {
                    return(new List <Polygon>());
                }
                //Use the clip as the subject if this is a union operation and the clip is not null.
                if (clipType == ClipType.ctUnion)
                {
                    subject = clip;
                    clip    = null;
                }
            }
            var subjectAll = subject.SelectMany(p => p.AllPolygons).ToList();

            var clipperSolution = new List <List <IntPoint> >();
            //Convert Points (TVGL) to IntPoints (Clipper)
            var clipperSubject =
                subjectAll.Select(loop => loop.Vertices.Select(point => new IntPoint(point.X * scale, point.Y * scale)).ToList()).ToList();

            //Setup Clipper
            var clipper = new ClipperLib.Clipper()
            {
                StrictlySimple = true
            };

            clipper.AddPaths(clipperSubject, PolyType.ptSubject, subjectIsClosed);

            if (clip != null)
            {
                var clipAll = clip.SelectMany(p => p.AllPolygons).ToList();

                var clipperClip =
                    clipAll.Select(loop => loop.Vertices.Select(point => new IntPoint(point.X * scale, point.Y * scale)).ToList()).ToList();
                clipper.AddPaths(clipperClip, PolyType.ptClip, clipIsClosed);
            }

            //Begin an evaluation
            var result = clipper.Execute(clipType, clipperSolution, fillMethod, fillMethod);

            if (!result)
            {
                throw new Exception("Clipper Union Failed");
            }

            //Convert back to points and return solution
            var solution = clipperSolution.Select(clipperPath => new Polygon(clipperPath.Select(point => new Vector2(point.X / scale, point.Y / scale))));

            return(solution.CreateShallowPolygonTrees(true));
        }