///// <summary> ///// OLH: One Level Hole; we assume that there is only one polygon in pPolyTree ///// </summary> ///// <param name="pPolyTree"></param> ///// <returns></returns> ///// <remarks></remarks> //public static CPolygon GenerateOLHCpgByPolyTree(PolyTree pPolyTree, int intID) //{ // if (pPolyTree.ChildCount > 1) // { // throw new ArgumentOutOfRangeException("there should be no more than 1 polygon!"); // } // return GenerateOLHCpgEbByPolyNode(pPolyTree.Childs[0], intID); //} public static IEnumerable <CPolygon> GenerateCpgEbByPolyTree(PolyTree polyTree, int intID = -1, bool blnReverse = true) { foreach (var polynode in GetOneLevelPolyNode(polyTree)) { yield return(GenerateOLHCpgEbByPolyNode(polynode, intID, blnReverse)); } }
/// <summary> /// Note: Containment definition varies by hole vs terrain: Containment for holes /// does not include the hole edge, containment for terrain includes the terrain edge. /// This is important, else e.g. knockback + terrain push placing an entity on an edge /// would potentially infinite loop. /// </summary> public static void PickDeepestPolynodeGivenHoleShapePolytree(this PolyTree polyTree, IntVector2 query, out PolyNode result, out bool isHole) { polyTree.AssertIsContourlessRootHolePunchResult(); PolyNode current = polyTree; while (true) { // current is a hole of a hole's shape PolyNode match; // if we fail to find the first child land node border-inclusively containing the query point if (!current.Childs.TryFindFirst(child => Clipper.PointInPolygon(new IntVector2(query.X, query.Y), child.Contour) == PolygonContainmentResult.InPolygon, out match)) { result = current; isHole = true; return; } // next off, current is land of a hole's shape current = match; // If we fail to find a child hole border-excludingly containing the query point if (!current.Childs.TryFindFirst(child => Clipper.PointInPolygon(new IntVector2(query.X, query.Y), child.Contour) != PolygonContainmentResult.OutsidePolygon, out match)) { result = current; isHole = false; return; } // next off, current is a hole of a hole's shape current = match; } }
private static IEnumerable <Paths> GetOneLevelPathsEbFromPolyTree(PolyTree polyTree) { foreach (var polynode in GetOneLevelPolyNode(polyTree)) { yield return(GetPathsFromOnelevelPolyNode(polynode)); } }
private List <List <IntPoint> > ClipToRooms(List <IntPoint> roomFootprint, bool allowSplit) { _clipper.Clear(); _clipper.AddPath(roomFootprint, PolyType.ptSubject, true); _clipper.AddPaths(_rooms.Select(r => r.OuterFootprint.Select(ToPoint).ToList()).ToList(), PolyType.ptClip, true); var solution = new PolyTree(); _clipper.Execute(ClipType.ctDifference, solution); //Rooms with holes are not supported if (HasHole(solution)) { //Rooms with holes are not supported (issue #166 - Will Not Fix) return(new List <List <IntPoint> >()); } var shapes = Clipper.ClosedPathsFromPolyTree(solution); if (shapes.Count > 1 && !allowSplit) { return(new List <List <IntPoint> >()); } return(shapes); }
public static Polygons GetCorrectedWinding(this Polygons polygonsToFix) { polygonsToFix = Clipper.CleanPolygons(polygonsToFix); var boundsPolygon = new Polygon(); IntRect bounds = Clipper.GetBounds(polygonsToFix); bounds.minX -= 10; bounds.minY -= 10; bounds.maxY += 10; bounds.maxX += 10; boundsPolygon.Add(new IntPoint(bounds.minX, bounds.minY)); boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.minY)); boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.maxY)); boundsPolygon.Add(new IntPoint(bounds.minX, bounds.maxY)); var clipper = new Clipper(); clipper.AddPaths(polygonsToFix, PolyType.ptSubject, true); clipper.AddPath(boundsPolygon, PolyType.ptClip, true); var intersectionResult = new PolyTree(); clipper.Execute(ClipType.ctIntersection, intersectionResult); Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult); return(outputPolygons); }
public List <DTPolygon> Subtract(DTPolygon subject, DTPolygon clippingPolygon) { if (!DTUtility.BoundsCheck(subject.Contour, clippingPolygon.Contour)) { // There is no overlap at all, so output a copy of the subject polygon return(new List <DTPolygon>() { new DTPolygon(new List <Vector2>(subject.Contour)) }); } clipper.Clear(); // Add subject polygon paths clipper.AddPath(subject.Contour.ToIntPointList(), PolyType.ptSubject, true); foreach (var hole in subject.Holes) { clipper.AddPath(hole.ToIntPointList(), PolyType.ptSubject, true); } // Add clipping polygon paths clipper.AddPath(clippingPolygon.Contour.ToIntPointList(), PolyType.ptClip, true); foreach (var hole in clippingPolygon.Holes) { clipper.AddPath(hole.ToIntPointList(), PolyType.ptClip, true); } // Execute subtraction and store result in a PolyTree so that we can easily identify holes PolyTree clipperOutput = new PolyTree(); clipper.Execute(ClipType.ctDifference, clipperOutput, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero); // Convert Polytree into list of DTPolygons return(clipperOutput.ToDTPolygons()); }
protected internal virtual Path FilterStrokePath(Path path, Matrix ctm, float lineWidth, int lineCapStyle, int lineJoinStyle, float miterLimit, LineDashPattern lineDashPattern) { JoinType joinType = GetJoinType(lineJoinStyle); EndType endType = GetEndType(lineCapStyle); if (lineDashPattern != null) { if (IsZeroDash(lineDashPattern)) { return(new Path()); } if (!IsSolid(lineDashPattern)) { path = ApplyDashPattern(path, lineDashPattern); } } ClipperOffset offset = new ClipperOffset(miterLimit, PdfCleanUpProcessor.ArcTolerance * PdfCleanUpProcessor.FloatMultiplier); AddPath(offset, path, joinType, endType); PolyTree resultTree = new PolyTree(); offset.Execute(ref resultTree, lineWidth * PdfCleanUpProcessor.FloatMultiplier / 2); return(FilterFillPath(ConvertToPath(resultTree), ctm, PathPaintingRenderInfo.NONZERO_WINDING_RULE)); }
public void GenerateBase(Polygons polygonShape, double bottomWithoutBase) { if (polygonShape != null && polygonShape.Select(p => p.Count).Sum() > 3) { Polygons polysToOffset = new Polygons(); switch (BaseType) { case BaseTypes.Rectangle: polysToOffset.Add(GetBoundingPolygon(polygonShape)); break; case BaseTypes.Circle: polysToOffset.Add(GetBoundingCircle(polygonShape)); break; case BaseTypes.Outline: PolyTree polyTreeForBase = GetPolyTree(polygonShape); foreach (PolyNode polyToOffset in polyTreeForBase.Childs) { polysToOffset.Add(polyToOffset.Contour); } break; } if (polysToOffset.Count > 0) { Polygons basePolygons; if (BaseType == BaseTypes.Outline && InfillAmount > 0) { basePolygons = Offset(polysToOffset, (BaseSize + InfillAmount) * scalingForClipper); basePolygons = Offset(basePolygons, -InfillAmount * scalingForClipper); } else { basePolygons = Offset(polysToOffset, BaseSize * scalingForClipper); } basePolygons = ClipperLib.Clipper.CleanPolygons(basePolygons, 10); VertexStorage rawVectorShape = basePolygons.PolygonToPathStorage(); var vectorShape = new VertexSourceApplyTransform(rawVectorShape, Affine.NewScaling(1.0 / scalingForClipper)); var baseObject = new Object3D() { Mesh = VertexSourceToMesh.Extrude(vectorShape, zHeight: ExtrusionHeight) }; Children.Add(baseObject); baseObject.Mesh.Translate(new Vector3(0, 0, -ExtrusionHeight + bottomWithoutBase)); } else { // clear the mesh Mesh = null; } } }
private int FixAndSetShapes(IEnumerable <IShape> outlines, IEnumerable <IShape> holes) { Clipper clipper = new Clipper(); // add the outlines and the holes to clipper, scaling up from the float source to the int based system clipper uses this.AddPoints(clipper, outlines, PolyType.Subject); this.AddPoints(clipper, holes, PolyType.Clip); PolyTree tree = clipper.Execute(); List <IShape> shapes = new List <IShape>(); List <IPath> paths = new List <IPath>(); // convert the 'tree' back to paths this.ExtractOutlines(tree, shapes, paths); this.shapes = shapes.ToArray(); this.paths = paths.ToArray(); int intersections = 0; foreach (IShape s in this.shapes) { intersections += s.MaxIntersections; } return(intersections); }
/** * Note: this method will close all unclosed subpaths of the passed path. * * @param fillingRule If the subpath is contour, pass any value. */ protected internal Path FilterFillPath(Path path, Matrix ctm, int fillingRule) { path.CloseAllSubpaths(); Clipper clipper = new Clipper(); AddPath(clipper, path); foreach (Rectangle rectangle in rectangles) { Point2D[] transfRectVertices = TransformPoints(ctm, true, GetVertices(rectangle)); AddRect(clipper, transfRectVertices, PolyType.ptClip); } PolyFillType fillType = PolyFillType.pftNonZero; if (fillingRule == PathPaintingRenderInfo.EVEN_ODD_RULE) { fillType = PolyFillType.pftEvenOdd; } PolyTree resultTree = new PolyTree(); clipper.Execute(ClipType.ctDifference, resultTree, fillType, PolyFillType.pftNonZero); return(ConvertToPath(resultTree)); }
public Nav2D(Vector2 leftBottomMapCorner, Vector2 rightUpperMapCorner, float agentRadius, Accuracy accuracy) { if (new Quad(leftBottomMapCorner, rightUpperMapCorner).Area() < _MinWorldAreaSize) { throw new Exception("World is too small! The world minimum area is 1 m^2"); } _LeftBottomMapCorner = leftBottomMapCorner; _RightUpperMapCorner = rightUpperMapCorner; AgentRadius = agentRadius; _Obstacles = new List <NavElement>(); _Surfaces = new List <NavElement>(); _ClipperOffset = new ClipperOffset(); _ExitExtendPoints = new List <List <IntPoint> >(); elementsGroups = new List <ElementsGroup>(); _Connections = new Dictionary <Tuple <NavPoint, NavPoint>, ConnectionData>(); _NavPoints = new List <NavPoint>(); _TmpGroupedElements = new HashSet <NavElement>(); _TmpLocalGroupedElements = new List <NavElement>(); _TmpCollidedElements = new Queue <NavElement>(); _TmpSearchList = new List <NavElement>(); _TmpElementsGroups = new Dictionary <uint, ElementsGroup>(); elementsGroupPull = new Stack <ElementsGroup>(); clipper = new Clipper(); polyTree = new PolyTree(); QuadTree = new QuadTree <NavElement>(10, 6, GetQuadTreeBounds(_LeftBottomMapCorner, _RightUpperMapCorner)); _Accuracy = accuracy; _NextElementsGroupId = 1; }
public SimplifiedGeometryShape(List <List <Vector2> > polygons, PolyTree tree) { this.polygons = polygons; this.tree = tree; Triangulated = false; }
internal void ConvertSupportIntersectionsToPolyTrees(float sliceHeight, AtumPrinter selectedPrinter) { this.SupportPolyTrees[0] = new List <PolyTree>() { PolyTree.FromListOfSupportIntersectionsUsingPolygons(sliceHeight, this._supportIntersectionsZ, selectedPrinter) }; }
private Polygons FixWinding(Polygons polygonsToPathAround) { polygonsToPathAround = Clipper.CleanPolygons(polygonsToPathAround); Polygon boundsPolygon = new Polygon(); IntRect bounds = Clipper.GetBounds(polygonsToPathAround); bounds.minX -= 10; bounds.maxY += 10; bounds.maxX += 10; bounds.minY -= 10; boundsPolygon.Add(new IntPoint(bounds.minX, bounds.minY)); boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.minY)); boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.maxY)); boundsPolygon.Add(new IntPoint(bounds.minX, bounds.maxY)); Clipper clipper = new Clipper(); clipper.AddPaths(polygonsToPathAround, 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); }
public Polygon Clip(Polygon clippingPoly, ClipType type = ClipType.ctIntersection) { List <List <IntPoint> > list = new List <List <IntPoint> >(); list.Add(GetPath()); List <List <IntPoint> > list2 = new List <List <IntPoint> >(); list2.Add(clippingPoly.GetPath()); Clipper clipper = new Clipper(0); PolyTree polytree = new PolyTree(); clipper.AddPaths(list, PolyType.ptSubject, true); clipper.AddPaths(list2, PolyType.ptClip, true); clipper.Execute(type, polytree, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd); List <List <IntPoint> > list3 = Clipper.PolyTreeToPaths(polytree); if (list3.Count > 0) { List <Vector2> list4 = new List <Vector2>(); for (int i = 0; i < list3[0].Count; i++) { List <Vector2> list5 = list4; IntPoint intPoint = list3[0][i]; float x = (float)intPoint.X * 0.0001f; IntPoint intPoint2 = list3[0][i]; list5.Add(new Vector2(x, (float)intPoint2.Y * 0.0001f)); } return(new Polygon(list4)); } return(null); }
private static IEnumerable <PolyNode> GetOneLevelPolyNode(PolyTree polyTree) { var QueueNode = new Queue <PolyNode>(polyTree.Childs); while (QueueNode.Count > 0) { var polynode = QueueNode.Dequeue(); yield return(polynode); //do it recursively if (polynode.ChildCount > 0) { foreach (var holepolynode in polynode.Childs) { if (holepolynode.ChildCount > 0) { foreach (var exteriorpolynode in holepolynode.Childs) { QueueNode.Enqueue(exteriorpolynode); } } } } } }
internal void CalcSlicesIndexes(Material selectedMaterial, AtumPrinter selectedPrinter, int sliceIndexModulus = 1) { this.CalcSliceIndexes(selectedMaterial, true); var firstSliceIndex = 0; var firstSliceHeight = 0f; foreach (var sliceHeight in this.SliceIndexes.Keys) { if (sliceHeight > this.BottomPoint) { firstSliceHeight = sliceHeight; break; } firstSliceIndex++; } var lastSliceHeight = this.SliceIndexes.Last().Key; Parallel.ForEach(MagsAIEngine.SliceHeightsWithModulus.Keys, sliceHeightAsync => { var sliceHeight = sliceHeightAsync; var sliceIndex = firstSliceIndex; if (sliceHeight >= firstSliceHeight && sliceHeight <= lastSliceHeight) { var sliceAngledContours = new PolyTree();; var sliceContours = this.GetSliceContours(sliceIndex, sliceHeight, selectedPrinter, selectedMaterial, out sliceAngledContours); ModelContours.TryAdd(sliceHeight, sliceContours); ModelAngledContours.TryAdd(sliceHeight, sliceAngledContours); sliceIndex++; } }); }
/// <summary> /// Constructs the geometric differences between this Line and the supplied Polygons. /// </summary> /// <param name="diffs">The list of intersecting Polygons.</param> /// <returns> /// Returns a list of Lines representing the subtraction of the Lines intersecting the supplied list of Polygons. /// </returns> public static List <Line> Differences(this Line line, IList <Polygon> diffs) { var thisPath = LineToClipper(line); var polyPaths = new List <List <IntPoint> >(); foreach (Polygon poly in diffs) { polyPaths.Add(Shaper.PolygonToClipper(poly)); } Clipper clipper = new Clipper(); clipper.AddPath(thisPath, PolyType.ptSubject, false); clipper.AddPaths(polyPaths, PolyType.ptClip, true); var solution = new PolyTree(); clipper.Execute(ClipType.ctDifference, solution, PolyFillType.pftEvenOdd); var soLines = Clipper.OpenPathsFromPolyTree(solution); var lines = new List <Line>(); foreach (List <IntPoint> path in soLines) { lines.Add(LineFromClipper(path.ToList())); } return(lines); }
/// <summary> /// This method clips a list of lines inside polygons /// </summary> /// <param name="lines">The list of lines to clip</param> /// <param name="polygons">The polygons in which to clip</param> /// <returns>The list of lines clipped to intersect with the polygons</returns> public static List <LineSegment> clipLinesInPolygons(Polygons lines, Polygons polygons) { List <LineSegment> lineList = new List <LineSegment>(); Clipper clipper = new Clipper(); clipper.AddPaths(lines, PolyType.ptSubject, false); clipper.AddPaths(polygons, PolyType.ptClip, true); PolyTree result = new PolyTree(); clipper.Execute(ClipType.ctIntersection, result); foreach (PolyNode node in result.Childs) { if (node.Contour.Count == 2) { //Make sure the infill line is longer than at least double the nozzlewidth LineSegment line = new LineSegment(node.Contour[0], node.Contour[1]); if (line.length < Global.Values.nozzleWidth * 2) { continue; } lineList.Add(line); } } return(lineList); }
private Polygons FixWinding(Polygons polygonsToPathAround) { polygonsToPathAround = Clipper.CleanPolygons(polygonsToPathAround); Polygon boundsPolygon = new Polygon(); IntRect bounds = Clipper.GetBounds(polygonsToPathAround); 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(polygonsToPathAround, PolyType.ptSubject, true); clipper.AddPath(boundsPolygon, PolyType.ptClip, true); PolyTree intersectionResult = new PolyTree(); clipper.Execute(ClipType.ctIntersection, intersectionResult); Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult); Clipper.ReversePaths(outputPolygons); return(outputPolygons); }
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); }
public static PolygonList Execute(PolygonList a, PolygonList b, ClipType clipType) { PolyTree solution = new PolyTree(); Clipper clipper = new Clipper(); PolygonList a_flat = new PolygonList(); _addRecursive(a, ref a_flat); PolygonList b_flat = new PolygonList(); _addRecursive(b, ref b_flat); clipper.AddPaths(a_flat, PolyType.ptSubject, true); clipper.AddPaths(b_flat, PolyType.ptClip, true); clipper.Execute(clipType, solution); PolygonList solutionPolygons = new PolygonList(); foreach (PolyNode node in solution.Childs) { Polygon polygon = new Polygon(node); solutionPolygons.AddRange(polygon.Flatten()); } return(solutionPolygons); }
public Slice(Slice fromSlice) { this.plane = fromSlice.plane; this.transform = fromSlice.transform; this.inverseTransform = fromSlice.inverseTransform; this.polyTree = fromSlice.polyTree; }
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); }
private void CutExtra(List <IntPoint> poly, List <IntPoint> extraClipShape, PolyTree result) { this.clipper.Clear(); this.clipper.AddPolygon(poly, PolyType.ptSubject); this.clipper.AddPolygon(extraClipShape, PolyType.ptClip); result.Clear(); this.clipper.Execute(ClipType.ctIntersection, result, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero); }
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); }
public void Execute() { PolyTree solution = new PolyTree(); m_Clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftNonZero, PolyFillType.pftEvenOdd); AddConvexPolygonsFromSolution(solution); CombineLines(); }
public virtual void GetTotalSizeDifferentPolyNodeTest() { PolyTree tree = new PolyTree(); IList <PolyNode> allPolys = tree.m_AllPolys; allPolys.Add(new PolyNode()); allPolys.Add(new PolyNode()); tree.AddChild(new PolyNode()); NUnit.Framework.Assert.AreEqual(1, tree.Total); }
public virtual void GetFistChildInPolyTreeTest() { PolyTree tree = new PolyTree(); PolyNode firstChild = new PolyNode(); PolyNode secondChild = new PolyNode(); tree.AddChild(firstChild); tree.AddChild(secondChild); NUnit.Framework.Assert.AreSame(firstChild, tree.GetFirst()); }
internal void ConvertModelBleedingIntersectionsToPolyTrees(float sliceHeight, AtumPrinter selectedPrinter, bool usePixelsAsValues = true) { var angledSides = new List <List <PolylineWithNormal> >(); var wallSides = new List <List <PolylineWithNormal> >(); var facingDownSides = new List <PolyNode>(); this.ModelBleedingPolyTrees[0] = PolyTree.FromListOfModelIntersectionsUsingPolygons(sliceHeight, this._modelBleedingZIntersections, selectedPrinter, null, null, out angledSides, out wallSides, usePixelsAsValues); }
public static void GenerateLinePaths(Polygons in_outline, ref Polygons result, int lineSpacing, int infillExtendIntoPerimeter_um, double rotation, long rotationOffset = 0) { if (in_outline.Count > 0) { Polygons outlines = in_outline.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); result.AddRange(newSegments); } } }
protected internal Path FilterStrokePath(Path sourcePath, Matrix ctm, float lineWidth, int lineCapStyle, int lineJoinStyle, float miterLimit, LineDashPattern lineDashPattern) { Path path = sourcePath; JoinType joinType = GetJoinType(lineJoinStyle); EndType endType = GetEndType(lineCapStyle); if (lineDashPattern != null && !lineDashPattern.IsSolid()) { path = ApplyDashPattern(path, lineDashPattern); } ClipperOffset offset = new ClipperOffset(miterLimit, PdfCleanUpProcessor.ArcTolerance * PdfCleanUpProcessor.FloatMultiplier); IList<Subpath> degenerateSubpaths = AddPath(offset, path, joinType, endType); PolyTree resultTree = new PolyTree(); offset.Execute(ref resultTree, lineWidth * PdfCleanUpProcessor.FloatMultiplier / 2); Path offsetedPath = ConvertToPath(resultTree); if (degenerateSubpaths.Count > 0) { if (endType == EndType.etOpenRound) { IList<Subpath> circles = ConvertToCircles(degenerateSubpaths, lineWidth / 2); offsetedPath.AddSubpaths(circles); } else if (endType == EndType.etOpenSquare && lineDashPattern != null) { IList<Subpath> squares = ConvertToSquares(degenerateSubpaths, lineWidth, sourcePath); offsetedPath.AddSubpaths(squares); } } return FilterFillPath(offsetedPath, ctm, PathPaintingRenderInfo.NONZERO_WINDING_RULE); }
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; }
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); }
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; }
public static List<Polygons> CreateLayerOutlines(this Polygons polygons, LayerOpperation opperation) { List<Polygons> ret = new List<Polygons>(); Clipper clipper = new Clipper(); PolyTree resultPolyTree = new PolyTree(); clipper.AddPaths(polygons, PolyType.ptSubject, true); if (opperation == LayerOpperation.UnionAll) { clipper.Execute(ClipType.ctUnion, resultPolyTree, PolyFillType.pftNonZero, PolyFillType.pftNonZero); } else { clipper.Execute(ClipType.ctUnion, resultPolyTree); } polygons._processPolyTreeNode(resultPolyTree, ret); return ret; }
/** * Note: this method will close all unclosed subpaths of the passed path. * * @param fillingRule If the subpath is contour, pass any value. */ protected internal Path FilterFillPath(Path path, Matrix ctm, int fillingRule) { path.CloseAllSubpaths(); Clipper clipper = new Clipper(); AddPath(clipper, path); foreach (Rectangle rectangle in rectangles) { Point2D[] transfRectVertices = TransformPoints(ctm, true, GetVertices(rectangle)); AddRect(clipper, transfRectVertices, PolyType.ptClip); } PolyFillType fillType = PolyFillType.pftNonZero; if (fillingRule == PathPaintingRenderInfo.EVEN_ODD_RULE) { fillType = PolyFillType.pftEvenOdd; } PolyTree resultTree = new PolyTree(); clipper.Execute(ClipType.ctDifference, resultTree, fillType, PolyFillType.pftNonZero); return ConvertToPath(resultTree); }
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); } } }
private static Path ConvertToPath(PolyTree result) { Path path = new Path(); PolyNode node = result.GetFirst(); while (node != null) { AddContour(path, node.Contour, !node.IsOpen); node = node.GetNext(); } return path; }
protected internal virtual Path FilterStrokePath(Path path, Matrix ctm, float lineWidth, int lineCapStyle, int lineJoinStyle, float miterLimit, LineDashPattern lineDashPattern) { JoinType joinType = GetJoinType(lineJoinStyle); EndType endType = GetEndType(lineCapStyle); if (lineDashPattern != null) { if (IsZeroDash(lineDashPattern)) { return new Path(); } if (!IsSolid(lineDashPattern)) { path = ApplyDashPattern(path, lineDashPattern); } } ClipperOffset offset = new ClipperOffset(miterLimit, PdfCleanUpProcessor.ArcTolerance * PdfCleanUpProcessor.FloatMultiplier); AddPath(offset, path, joinType, endType); PolyTree resultTree = new PolyTree(); offset.Execute(ref resultTree, lineWidth * PdfCleanUpProcessor.FloatMultiplier / 2); return FilterFillPath(ConvertToPath(resultTree), ctm, PathPaintingRenderInfo.NONZERO_WINDING_RULE); }
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); }