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); }
/// <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); } }