Esempio n. 1
0
        public static List <Polyline> Boolean(ClipType clipType, IEnumerable <Polyline> polyA, IEnumerable <Polyline> polyB, Plane pln, double tolerance, bool evenOddFilling)
        {
            Clipper      clipper      = new Clipper(0);
            PolyFillType polyfilltype = PolyFillType.pftEvenOdd;

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

            List <List <IntPoint> > PathsA = new List <List <IntPoint> >();
            List <List <IntPoint> > PathsB = new List <List <IntPoint> >();

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

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

            PolyTree OutputTree = new PolyTree();

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

            List <Polyline> Output = new List <Polyline> ();

            foreach (PolyNode pn in OutputTree.Iterate())
            {
                if (pn.Contour.Count > 1)
                {
                    Output.Add(pn.Contour.ToPolyline(pln, tolerance, !pn.IsOpen));
                }
            }

            return(Output);
        }
Esempio n. 2
0
        public static List <Polyline> Boolean(ClipType clipType, IEnumerable <Polyline> polyA, IEnumerable <Polyline> polyB,
                                              Plane pln, double tolerance, bool evenOddFilling)
        {
            NGonsCore.Clipper642.Clipper clipper = new NGonsCore.Clipper642.Clipper();
            PolyFillType polyfilltype            = PolyFillType.pftEvenOdd;

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

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

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

            PolyTree polytree = new PolyTree();

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

            List <Polyline> output = new List <Polyline>();

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

            return(output);
        }
Esempio n. 3
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)
        {
            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)
             */

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

            foreach (Polyline pl in polylines)
            {
                EndType  et = EndType.etOpenButt;
                JoinType jt = JoinType.jtSquare;
                if (pl.IsClosed)
                {
                    et = EndType.etClosedLine;
                }
                else if (openFilletType.Count != 0)
                {
                    OpenFilletType 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)
                {
                    ClosedFilletType 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;
                }
                cOffset.AddPath(pl.ToPath2D(plane, tolerance), jt, et);
                i++;
            }

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

                List <Polyline> holes    = new List <Polyline>();
                List <Polyline> contours = new List <Polyline>();

                foreach (PolyNode 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);
            }
        }
Esempio n. 4
0
        public override void Calculate()
        {
            ResultPaths = new List <Polyline>();

            if (Stock == null || Stock.Count < 1 || DriveGeometry == null || DriveGeometry.Count < 1)
            {
                throw new Exception("Stock or drive geometry not set!");
            }

            BoundingBox bb = Stock[0].GetBoundingBox(Workplane);

            foreach (Mesh m in Stock)
            {
                bb = BoundingBox.Union(bb, m.GetBoundingBox(Workplane));
            }

            if (bb.IsDegenerate(0.1) > 0)
            {
                throw new Exception("Bounding Box is degenerate.");// return;
            }
            Point3d top    = bb.Center; top.Z = bb.Corner(false, false, false).Z;
            Point3d bottom = bb.Center; bottom.Z = bb.Corner(true, true, true).Z;

            double TotalDepth = top.DistanceTo(bottom);

            int     N            = (int)(Math.Ceiling(Math.Min(MaxDepth, TotalDepth) / Tool.StepDown));
            Plane   CuttingPlane = new Plane(Workplane);
            Point3d top_xform    = new Point3d(top);

            top_xform.Transform(Transform.PlaneToPlane(Plane.WorldXY, Workplane));
            CuttingPlane.Origin = top_xform;

            Tuple <CPaths, CPaths, CPaths> Polygons;

            Polygons = GeneratePolygons(CuttingPlane);

            CPaths Shadow = new CPaths(Polygons.Item1);
            double Area   = PathsArea(Shadow);

            for (int i = 0; i <= N; ++i)
            {
                // for each layer
                CuttingPlane.Origin = CuttingPlane.Origin - Workplane.ZAxis * Tool.StepDown;

                Polygons = GeneratePolygons(CuttingPlane, Shadow);
                if (Polygons == null)
                {
                    throw new Exception("Failed to generate polygons!");
                }

                double AreaNew = PathsArea(Polygons.Item1);
                if (AreaNew > Area)
                {
                    Shadow = new CPaths(Polygons.Item1);
                    Area   = AreaNew;
                }

                ClipperOffset offset = new ClipperOffset(0.25, 0.25);
                offset.AddPaths(Polygons.Item3, JoinType.jtMiter, EndType.etClosedPolygon);

                PolyTree tree = new PolyTree();
                offset.Execute(ref tree, -(Tool.Diameter / 2 + RestHorizontal) / Tolerance);

                CPaths WorkingPaths = new CPaths();

                List <Polyline> Output = new List <Polyline>();

                foreach (PolyNode pn in tree.Iterate())
                {
                    if (pn.Contour.Count > 0)
                    {
                        Output.Add(pn.Contour.ToPolyline(CuttingPlane, Tolerance, true));
                        WorkingPaths.Add(pn.Contour);
                    }
                }

                int counter = 0;
                do
                {
                    offset.Clear();
                    offset.AddPaths(WorkingPaths, JoinType.jtMiter, EndType.etClosedPolygon);
                    offset.Execute(ref tree, -Tool.StepOver / Tolerance);

                    WorkingPaths = new List <List <IntPoint> >();
                    foreach (PolyNode pn in tree.Iterate())
                    {
                        if (pn.Contour.Count > 0)
                        {
                            Output.Add(pn.Contour.ToPolyline(CuttingPlane, Tolerance, true));
                            WorkingPaths.Add(pn.Contour);
                        }
                    }
                    counter++;
                }while (tree.Total > 0 && counter < LOOP_LIMIT);

                ResultPaths.AddRange(Output);
            }

            ShadowPolylines = new List <Polyline>();
            foreach (CPath p in Shadow)
            {
                ShadowPolylines.Add(p.ToPolyline(CuttingPlane, Tolerance, true));
            }
        }