상속: PolyNode
예제 #1
0
    GameObject SpawnSegment(bool leftSide)
    {
        clipType = leftSide ? ClipperLib.ClipType.ctIntersection : ClipperLib.ClipType.ctDifference;
        ClipperLib.PolyTree tree = new ClipperLib.PolyTree();
        clip.Execute(clipType, tree, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero);

        List <Vector3> verts = new List <Vector3>();
        List <Vector3> norms = new List <Vector3>();
        List <Vector2> uvs   = new List <Vector2>();
        List <int>     faces = new List <int>();
        int            idx   = 0;

        foreach (ClipperLib.PolyNode child in tree.Childs)
        {
            if (!child.IsHole)
            {
                renderTree(child, verts, norms, uvs, faces, ref idx);
            }
        }

        if (verts.Count == 0)
        {
            return(null);
        }

        Mesh mesh = new Mesh();

        mesh.Clear();
        mesh.vertices  = verts.ToArray();
        mesh.uv        = uvs.ToArray();
        mesh.normals   = norms.ToArray();
        mesh.triangles = faces.ToArray();

        GameObject obj = GameObject.Instantiate <GameObject>(sliceInfo.slicePrefab);

        obj.GetComponent <MeshFilter>().mesh       = mesh;
        obj.GetComponent <MeshRenderer>().material = sliceInfo.renderObject.material;

        Transform t = obj.transform;

        t.localPosition = transform.localPosition;
        t.localRotation = transform.localRotation;
        t.localScale    = transform.localScale;

        Vector3 min = new Vector3(1000, 1000, 0);
        Vector3 max = new Vector3(-1000, -1000, 0);

        foreach (Vector3 v in verts)
        {
            min = Vector3.Min(min, v);
            max = Vector3.Max(max, v);
        }

        BoxCollider2D c = obj.GetComponent <BoxCollider2D>();

        c.offset = (max + min) / 2;
        c.size   = max - min;

        return(obj);
    }
예제 #2
0
        public SimplifiedGeometryShape(List<List<Vector2>> polygons, PolyTree tree)
        {
            this.polygons = polygons;
            this.tree = tree;

            Triangulated = false;
        }
예제 #3
0
        public static PolyTree Combine(List<List<ControlPoint>> polygons)
        {
            Clipper.Clear();
            Clipper.AddPaths(polygons, PolyType.ptSubject, true);
            Clipper.AddPaths(polygons, PolyType.ptClip, true);

            var tree = new PolyTree();
            Clipper.Execute(ClipType.ctUnion, tree, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
            return tree;
        }
예제 #4
0
        public static List<List<Vector2>> Simplify(List<Vector2> polygon, FillMode fillMode, out PolyTree tree)
        {
            Clipper.Clear();
            Clipper.AddPath(polygon, PolyType.ptSubject, true);
            Clipper.AddPath(polygon, PolyType.ptClip, true);

            tree = new PolyTree();
            PolyFillType fillType = fillMode.ToPolyFillType();
            Clipper.Execute(ClipType.ctUnion, tree, fillType, fillType);
            return Clipper.ClosedPathsFromPolyTree(tree);
        }
예제 #5
0
        public static List<List<Vector2>> Combine(List<List<Vector2>> subjectPolygons, List<List<Vector2>> clippingPolygons,
                                                  FillMode subjectFillMode, FillMode clipFillMode, CombineMode combineMode, out PolyTree tree)
        {
            Clipper.Clear();
            Clipper.AddPaths(subjectPolygons, PolyType.ptSubject, true);
            Clipper.AddPaths(clippingPolygons, PolyType.ptClip, true);

            tree = new PolyTree();
            Clipper.Execute(combineMode.ToClipType(), tree, subjectFillMode.ToPolyFillType(), clipFillMode.ToPolyFillType());
            return Clipper.ClosedPathsFromPolyTree(tree);
        }
예제 #6
0
        public static List<List<Vector2>> Outline(List<Vector2> polygon, FillMode fillMode, bool closed, StrokeStyle strokeStyle, float strokeWidth, out PolyTree tree)
        {
            List<List<Vector2>> simplified = Clipper.SimplifyPolygon(polygon, fillMode.ToPolyFillType());

            Offsetter.Clear();
            Offsetter.MiterLimit = strokeStyle.MiterLimit;
            Offsetter.AddPaths(simplified, (JoinType)strokeStyle.LineJoin, closed ? EndType.etClosedLine : strokeStyle.CapStyle.ToEndType());

            tree = new PolyTree();
            Offsetter.Execute(ref tree, strokeWidth / 2);
            return Clipper.ClosedPathsFromPolyTree(tree);
        }
        private XElement CreateCollisionElementForLayer(TmxLayer layer)
        {
            // Collision elements look like this
            // (Can also have EdgeCollider2Ds)
            //      <GameOject name="Collision">
            //        <PolygonCollider2D>
            //          <Path>list of points</Path>
            //          <Path>another list of points</Path>
            //        </PolygonCollider2D>
            //      </GameOject>

            LayerClipper.TransformPointFunc xfFunc =
                delegate(float x, float y)
            {
                // Transform point to Unity space
                Vector3D pointUnity3d = PointFToUnityVector_NoScale(new PointF(x, y));
                IntPoint point        = new IntPoint(pointUnity3d.X, pointUnity3d.Y);
                return(point);
            };

            LayerClipper.ProgressFunc progFunc =
                delegate(string prog)
            {
                Program.WriteLine(prog);
            };

            ClipperLib.PolyTree solution = LayerClipper.ExecuteClipper(this.tmxMap, layer, xfFunc, progFunc);

            // Add our polygon and edge colliders
            List <XElement> polyColliderElements = new List <XElement>();

            AddPolygonCollider2DElements(Clipper.ClosedPathsFromPolyTree(solution), polyColliderElements);
            AddEdgeCollider2DElements(Clipper.OpenPathsFromPolyTree(solution), polyColliderElements);

            if (polyColliderElements.Count() == 0)
            {
                // No collisions on this layer
                return(null);
            }

            XElement gameObjectCollision =
                new XElement("GameObject",
                             new XAttribute("name", "Collision"),
                             polyColliderElements);

            return(gameObjectCollision);
        }
예제 #8
0
        //------------------------------------------------------------------------------

        public void Execute(ref PolyTree solution, double delta)
        {
            solution.Clear();
            FixOrientations();
            DoOffset(delta);

            //now clean up 'corners' ...
            Clipper clpr = new Clipper();

            clpr.AddPaths(m_destPolys, PolyType.ptSubject, true);
            if (delta > 0)
            {
                clpr.Execute(ClipType.ctUnion, solution,
                             PolyFillType.pftPositive, PolyFillType.pftPositive);
            }
            else
            {
                IntRect         r     = Clipper.GetBounds(m_destPolys);
                List <IntPoint> outer = new List <IntPoint>(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.AddPath(outer, PolyType.ptSubject, true);
                clpr.ReverseSolution = true;
                clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                //remove the outer PolyNode rectangle ...
                if (solution.ChildCount == 1 && solution.Childs[0].ChildCount > 0)
                {
                    PolyNode outerNode = solution.Childs[0];
                    solution.Childs.Capacity    = outerNode.ChildCount;
                    solution.Childs[0]          = outerNode.Childs[0];
                    solution.Childs[0].m_Parent = solution;
                    for (int i = 1; i < outerNode.ChildCount; i++)
                    {
                        solution.AddChild(outerNode.Childs[i]);
                    }
                }
                else
                {
                    solution.Clear();
                }
            }
        }
예제 #9
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);
				}
			}
		}
예제 #10
0
        public void Execute(ref PolyTree solution, double delta)
        {
            solution.Clear();
            FixOrientations();
            DoOffset(delta);
            Clipper clipper = new Clipper(0);

            clipper.AddPaths(m_destPolys, PolyType.ptSubject, true);
            if (delta > 0.0)
            {
                clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
            }
            else
            {
                IntRect         bounds = ClipperBase.GetBounds(m_destPolys);
                List <IntPoint> list   = new List <IntPoint>(4);
                list.Add(new IntPoint(bounds.left - 10, bounds.bottom + 10));
                list.Add(new IntPoint(bounds.right + 10, bounds.bottom + 10));
                list.Add(new IntPoint(bounds.right + 10, bounds.top - 10));
                list.Add(new IntPoint(bounds.left - 10, bounds.top - 10));
                clipper.AddPath(list, PolyType.ptSubject, true);
                clipper.ReverseSolution = true;
                clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                if (solution.ChildCount == 1 && solution.Childs[0].ChildCount > 0)
                {
                    PolyNode polyNode = solution.Childs[0];
                    solution.Childs.Capacity    = polyNode.ChildCount;
                    solution.Childs[0]          = polyNode.Childs[0];
                    solution.Childs[0].m_Parent = solution;
                    for (int i = 1; i < polyNode.ChildCount; i++)
                    {
                        solution.AddChild(polyNode.Childs[i]);
                    }
                }
                else
                {
                    solution.Clear();
                }
            }
        }
예제 #11
0
        public static List <Polyline> Boolean(ClipType clipType, IEnumerable <Polyline> polyA, IEnumerable <Polyline> polyB,
                                              Plane pln, double tolerance, bool evenOddFilling)
        {
            var clipper      = new Clipper();
            var polyfilltype = PolyFillType.pftEvenOdd;

            if (!evenOddFilling)
            {
                polyfilltype = PolyFillType.pftNonZero;
            }

            foreach (var plA in polyA)
            {
                clipper.AddPath(plA.ToPath2D(pln, tolerance), PolyType.ptSubject, plA.IsClosed);
            }

            foreach (var plB in polyB)
            {
                clipper.AddPath(plB.ToPath2D(pln, tolerance), PolyType.ptClip, true);
            }

            var polytree = new PolyTree();

            clipper.Execute(clipType, polytree, polyfilltype, polyfilltype);

            var output = new List <Polyline>();

            // ReSharper disable once LoopCanBeConvertedToQuery
            foreach (var pn in polytree.Iterate())
            {
                if (pn.Contour.Count > 1)
                {
                    output.Add(pn.Contour.ToPolyline(pln, tolerance, !pn.IsOpen));
                }
            }

            return(output);
        }
예제 #12
0
        public static PolyTree Clip_PolyTree(Paths subjpaths, bool blnSubjClosed,
                                             Paths clippaths, bool blnClipClosed, ClipType pClipType)
        {
            Clipper pClipper = new Clipper();

            //var blnadd = pClipper.AddPaths(subjpaths, PolyType.ptSubject, blnSubjClosed);
            //var blnad2 = pClipper.AddPaths(clippaths, PolyType.ptClip, blnClipClosed);

            if (pClipper.AddPaths(subjpaths, PolyType.ptSubject, blnSubjClosed) == false ||
                pClipper.AddPaths(clippaths, PolyType.ptClip, blnClipClosed) == false)
            {
                throw new ArgumentException("failed to add paths!");
            }

            PolyTree clippedPolyTree = new ClipperLib.PolyTree();

            if (pClipper.Execute(pClipType, clippedPolyTree) == false)
            {
                throw new ArgumentException("failed to cut!");
            }

            return(clippedPolyTree);
        }
예제 #13
0
        public List<DelaunayTriangle> TriangulateComplex(
         PolyTree polyTree,
         bool ignoreFills = false, bool ignoreHoles = true)
        {
            PolyNode rootNode;
             if (polyTree.Total == 0) {
            Console.WriteLine(0);
            rootNode = new PolyNode();
             } else {
            rootNode = polyTree.GetFirst().Parent;
             }

             // Equivalent to rootNode.Contour = bounds;
             var contourField = rootNode.GetType().GetField("m_polygon", BindingFlags.Instance | BindingFlags.NonPublic);
             if (contourField == null) {
            throw new Exception("Could not find field contour backing field.");
             }
             contourField.SetValue(rootNode, kTriangulatorBounds);

             var result = new List<DelaunayTriangle>();
             int i = 0;
             for (var currentNode = rootNode; currentNode != null; currentNode = currentNode.GetNext()) {
            if ((ignoreHoles && currentNode.IsHole) || (ignoreFills && !currentNode.IsHole)) continue;
            var polyline = DownscalePolygon(currentNode.Contour);
            var finalPolygon = new Polygon(polyline);
            foreach (var child in currentNode.Childs) {
               var shrunkContour = EdgeShrink(child.Contour);
               var holePoints = DownscalePolygon(shrunkContour);
               var holePoly = new Polygon(holePoints);
               finalPolygon.AddHole(holePoly);
            }
            P2T.Triangulate(finalPolygon);
            result.AddRange(finalPolygon.Triangles);
             }
             return result;
        }
예제 #14
0
파일: Slice.cs 프로젝트: JackTing/PathCAM
 private Paths PolyTreeToPolygons(PolyTree tree)
 {
     Paths p = new Paths();
     PolyNode n = tree.GetFirst();
     while (null != n)
     {
         p.Add(n.Contour);
         n = n.GetNext();
     }
     return p;
 }
예제 #15
0
파일: Slice.cs 프로젝트: JackTing/PathCAM
 private PolyTree PolygonsToPolyTree(Paths polygons)
 {
     var tree = new PolyTree();
     Clipper c = new Clipper();
     c.Clear();
     c.AddPaths(polygons, PolyType.ptSubject, true);
     c.Execute(ClipType.ctUnion, tree);
     return tree;
 }
예제 #16
0
파일: Slice.cs 프로젝트: JackTing/PathCAM
 private void Init(IEnumerable<LineStrip> lines, Plane plane, PolyFillType pft = PolyFillType.pftEvenOdd)
 {
     transform = plane.CreateMatrix();
     transform = Matrix4.Mult(transform, Matrix4.CreateScale(scale));
     inverseTransform = Matrix4.Invert(transform);
     this.plane = plane;
     polyTree = GetPolyTree(lines, pft);
 }
예제 #17
0
파일: Slice.cs 프로젝트: JackTing/PathCAM
        private PolyTree GetPolyTree(IEnumerable<LineStrip> lines, PolyFillType pft)
        {
            Paths polygons = new Paths();
            Clipper c = new Clipper();
            c.Clear();

            foreach (var line in lines)
            {
                polygons.Add(LineStripToPolygon(line));
            }

            polygons = Clipper.SimplifyPolygons(polygons, pft);
            c.AddPaths(polygons, PolyType.ptSubject, true);
            PolyTree tree = new PolyTree();
            c.Execute(ClipType.ctUnion, tree);
            return tree;
        }
예제 #18
0
파일: Slice.cs 프로젝트: JackTing/PathCAM
        public void Union(Slice other)
        {
            Clipper c = new Clipper();
            c.Clear();
            c.AddPaths(Clipper.PolyTreeToPaths(polyTree), PolyType.ptSubject, true);
            c.AddPaths(Clipper.PolyTreeToPaths(other.polyTree), PolyType.ptClip, true);

            polyTree = new PolyTree();
            c.Execute(ClipType.ctUnion, polyTree);
        }
예제 #19
0
파일: Slice.cs 프로젝트: JackTing/PathCAM
        public void SubtractFrom(Slice other)
        {
            Clipper c = new Clipper();
            c.Clear();
            c.AddPaths(PolyTreeToPolygons(other.polyTree), PolyType.ptSubject, true);
            c.AddPaths(PolyTreeToPolygons(polyTree), PolyType.ptClip, true);

            polyTree = new PolyTree();
            c.Execute(ClipType.ctDifference, polyTree);
        }
예제 #20
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);
        }
예제 #21
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);
        }
예제 #22
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;
		}
예제 #23
0
		public static Polygons CreateLineIntersections(this Polygons polygons, Polygons other)
		{
			Clipper clipper = new Clipper();

			clipper.AddPaths(other, PolyType.ptSubject, false);
			clipper.AddPaths(polygons, PolyType.ptClip, true);

			PolyTree clippedLines = new PolyTree();

			clipper.Execute(ClipType.ctIntersection, clippedLines);

			return Clipper.OpenPathsFromPolyTree(clippedLines);
		}
예제 #24
0
        //------------------------------------------------------------------------------

        public static void PolyTreeToPolygons(PolyTree polytree, Polygons polygons)
        {
            polygons.Clear();
            polygons.Capacity = polytree.Total;
            AddPolyNodeToPolygons(polytree, polygons);
        }
예제 #25
0
        //------------------------------------------------------------------------------

        public bool Execute(ClipType clipType, PolyTree polytree)
        {
            return Execute(clipType, polytree,
                PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
        }
예제 #26
0
        /// <summary>
        /// Offsets the specified polylines.
        /// </summary>
        /// <param name="polylines">A list of polylines</param>
        /// <param name="openFilletType">Optional: line endtype (Butt, Square, Round)</param>
        /// <param name="closedFilltetType">Optional: join type: Round, Miter (uses miter parameter) or Square</param>
        /// <param name="plane">Plane to project the polylines to</param>
        /// <param name="tolerance">Tolerance: Cutoff point. Eg. point {1.245; 9.244351; 19.3214} with precision {0.1} will be cut
        /// off to {1.2; 9.2; 19.3}.</param>
        /// <param name="distance">Distances to offset set of shapes.</param>
        /// <param name="miter">Miter deterimines how long narrow spikes can become before they are cut off: A miter setting of 2
        /// means not longer than 2 times the offset distance. A miter of 25 will give big spikes.</param>
        /// <param name="arcTolerance">The arc tolerance.</param>
        /// <param name="outContour">The out contour.</param>
        /// <param name="outHoles">The out holes.</param>
        public static void Offset(IEnumerable <Polyline> polylines, List <OpenFilletType> openFilletType,
                                  List <ClosedFilletType> closedFilltetType, Plane plane, double tolerance, IEnumerable <double> distance,
                                  double miter, double arcTolerance, out List <List <Polyline> > outContour, out List <List <Polyline> > outHoles, EndType endType = default)
        {
            outContour = new List <List <Polyline> >();
            outHoles   = new List <List <Polyline> >();

            /*
             * iEndType: How to handle open ended polygons.
             * Open				Closed
             * etOpenSquare		etClosedLine    (fill inside & outside)
             * etOpenRound			etClosedPolygon (fill outside only)
             * etOpenButt
             *
             * See: http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/EndType.htm
             */

            /*
             * jtJoinType
             * How to fill angles of closed polygons
             * jtRound: Round
             * jtMiter: Square with variable distance
             * jtSquare: Square with fixed distance (jtMiter = 1)
             */

            var cOffset = new ClipperOffset(miter, arcTolerance);
            var i       = 0;

            foreach (var pl in polylines)
            {
                var et = EndType.etOpenButt;
                var jt = JoinType.jtSquare;
                if (pl.IsClosed)
                {
                    et = EndType.etClosedLine;
                }
                else if (openFilletType.Count != 0)
                {
                    var oft = IndexOrLast(openFilletType, i);
                    switch (oft)
                    {
                    case OpenFilletType.Butt:
                        et = EndType.etOpenButt;
                        break;

                    case OpenFilletType.Round:
                        et = EndType.etOpenRound;
                        break;

                    case OpenFilletType.Square:
                        et = EndType.etOpenSquare;
                        break;
                    }
                }
                else
                {
                    et = EndType.etOpenButt;
                }

                if (closedFilltetType.Count != 0)
                {
                    var cft = IndexOrLast(closedFilltetType, i);
                    switch (cft)
                    {
                    case ClosedFilletType.Miter:
                        jt = JoinType.jtMiter;
                        break;

                    case ClosedFilletType.Round:
                        jt = JoinType.jtRound;
                        break;

                    case ClosedFilletType.Square:
                        jt = JoinType.jtSquare;
                        break;
                    }
                }
                else
                {
                    jt = JoinType.jtSquare;
                }
                if (endType != default)
                {
                    et = endType;
                }
                cOffset.AddPath(pl.ToPath2D(plane, tolerance), jt, et);
                i++;
            }

            foreach (var offsetDistance in distance)
            {
                var tree = new PolyTree();
                cOffset.Execute(ref tree, offsetDistance / tolerance);

                var holes    = new List <Polyline>();
                var contours = new List <Polyline>();
                foreach (var path in tree.Iterate())
                {
                    if (path.Contour.Count == 0)
                    {
                        continue;
                    }
                    Polyline polyline = path.Contour.ToPolyline(plane, tolerance, !path.IsOpen);
                    if (path.IsHole)
                    {
                        holes.Add(polyline);
                    }
                    else
                    {
                        contours.Add(polyline);
                    }
                }

                outContour.Add(contours);
                outHoles.Add(holes);
            }
        }
예제 #27
0
파일: Form1.cs 프로젝트: sverreeh/clipper
        //------------------------------------------------------------------------------
        private void BmpUpdateNeeded()
        {
            const int textOffset = 20;

              if (bmpGraphics == null) return;
              FillMode fm = (mEvenOdd.Checked ? FillMode.Alternate : FillMode.Winding);
              bmpGraphics.Clear(Color.White);

              //draw the subject and clip paths ...
              Paths openPaths = new Paths();
              Paths closedPaths = new Paths();
              Paths clipPaths = new Paths();
              //sort the paths into open and closed subjects and (closed) clips ...
              foreach (MultiPath mp2 in allPaths)
            if (mp2.RefID == CLIP) clipPaths.Add(mp2.Flatten());
            else if (mp2.IsClosed) closedPaths.Add(mp2.Flatten());
            else openPaths.Add(mp2.Flatten());

              DrawPath(bmpGraphics, openPaths, false, 0x0, 0xFFAAAAAA, fm, 1.0);
              DrawPath(bmpGraphics, closedPaths, true, 0x0, 0xFFAAAAAA, fm, 1.0);
              DrawPath(bmpGraphics, clipPaths, true, 0x10FF6600, 0x99FF6600, fm, 1.0);

              if (cbShowCoords.Checked)
              {
            Font fnt = new Font("Arial", 8);
            SolidBrush brush = new SolidBrush(Color.Navy);
            foreach (MultiPath mp2 in allPaths)
            {
              foreach (MultiPathSegment mps in mp2)
            foreach (IntPoint ip in mps)
            {
              IntPoint ip2 = new IntPoint(ip.X / scale, ip.Y / scale);
              string coords = ip2.X.ToString() + "," + ip2.Y.ToString();
              bmpGraphics.DrawString(coords, fnt, brush, ip2.X - textOffset, ip2.Y - textOffset, null);
            }
            }
            fnt.Dispose();
            brush.Dispose();
              }

              //for the active path, draw control buttons and control lines too ...
              MultiPath activePath = GetActivePath();
              if (activePath != null && activePath.Count > 0)
              {
            foreach (MultiPathSegment mps in activePath)
            {
              CurveType pt = mps.curvetype;
              if (pt == CurveType.CubicBezier)
            DrawBezierCtrlLines(bmpGraphics, mps, 0xFFEEEEEE);
              else if (pt == CurveType.QuadBezier)
            DrawBezierCtrlLines(bmpGraphics, mps, 0xFFEEEEEE);
            }

            DrawButtons(bmpGraphics, activePath);

            //display the coords of a moving button ...
            if (MovingButtonIdx >= 0)
            {
              Font f = new Font("Arial", 8);
              SolidBrush b = new SolidBrush(Color.Navy);
              IntPoint ip = MovingButtonSeg[MovingButtonIdx];
              ip.X = (int)(ip.X / scale); ip.Y = (int)(ip.Y / scale);
              string coords = ip.X.ToString() + "," + ip.Y.ToString();
              bmpGraphics.DrawString(coords, f, b, ip.X - textOffset, ip.Y - textOffset, null);
              f.Dispose();
              b.Dispose();
            }
              }

              //if there's any clipping to be done, do it here ...
              if (!mNone.Checked && GetCurrentSubjMultiPath() != null && GetCurrentClipMultiPath() != null)
              {
            PolyFillType pft = (mEvenOdd.Checked ? PolyFillType.pftEvenOdd : PolyFillType.pftNonZero);
            ClipType ct;
            if (mUnion.Checked) ct = ClipType.ctUnion;
            else if (mDifference.Checked) ct = ClipType.ctDifference;
            else if (mXor.Checked) ct = ClipType.ctXor;
            else ct = ClipType.ctIntersection;

            //CLIPPING DONE HERE ...
            Clipper c = new Clipper();
            c.ZFillFunction = MultiPaths.ClipCallback; //set the callback function (called at intersections)
            if (openPaths.Count > 0)
              c.AddPaths(openPaths, PolyType.ptSubject, false);
            if (closedPaths.Count > 0)
              c.AddPaths(closedPaths, PolyType.ptSubject, true);
            c.AddPaths(clipPaths, PolyType.ptClip, true);
            PolyTree polytree = new PolyTree();

            Paths solution;
            c.Execute(ct, polytree, pft, pft); //EXECUTE CLIP !!!!!!!!!!!!!!!!!!!!!!
            solution = Clipper.ClosedPathsFromPolyTree(polytree);
            if (!cbReconstCurve.Checked)
              DrawPath(bmpGraphics, solution, true, 0x2033AA00, 0xFF33AA00, fm, 2.0);
            solution = Clipper.OpenPathsFromPolyTree(polytree);
            if (!cbReconstCurve.Checked)
              DrawPath(bmpGraphics, solution, false, 0x0, 0xFF33AA00, fm, 2.0);

            //now to demonstrate reconstructing beziers & arcs ...
            if (cbReconstCurve.Checked)
            {
              PolyNode pn = polytree.GetFirst();
              while (pn != null)
              {
            if (pn.IsHole || pn.Contour.Count < 2)
            {
              pn = pn.GetNext();
              continue;
            }

            if (pn.ChildCount > 0)
              throw new Exception("Sorry, this demo doesn't currently handle holes");

            //and reconstruct each curve ...
            MultiPath reconstructedMultiPath = allPaths.Reconstruct(pn.Contour);

            if (cbShowCtrls.Enabled && cbShowCtrls.Checked)
            {
              //show (small) buttons on the red reconstructed path too ...
              DrawButtons(bmpGraphics, reconstructedMultiPath, true);
            }

            //now to show how accurate these reconstructed (control) paths are,
            //we flatten them (drawing them red) so we can compare them with
            //the original flattened paths (light gray) ...
            Paths paths = new Paths();
            paths.Add(reconstructedMultiPath.Flatten());
            DrawPath(bmpGraphics, paths, !pn.IsOpen, 0x18FF0000, 0xFFFF0000, fm, 2.0);

            pn = pn.GetNext();
              }
            }
            //else //shows just how many vertices there are in flattened paths ...
            //{
            //  solution = Clipper.PolyTreeToPaths(polytree);
            //  MultiPath flatMultiPath = new MultiPath(null, 0, false);
            //  foreach (Path p in solution)
            //    flatMultiPath.NewMultiPathSegment(PathType.Line, p);
            //  DrawButtons(bmpGraphics, flatMultiPath, true);
            //}
              }

              string s = "  ";
              if (mIntersection.Checked) s += "INTERSECTION";
              else if (mUnion.Checked) s += "UNION";
              else if (mDifference.Checked) s += "DIFFERENCE";
              else if (mXor.Checked) s += "XOR";
              else s += "NO CLIPPING";
              s += " with ";
              if (mEvenOdd.Checked) s += "EVENODD fill.";
              else s += "NONZERO fill.";
              toolStripStatusLabel2.Text = s;
              displayPanel.Invalidate();
        }
예제 #28
0
파일: Slice.cs 프로젝트: JackTing/PathCAM
 public void RemoveHoles(float maxPerimiter)
 {
     Paths keep = new Paths();
     PolyNode node = polyTree.GetFirst();
     while (node != null)
     {
         if (node.IsHole && node.ChildCount == 0)
         {
             var line = LineStripFromPolygon(node.Contour);
             float length = line.Length(LineStrip.Type.Closed);
             if (length < maxPerimiter)
             {
                 // Remove it
             }
             else
             {
                 keep.Add(node.Contour);
             }
         }
         else
         {
             keep.Add(node.Contour);
         }
         node = node.GetNext();
     }
     Clipper c = new Clipper();
     c.Clear();
     c.AddPaths(keep, PolyType.ptSubject, true);
     polyTree = new PolyTree();
     c.Execute(ClipType.ctUnion, polyTree);
 }
예제 #29
0
		public static void GenerateHexLinePaths(Polygons in_outline, ref Polygons result, int lineSpacing, int infillExtendIntoPerimeter_um, double rotationDegrees, int layerIndex)
		{
			int extraRotationAngle = 0;
			if (in_outline.Count > 0)
			{
				Polygons outlines = in_outline.Offset(infillExtendIntoPerimeter_um);
				if (outlines.Count > 0)
				{
					int perIncrementOffset = (int)(lineSpacing * Math.Sqrt(3) / 2 + .5);
					PointMatrix matrix = new PointMatrix(-(rotationDegrees + extraRotationAngle)); // 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;
					boundary.min.Y = ((boundary.min.Y / perIncrementOffset) - 2) * perIncrementOffset;
					boundary.max.X += lineSpacing;
					boundary.max.Y += perIncrementOffset;
					Polygons unclipedPatern = new Polygons();

					foreach (IntPoint startPoint in StartPositionIterator(boundary, lineSpacing, layerIndex))
					{
						Polygon attachedLine = new Polygon();
						foreach (IntPoint center in IncrementPositionIterator(startPoint, boundary, lineSpacing, layerIndex))
						{
							// what we are adding are the little plusses that define the points
							//        | top
							//        |
							//        /\ center
							//   left/  \ right
							//
							IntPoint left = center + new IntPoint(-lineSpacing / 2, -perIncrementOffset / 3);
							IntPoint right = center + new IntPoint(lineSpacing / 2, -perIncrementOffset / 3);
							IntPoint top = center + new IntPoint(0, perIncrementOffset * 2 / 3);

							switch (layerIndex % 3)
							{
								case 0: // left to right
									attachedLine.Add(left); attachedLine.Add(center);
									attachedLine.Add(center); attachedLine.Add(right);
									unclipedPatern.Add(new Polygon() { top, center });
									break;

								case 1: // left to top
									attachedLine.Add(left); attachedLine.Add(center);
									attachedLine.Add(center); attachedLine.Add(top);
									unclipedPatern.Add(new Polygon() { center, right });
									break;

								case 2: // top to right
									attachedLine.Add(top); attachedLine.Add(center);
									attachedLine.Add(center); attachedLine.Add(right);
									unclipedPatern.Add(new Polygon() { left, center });
									break;
							}
						}
						if (attachedLine.Count > 0)
						{
							unclipedPatern.Add(attachedLine);
						}
					}

					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((rotationDegrees + extraRotationAngle));
					newSegments.ApplyMatrix(inversematrix);

					result.AddRange(newSegments);
				}
			}
		}
예제 #30
0
        //------------------------------------------------------------------------------

        public override bool Execute(ClipType clipType, PolyTree polytree, Paths Open, FillRule ft = FillRule.EvenOdd)
        {
            return(false); //unsupported
        }
예제 #31
0
        //------------------------------------------------------------------------------

        public bool Execute(ClipType clipType, PolyTree polytree,
            PolyFillType subjFillType, PolyFillType clipFillType)
        {
            if (m_ExecuteLocked) return false;
            m_ExecuteLocked = true;
            m_SubjFillType = subjFillType;
            m_ClipFillType = clipFillType;
            m_ClipType = clipType;
            m_UsingPolyTree = true;
            bool succeeded = ExecuteInternal();
            //build the return polygons ...
            if (succeeded) BuildResult2(polytree);
            m_ExecuteLocked = false;
            return succeeded;
        }
예제 #32
0
      //------------------------------------------------------------------------------

      public static Paths OpenPathsFromPolyTree(PolyTree polytree)
      {
        Paths result = new Paths();
        result.Capacity = polytree.ChildCount;
        for (int i = 0; i < polytree.ChildCount; i++)
          if (polytree.Childs[i].IsOpen)
            result.Add(polytree.Childs[i].Contour);
        return result;
      }
예제 #33
0
        //------------------------------------------------------------------------------

        private void BuildResult2(PolyTree polytree)
        {
            polytree.Clear();

            //add each output polygon/contour to polytree ...
            polytree.m_AllPolys.Capacity = m_PolyOuts.Count;
            for (int i = 0; i < m_PolyOuts.Count; i++)
            {
                OutRec outRec = m_PolyOuts[i];
                int cnt = PointCount(outRec.pts);
                if (cnt < 3) continue;
                FixHoleLinkage(outRec);
                PolyNode pn = new PolyNode();
                polytree.m_AllPolys.Add(pn);
                outRec.polyNode = pn;
                pn.m_polygon.Capacity = cnt;
                OutPt op = outRec.pts;
                for (int j = 0; j < cnt; j++)
                {
                    pn.m_polygon.Add(op.pt);
                    op = op.prev;
                }
            }

            //fixup PolyNode links etc ...
            polytree.m_Childs.Capacity = m_PolyOuts.Count;
            for (int i = 0; i < m_PolyOuts.Count; i++)
            {
                OutRec outRec = m_PolyOuts[i];
                if (outRec.polyNode == null) continue;
                if (outRec.FirstLeft == null)
                    polytree.AddChild(outRec.polyNode);
                else
                    outRec.FirstLeft.polyNode.AddChild(outRec.polyNode);
            }
        }
예제 #34
0
      //------------------------------------------------------------------------------

      public static Paths ClosedPathsFromPolyTree(PolyTree polytree)
      {
        Paths result = new Paths();
        result.Capacity = polytree.Total;
        AddPolyNodeToPaths(polytree, NodeType.ntClosed, result);
        return result;
      }
예제 #35
0
		public static Polygons CreateLineDifference(this Polygons linePolygons, Polygons removePolygons)
		{
			Clipper clipper = new Clipper();

			clipper.AddPaths(linePolygons, PolyType.ptSubject, false);
			clipper.AddPaths(removePolygons, PolyType.ptClip, true);

			PolyTree clippedLines = new PolyTree();

			clipper.Execute(ClipType.ctDifference, clippedLines);

			return Clipper.OpenPathsFromPolyTree(clippedLines);
		}
예제 #36
0
파일: Slice.cs 프로젝트: JackTing/PathCAM
 public Slice(Slice fromSlice)
 {
     this.plane = fromSlice.plane;
     this.transform = fromSlice.transform;
     this.inverseTransform = fromSlice.inverseTransform;
     this.polyTree = fromSlice.polyTree;
 }
예제 #37
0
		public static List<Polygons> ProcessIntoSeparatIslands(this Polygons polygons)
		{
			List<Polygons> ret = new List<Polygons>();
			Clipper clipper = new Clipper();
			PolyTree resultPolyTree = new PolyTree();
			clipper.AddPaths(polygons, PolyType.ptSubject, true);
			clipper.Execute(ClipType.ctUnion, resultPolyTree);

			polygons.ProcessPolyTreeNodeIntoSeparatIslands(resultPolyTree, ret);
			return ret;
		}
예제 #38
0
파일: Slice.cs 프로젝트: JackTing/PathCAM
        /// <summary>
        /// Create a slice from an open path with the given width
        /// </summary>
        /// <param name="path"></param>
        /// <param name="width"></param>
        /// <param name="plane"></param>
        public Slice(LineStrip path, float width, Plane plane, bool closed = false)
        {
            this.plane = plane;
            transform = plane.CreateMatrix();
            transform = Matrix4.Mult(transform, Matrix4.CreateScale(scale));
            inverseTransform = Matrix4.Invert(transform);
            polyTree = new PolyTree();

            ClipperOffset co = new ClipperOffset();
            co.ArcTolerance = scale * 0.0001f;
            if (closed)
            {
                co.AddPath(LineStripToPolygon(path), JoinType.jtRound, EndType.etClosedLine);
            }
            else
            {
                co.AddPath(LineStripToPolygon(path), JoinType.jtRound, EndType.etOpenRound);
            }
            co.Execute(ref this.polyTree, scale * width / 2.0f);
        }
예제 #39
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;
		}
예제 #40
0
파일: Slice.cs 프로젝트: JackTing/PathCAM
 public void Offset(float offset)
 {
     Paths polygons = Clipper.ClosedPathsFromPolyTree(polyTree);
     ClipperOffset co = new ClipperOffset();
     co.ArcTolerance = scale * .0001f;
     co.AddPaths(polygons, JoinType.jtRound, EndType.etClosedPolygon);
     polyTree = new PolyTree();
     Paths offsetPaths = new Paths();
     co.Execute(ref offsetPaths, scale * offset);
     offsetPaths = Clipper.CleanPolygons(offsetPaths, scale * .0001f);
     polyTree = PolygonsToPolyTree(offsetPaths);
 }