public static List <Polygon> OffsetLinesViaClipper(this IEnumerable <IEnumerable <Vector2> > polylines, double offset, double tolerance)
        {
            if (double.IsNaN(tolerance) || tolerance.IsNegligible())
            {
                tolerance = Constants.BaseTolerance;
            }

            //Convert Points (TVGL) to IntPoints (Clipper)
            var clipperSubject = polylines.Select(line => line.Select(point => new IntPoint(point.X * scale, point.Y * scale)).ToList()).ToList();

            //Setup Clipper
            var clip = new ClipperOffset(2, tolerance * scale);

            clip.AddPaths(clipperSubject, JoinType.jtSquare, EndType.etOpenSquare);

            //Begin an evaluation
            var clipperSolution = new List <List <IntPoint> >();

            clip.Execute(clipperSolution, offset * scale);

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

            return(solution.CreateShallowPolygonTrees(true));
        }
        /// <summary>
        /// Adds all iText
        /// <see cref="iText.Kernel.Geom.Subpath"/>
        /// s of the iText
        /// <see cref="iText.Kernel.Geom.Path"/>
        /// to the
        /// <see cref="ClipperOffset"/>
        /// object with one
        /// note: it doesn't add degenerate subpaths.
        /// </summary>
        /// <returns>
        ///
        /// <see cref="System.Collections.IList{E}"/>
        /// consisting of all degenerate iText
        /// <see cref="iText.Kernel.Geom.Subpath"/>
        /// s of the path.
        /// </returns>
        public static IList <Subpath> AddPath(ClipperOffset offset, Path path, JoinType joinType, EndType endType)
        {
            IList <Subpath> degenerateSubpaths = new List <Subpath>();

            foreach (Subpath subpath in path.GetSubpaths())
            {
                if (subpath.IsDegenerate())
                {
                    degenerateSubpaths.Add(subpath);
                    continue;
                }
                if (!subpath.IsSinglePointClosed() && !subpath.IsSinglePointOpen())
                {
                    EndType et;
                    if (subpath.IsClosed())
                    {
                        // Offsetting is never used for path being filled
                        et = EndType.CLOSED_LINE;
                    }
                    else
                    {
                        et = endType;
                    }
                    IList <Point> linearApproxPoints = subpath.GetPiecewiseLinearApproximation();
                    offset.AddPath(new List <IntPoint>(ConvertToLongPoints(linearApproxPoints)), joinType, et);
                }
            }
            return(degenerateSubpaths);
        }
Exemple #3
0
            private IEnumerable <HPGLLine> OffsetLine(double offset, HPGLLine line)
            {
                var newlines = new List <HPGLLine> {
                    line
                };

                var co        = new ClipperOffset();
                var solution  = new List <List <IntPoint> >();
                var solution2 = new List <List <IntPoint> >();

                solution.Add(line.Commands.Select(x => new IntPoint(_scale * x.PointFrom.X0, _scale * x.PointFrom.Y0)).ToList());
                co.AddPaths(solution, JoinType.jtRound, EndType.etClosedPolygon);
                co.Execute(ref solution2, offset);
                var existingline = line;

                foreach (var polygon in solution2)
                {
                    var         newcmds = new List <HPGLCommand>();
                    HPGLCommand last    = null;

                    foreach (var pt in polygon)
                    {
                        var from = new Point3D {
                            X = pt.X / _scale, Y = pt.Y / _scale
                        };
                        var hpgl = new HPGLCommand {
                            PointFrom = from, CommandType = HPGLCommand.HPGLCommandType.PenDown
                        };
                        newcmds.Add(hpgl);
                        if (last != null)
                        {
                            last.PointTo = from;
                        }
                        last = hpgl;
                    }
                    last.PointTo = newcmds.First().PointFrom;

                    if (existingline == null)
                    {
                        // add new line
                        existingline = new HPGLLine
                        {
                            PreCommands = new List <HPGLCommand>
                            {
                                new HPGLCommand {
                                    CommandType = HPGLCommand.HPGLCommandType.PenUp
                                }
                            },
                            PostCommands = new List <HPGLCommand>(),
                            ParentLine   = line.ParentLine
                        };
                        newlines.Add(existingline);
                    }

                    existingline.Commands = newcmds;
                    existingline.PreCommands.Last(l => l.IsPenCommand).PointTo = newcmds.First().PointFrom;
                    existingline = null;
                }
                return(newlines);
            }
        private static List <Polygon> OffsetViaClipper(IEnumerable <Polygon> polygons, double offset, bool notMiter, double tolerance, double deltaAngle)
        {
            var allPolygons = polygons.SelectMany(polygon => polygon.AllPolygons).ToList();

            if (double.IsNaN(tolerance) || tolerance.IsNegligible())
            {
                var totalLength = allPolygons.Sum(loop => loop.Perimeter);
                tolerance = totalLength * 0.001;
            }
            var joinType = notMiter ? (double.IsNaN(deltaAngle) ? JoinType.jtSquare : JoinType.jtRound) : JoinType.jtMiter;
            //Convert Points (TVGL) to IntPoints (Clipper)
            var clipperSubject = allPolygons.Select(loop => loop.Vertices.Select(point => new IntPoint(point.X * scale, point.Y * scale)).ToList()).ToList();

            //Setup Clipper
            var clip = new ClipperOffset(2, tolerance * scale);

            clip.AddPaths(clipperSubject, joinType, EndType.etClosedPolygon);

            //Begin an evaluation
            var clipperSolution = new List <List <IntPoint> >();

            clip.Execute(clipperSolution, offset * scale);

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

            return(solution.CreateShallowPolygonTrees(true));
        }
Exemple #5
0
        private void InsetPath()
        {
            var path = this.Children.OfType <IPathObject>().FirstOrDefault();

            if (path == null)
            {
                // clear our existing data
                VertexSource = new VertexStorage();
                return;
            }

            var aPolys = path.VertexSource.CreatePolygons();

            var offseter = new ClipperOffset();

            offseter.AddPaths(aPolys, InflatePathObject3D.GetJoinType(OuterStyle), EndType.etClosedPolygon);
            var outerLoops = new List <List <IntPoint> >();

            offseter.Execute(ref outerLoops, OutlineWidth * Ratio * 1000);
            Clipper.CleanPolygons(outerLoops);

            offseter.AddPaths(aPolys, InflatePathObject3D.GetJoinType(InnerStyle), EndType.etClosedPolygon);
            var innerLoops = new List <List <IntPoint> >();

            offseter.Execute(ref innerLoops, -OutlineWidth * (1 - Ratio) * 1000);
            Clipper.CleanPolygons(innerLoops);

            var allLoops = outerLoops;

            allLoops.AddRange(innerLoops);

            VertexSource = allLoops.CreateVertexStorage();

            (VertexSource as VertexStorage).Add(0, 0, ShapePath.FlagsAndCommand.Stop);
        }
        public static IEnumerable <IPolyLine2D> BuildOffset(IEnumerable <IPolygon2D> pgons, double delta, JoinType joinType, EndType endType, double mitterLimit, double maxDiscretizationAngle = 5)
        {
            bool containsCircArc = false;
            var  polygons        = new List <List <IntPoint> >(pgons.Count());

            foreach (var polygon in pgons)
            {
                var p = CreatePolygon(polygon);
                polygons.Add(p);
            }

            if (joinType == JoinType.jtRound || endType == EndType.etOpenRound)
            {
                containsCircArc = true;
            }

            var co = new ClipperOffset(mitterLimit);

            co.AddPaths(polygons, joinType, endType);
            var solution = new List <List <IntPoint> >();

            co.Execute(ref solution, delta * ClipperScale);
            foreach (var poly in solution)
            {
                yield return(CreatePolyline(poly, containsCircArc, maxDiscretizationAngle + 1));
            }
        }
Exemple #7
0
        /// <summary> Creates skeleton lines connected to outer walls and transit polygons. </summary>
        private static List <Wall> CreateConnectedAndTransit(InDoorGeneratorSettings settings,
                                                             List <SkeletonEdge> walls, out List <List <IntPoint> > transitPolygons)
        {
            var offset    = new ClipperOffset();
            var connected = new List <Wall>();
            var paths     = new List <List <IntPoint> >();
            var skeleton  = settings.Skeleton;

            foreach (var wall in walls)
            {
                var start = new IntPoint(wall.Start.X * Scale, wall.Start.Y * Scale);
                var end   = new IntPoint(wall.End.X * Scale, wall.End.Y * Scale);
                if (!wall.IsOuter)
                {
                    paths.Add(new List <IntPoint> {
                        start, end
                    });
                }
                else if (wall.IsSkeleton &&
                         (skeleton.Distances[wall.Start] < settings.HalfTransitAreaWidth ||
                          skeleton.Distances[wall.End] < settings.HalfTransitAreaWidth))
                {
                    var undesired = new Wall(wall.Start, wall.End, false);
                    // TODO do I need this check here?
                    //if (!connected.Contains(undesired))
                    connected.Add(undesired);
                }
            }

            transitPolygons = new List <List <IntPoint> >(1);
            offset.AddPaths(paths, JoinType.jtMiter, EndType.etClosedLine);
            offset.Execute(ref transitPolygons, settings.HalfTransitAreaWidth * Scale);
            return(connected);
        }
        public List <Point> GetPath()
        {
            List <Point>    result    = new List <Point>();
            List <IntPoint> intPoints = new List <IntPoint>();

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

            for (int i = 0; i < linkedBars.Count; i++)
            {
                intPoints.Add(new IntPoint
                {
                    X = Convert.ToInt64(linkedBars[i].X * 100),
                    Y = Convert.ToInt64(linkedBars[i].Y * 100)
                });
            }
            ClipperOffset c = new ClipperOffset();

            c.AddPath(intPoints, JoinType.jtRound, EndType.etClosedPolygon);
            c.Execute(ref solution, (linkedBars[0].diametar + diametar) * 10.0);

            for (int i = 0; i < solution[0].Count; i++)
            {
                result.Add(new Point
                {
                    X = solution[0][i].X / 100.0,
                    Y = solution[0][i].Y / 100.0,
                });
            }

            return(result);
        }
Exemple #9
0
    public static Vector2[] Extend(this Vector2[] points, float radius)
    {
        if (Mathf.Approximately(radius, 0))
        {
            return(points);
        }

        Path polygon = points.ToList().ConvertAll(p => new IntPoint(p.x, p.y));

        Paths solution = new Paths();

        ClipperOffset c = new ClipperOffset();

        c.AddPath(polygon, JoinType.jtRound, EndType.etClosedPolygon);
        c.Execute(ref solution, radius);

        var r = solution.Count > 0 ? solution[0].ConvertAll(p => new Vector2(p.X, p.Y)) : new List <Vector2>();

        if (r.Count > 0)
        {
            r.Add(r[0]);
        }

        return(r.ToArray());
    }
Exemple #10
0
        /// <summary>
        /// Offsets a polygon by the given distance. Counter-clockwise polygons will expand while clockwise polygons
        /// will contract.
        /// </summary>
        public static List <NativeArray <RigidTransform> > OffsetPolygon(
            NativeArray <RigidTransform> samples, float distance, Allocator allocator)
        {
            var solution = new List <List <IntPoint> >();
            var polygon  = FromSamplesToClipper(samples);

            // Clipper uses Even-Odd polygon boolean operations to calculate offsets, so offsetting a clockwise path
            // will result in an expanded offset path rather than a contracted path we're looking for. The offset
            // direction is reversed here to ensure that the orientation of the polygon determines the offset direction.
            var orientation = Clipper.Orientation(polygon);

            if (!orientation)
            {
                distance *= -1;
            }

            var clipperOffset = new ClipperOffset();

            clipperOffset.AddPath(polygon, JoinType.jtRound, EndType.etClosedPolygon);
            clipperOffset.Execute(ref solution, distance * UpScaleFactor);

            if (!orientation)
            {
                for (var i = 0; i < solution.Count; i++)
                {
                    solution[i].Reverse();
                }
            }

            return(ConvertToSamples(solution, allocator));
        }
Exemple #11
0
        private List <Point> Unclip(List <PointF> box, float unclip_ratio)
        {
            List <IntPoint> theCliperPts = new List <IntPoint>();

            foreach (PointF pt in box)
            {
                IntPoint a1 = new IntPoint((int)pt.X, (int)pt.Y);
                theCliperPts.Add(a1);
            }

            float  area     = Math.Abs(SignedPolygonArea(box.ToArray <PointF>()));
            double length   = LengthOfPoints(box);
            double distance = area * unclip_ratio / length;

            ClipperOffset co = new ClipperOffset();

            co.AddPath(theCliperPts, JoinType.jtRound, EndType.etClosedPolygon);
            List <List <IntPoint> > solution = new List <List <IntPoint> >();

            co.Execute(ref solution, distance);
            if (solution.Count == 0)
            {
                return(null);
            }

            List <Point> retPts = new List <Point>();

            foreach (IntPoint ip in solution[0])
            {
                retPts.Add(new Point((int)ip.X, (int)ip.Y));
            }

            return(retPts);
        }
Exemple #12
0
        /// <summary>
        /// Offset this polyline by the specified amount.
        /// </summary>
        /// <param name="offset">The amount to offset.</param>
        /// <param name="endType">The closure type to use on the offset polygon.</param>
        /// <param name="tolerance">An optional tolerance.</param>
        /// <returns>A new closed Polygon offset in all directions by offset from the polyline.</returns>
        public virtual Polygon[] Offset(double offset, EndType endType, double tolerance = Vector3.EPSILON)
        {
            var clipperScale = 1.0 / tolerance;
            var path         = this.ToClipperPath(tolerance);

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

            ClipperLib.EndType clEndType;
            switch (endType)
            {
            case EndType.Butt:
                clEndType = ClipperLib.EndType.etOpenButt;
                break;

            case EndType.ClosedPolygon:
                clEndType = ClipperLib.EndType.etClosedPolygon;
                break;

            case EndType.Square:
            default:
                clEndType = ClipperLib.EndType.etOpenSquare;
                break;
            }
            co.AddPath(path, JoinType.jtMiter, clEndType);
            co.Execute(ref solution, offset * clipperScale);  // important, scale also used here

            var result = new Polygon[solution.Count];

            for (var i = 0; i < result.Length; i++)
            {
                result[i] = solution[i].ToPolygon(tolerance);
            }
            return(result);
        }
Exemple #13
0
        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;
        }
        private static IPolygon Clopening(IPolygon p, Box2 boundingBox, double offset)
        {
            if (p.IsEmpty)
            {
                return(Polygon.Empty);
            }

            double scale           = Math.Max(boundingBox.Width, boundingBox.Height);
            var    fixedPointRange = new Box2(boundingBox.MinCorner, new Vector2(scale, scale));

            var fixedP           = ConvertToFixedPoint(p, fixedPointRange);
            var fixedScaleOffset = offset * _fixedPointRange / scale;

            try
            {
                var offsetter = new ClipperOffset();
                offsetter.AddPaths(fixedP, JoinType.jtMiter, EndType.etClosedPolygon);

                var fixedIntermediate = new ClipperPolygon();
                offsetter.Execute(ref fixedIntermediate, fixedScaleOffset);

                offsetter.Clear();
                offsetter.AddPaths(fixedIntermediate, JoinType.jtMiter, EndType.etClosedPolygon);

                var fixedAnswer = new ClipperPolygon();
                offsetter.Execute(ref fixedAnswer, -fixedScaleOffset);

                return(ConvertToFloatingPoint(fixedAnswer, fixedPointRange));
            }
            catch (Exception e)
            {
                Console.WriteLine("EXCEPTION: {0}", e);
                return(p);
            }
        }
        public static IPolygon Offset(this IPolygon p, double offset)
        {
            if (p.IsEmpty)
            {
                return(Polygon.Empty);
            }

            var    boundingBox     = p.BoundingBox().Offset(Math.Max(offset, 0));
            double scale           = Math.Max(boundingBox.Width, boundingBox.Height);
            var    fixedPointRange = new Box2(boundingBox.MinCorner, new Vector2(scale, scale));

            var fixedP = ConvertToFixedPoint(p, fixedPointRange);

            try
            {
                var offsetter = new ClipperOffset();
                offsetter.AddPaths(fixedP, JoinType.jtMiter, EndType.etClosedPolygon);

                var fixedAnswer = new ClipperPolygon();
                offsetter.Execute(ref fixedAnswer, offset * _fixedPointRange / scale);

                return(ConvertToFloatingPoint(fixedAnswer, fixedPointRange));
            }
            catch (Exception e)
            {
                Console.WriteLine("EXCEPTION: {0}", e);
                return(p);
            }
        }
Exemple #16
0
        private static List <List <Curve> > BuildInsetFilling(List <List <Curve> > plist, LaserGRBL.GrblFile.L2LConf cnf)
        {
            double spacing             = cnf.res / cnf.fres;
            List <List <Curve> > flist = new List <List <Curve> >();
            ClipperOffset        c     = new ClipperOffset();

            AddOffsetSubject(plist, c);

            for (int i = 1;  ; i++)
            {
                List <List <IntPoint> > solution = new List <List <IntPoint> >();
                c.Execute(ref solution, -spacing * i * resolution);

                if (solution.Count > 0)
                {
                    flist.AddRange(ToPotraceList(solution, true));
                }
                else
                {
                    break;
                }
            }

            return(flist);
        }
        public static IEnumerable <IPolyLine2D> BuildOffset(IEnumerable <IPolyLine2D> polylines, double delta, JoinType joinType, EndType endType, double mitterLimit, bool sort = false, double maxDiscretizationAngle = 5)
        {
            PolyLine2DDiscretizator discretizator = new PolyLine2DDiscretizator
            {
                NumberOfTiles = 1,
                LengthOfTile  = double.MaxValue,
                Angle         = maxDiscretizationAngle
            };
            bool containsCircArc = joinType == JoinType.jtRound || endType == EndType.etOpenRound;
            var  polygons        = new List <List <IntPoint> >(polylines.Count());

            foreach (var polyline in polylines)
            {
                if (!containsCircArc)
                {
                    containsCircArc |= polyline.Segments.FirstOrDefault(s => s is CircularArcSegment2D) != null;
                }

                var polygon = CreatePolygon(polyline, discretizator, true);
                polygons.Add(polygon);
            }

            var co = new ClipperOffset(mitterLimit);

            co.AddPaths(polygons, joinType, endType);
            var solution = new List <List <IntPoint> >();

            co.Execute(ref solution, delta * ClipperScale);
            foreach (var polygon in solution)
            {
                yield return(CreatePolyline(polygon, containsCircArc, maxDiscretizationAngle + 1));
            }
        }
        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));
        }
        /// <summary>
        /// Generates a solid outline of the path.
        /// </summary>
        /// <param name="path">the path to outline</param>
        /// <param name="width">The final width outline</param>
        /// <param name="jointStyle">The style to render the joints.</param>
        /// <param name="endCapStyle">The style to render the end caps of open paths (ignored on closed paths).</param>
        /// <returns>A new path representing the outline.</returns>
        public static IPath GenerateOutline(this IPath path, float width, JointStyle jointStyle = JointStyle.Square, EndCapStyle endCapStyle = EndCapStyle.Square)
        {
            var offset = new ClipperOffset()
            {
                MiterLimit = MiterOffsetDelta
            };

            JoinType style           = Convert(jointStyle);
            EndType  openEndCapStyle = Convert(endCapStyle);

            // Pattern can be applied to the path by cutting it into segments
            IEnumerable <ISimplePath> paths = path.Flatten();

            foreach (ISimplePath p in paths)
            {
                IReadOnlyList <PointF> vectors = p.Points;
                var points = new List <IntPoint>(vectors.Count);
                foreach (Vector2 v in vectors)
                {
                    points.Add(new IntPoint(v.X * ScalingFactor, v.Y * ScalingFactor));
                }

                EndType type = p.IsClosed ? EndType.etClosedLine : openEndCapStyle;

                offset.AddPath(points, style, type);
            }

            return(ExecuteOutliner(width, offset));
        }
Exemple #20
0
        // Rough shape only used in Inspector for quick preview.
        internal static List <Vector2> GetOutlinePath(Vector3[] shapePath, float offsetDistance)
        {
            const float     kClipperScale = 10000.0f;
            List <IntPoint> path          = new List <IntPoint>();
            List <Vector2>  output        = new List <Vector2>();

            for (var i = 0; i < shapePath.Length; ++i)
            {
                var newPoint = new Vector2(shapePath[i].x, shapePath[i].y) * kClipperScale;
                path.Add(new IntPoint((System.Int64)(newPoint.x), (System.Int64)(newPoint.y)));
            }
            List <List <IntPoint> > solution   = new List <List <IntPoint> >();
            ClipperOffset           clipOffset = new ClipperOffset(2048.0f);

            clipOffset.AddPath(path, JoinType.jtRound, EndType.etClosedPolygon);
            clipOffset.Execute(ref solution, kClipperScale * offsetDistance, path.Count);
            if (solution.Count > 0)
            {
                for (int i = 0; i < solution[0].Count; ++i)
                {
                    output.Add(new Vector2(solution[0][i].X / kClipperScale, solution[0][i].Y / kClipperScale));
                }
            }
            return(output);
        }
Exemple #21
0
        public static bool addSteinerPointsAtOffset(ref Polygon _polygon, ref ClipperOffset co, float offset, int seglenBigInt)
        {
            PolyTree resPolytree = new AXClipperLib.PolyTree();

            co.Execute(ref resPolytree, (double)(-offset * AXGeometryTools.Utilities.IntPointPrecision));
            Paths paths = Clipper.PolyTreeToPaths(resPolytree);

            if (paths != null && paths.Count > 0 && paths[0] != null && paths[0].Count > 0)
            {
                foreach (Path path in paths)
                {
                    if (path != null && path.Count > 0)
                    {
                        Path ppp = Pather.segmentPath(path, seglenBigInt);
                        if (ppp != null && ppp.Count > 0)
                        {
                            foreach (IntPoint ip in ppp)
                            {
                                _polygon.AddSteinerPoint(new TriangulationPoint((double)ip.X / (double)AXGeometryTools.Utilities.IntPointPrecision, (double)ip.Y / (double)AXGeometryTools.Utilities.IntPointPrecision));
                            }
                        }
                    }
                }


                return(true);
            }
            return(false);
        }
Exemple #22
0
        public static List <GeneralPolygon2d> ComputeOffsetPolygon(GeneralPolygon2d poly, double fOffset, bool bMiter = false)
        {
            double nIntScale = GetIntScale(poly);

            CPolygonList clipper_polys = new CPolygonList();

            clipper_polys.Add(ClipperUtil.ConvertToClipper(poly.Outer, nIntScale));
            foreach (Polygon2d hole in poly.Holes)
            {
                clipper_polys.Add(ClipperUtil.ConvertToClipper(hole, nIntScale));
            }

            CPolygonList dilate_solution = new CPolygonList();

            try {
                ClipperOffset co = new ClipperOffset();
                if (bMiter)
                {
                    co.AddPaths(clipper_polys, JoinType.jtMiter, EndType.etClosedPolygon);
                }
                else
                {
                    co.AddPaths(clipper_polys, JoinType.jtRound, EndType.etClosedPolygon);
                }
                co.Execute(ref dilate_solution, fOffset * nIntScale);
            } catch /*( Exception e )*/ {
                //System.Diagnostics.Debug.WriteLine("ClipperUtil.ComputeOffsetPolygon: Clipper threw exception: " + e.Message);
                return(new List <GeneralPolygon2d>());
            }

            List <GeneralPolygon2d> polys = ClipperUtil.ConvertFromClipper(dilate_solution, nIntScale);

            return(polys);
        }
Exemple #23
0
        /// <summary>
        /// Creates a set of polygonal regions offset from a given set of Clipper polygons
        /// </summary>
        /// <param name="paths">Hierarchy of Clipper polygons to be offset</param>
        /// <param name="innerOffset">Padding distance from the edge of the given paths region</param>
        /// <param name="outerOffset">The outer boundary distance of the offset region</param>
        /// <returns></returns>
        public static List <List <IntPoint> > GenerateOffsetRegionFromRoadPaths(
            List <List <IntPoint> > paths,
            float innerOffset,
            float outerOffset)
        {
            var solution = new List <List <IntPoint> >();

            if (outerOffset < 0f || outerOffset < innerOffset)
            {
                return(solution);
            }

            var clipperOffset = new ClipperOffset();

            clipperOffset.AddPaths(paths, JoinType.jtMiter, EndType.etClosedPolygon);

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

            clipperOffset.Execute(ref innerOffsetRegions, innerOffset * UpScaleFactor);

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

            clipperOffset.Execute(ref outerOffsetRegions, outerOffset * UpScaleFactor);

            var clipper = new Clipper();

            clipper.AddPaths(outerOffsetRegions, PolyType.ptSubject, true);
            clipper.AddPaths(innerOffsetRegions, PolyType.ptClip, true);

            clipper.Execute(ClipType.ctXor, solution, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
            return(solution);
        }
Exemple #24
0
        public void GenerateCollision()
        {
            //List<List<Vector2>> polygons = new List<List<Vector2>>();

            List <List <Vector2> > unitedPolygons = new List <List <Vector2> >();
            Clipper clipper = new Clipper();

            int scalingFactor = 10000;

            for (int x = 0; x < layer.chunkSize_x; x++)
            {
                for (int y = 0; y < layer.chunkSize_y; y++)
                {
                    if (grid[x, y] != null && grid[x, y].colider)
                    {
                        Path newPoligons = new Path(4);

                        newPoligons.Add(new IntPoint(Mathf.Floor((0 + x) * scalingFactor), Mathf.Floor((0 + y) * scalingFactor)));
                        newPoligons.Add(new IntPoint(Mathf.Floor((0 + x) * scalingFactor), Mathf.Floor((1 + y) * scalingFactor)));
                        newPoligons.Add(new IntPoint(Mathf.Floor((1 + x) * scalingFactor), Mathf.Floor((1 + y) * scalingFactor)));
                        newPoligons.Add(new IntPoint(Mathf.Floor((1 + x) * scalingFactor), Mathf.Floor((0 + y) * scalingFactor)));

                        clipper.AddPath(newPoligons, PolyType.ptSubject, true);
                    }
                }
            }

            Paths solution = new Paths();

            clipper.Execute(ClipType.ctUnion, solution);

            ClipperOffset offset = new ClipperOffset();

            offset.AddPaths(solution, JoinType.jtMiter, EndType.etClosedPolygon);
            offset.Execute(ref solution, 5f);

            foreach (Path path in solution)
            {
                List <Vector2> unitedPolygon = new List <Vector2>();
                foreach (IntPoint point in path)
                {
                    unitedPolygon.Add(new Vector2(point.X / (float)scalingFactor, point.Y / (float)scalingFactor));
                }
                unitedPolygons.Add(unitedPolygon);
            }

            unitedPolygons = TileMap.RemoveClosePointsInPolygons(unitedPolygons);

            PolygonCollider2D collider = layer.map.gameObject.GetComponent <PolygonCollider2D>();

            collider.pathCount = unitedPolygons.Count;

            for (int i = 0; i < unitedPolygons.Count; i++)
            {
                Vector2[] points = unitedPolygons[i].ToArray();

                collider.SetPath(i, points);
            }
        }
Exemple #25
0
    //this function takes a list of polygons as a parameter, this list of polygons represent all the polygons that constitute collision in your level.
    public List <List <Vector2> > UniteCollisionPolygons(List <List <Vector2> > polygons)
    {
        //this is going to be the result of the method
        List <List <Vector2> > unitedPolygons = new List <List <Vector2> >();
        Clipper clipper = new Clipper();

        //clipper only works with ints, so if we're working with floats, we need to multiply all our floats by
        //a scaling factor, and when we're done, divide by the same scaling factor again
        int scalingFactor = 10000;

        //this loop will convert our List<List<Vector2>> to what Clipper works with, which is "Path" and "IntPoint"
        //and then add all the Paths to the clipper object so we can process them
        for (int i = 0; i < polygons.Count; i++)
        {
            Path allPolygonsPath = new Path(polygons[i].Count);

            for (int j = 0; j < polygons[i].Count; j++)
            {
                allPolygonsPath.Add(new IntPoint(Mathf.Floor(polygons[i][j].x * scalingFactor), Mathf.Floor(polygons[i][j].y * scalingFactor)));
                //print(new IntPoint(Mathf.Floor(polygons[i][j].x * scalingFactor), Mathf.Floor(polygons[i][j].y * scalingFactor)).X + ", " + new IntPoint(Mathf.Floor(polygons[i][j].x * scalingFactor), Mathf.Floor(polygons[i][j].y * scalingFactor)).Y);
            }
            clipper.AddPath(allPolygonsPath, PolyType.ptSubject, true);
        }

        //this will be the result
        Paths solution = new Paths();

        //having added all the Paths added to the clipper object, we tell clipper to execute an union
        clipper.Execute(ClipType.ctUnion, solution);


        //the union may not end perfectly, so we're gonna do an offset in our polygons, that is, expand them outside a little bit
        ClipperOffset offset = new ClipperOffset();

        offset.AddPaths(solution, JoinType.jtMiter, EndType.etClosedPolygon);
        //5 is the amount of offset
        offset.Execute(ref solution, 0.1f);


        //now we just need to convert it into a List<List<Vector2>> while removing the scaling
        foreach (Path path in solution)
        {
            List <Vector2> unitedPolygon = new List <Vector2>();
            foreach (IntPoint point in path)
            {
                unitedPolygon.Add(new Vector2(point.X / (float)scalingFactor, point.Y / (float)scalingFactor));
            }
            unitedPolygons.Add(unitedPolygon);
        }


        //this removes some redundant vertices in the polygons when they are too close from each other
        //may be useful to clean things up a little if your initial collisions don't match perfectly from tile to tile
        unitedPolygons = RemoveClosePointsInPolygons(unitedPolygons);

        //everything done
        return(unitedPolygons);
    }
Exemple #26
0
        public static void generateOutlineSegments()
        {
            Logger.logProgress("Generating outline segments");

            //Check if there should be at least one shell
            if (Global.Values.shellThickness < 1)
            {
                return;
            }

            //We need to got through every layercomponent
            //for (ushort i = 0; i < Global.Values.layerCount; i++)
            foreach (LayerComponent layer in Global.Values.layerComponentList)
            {
                Logger.logProgress("Outline: " + layer.layerNumber);

                //And every island inside the list
                foreach (Island island in layer.islandList)
                {
                    if (island.outlinePolygons.Count < 1)
                    {
                        continue;
                    }

                    //The first outline will be one that is half an extrusion thinner than the sliced outline, ths is sothat the dimensions
                    //do not change once extruded
                    Polygons      outline = new Polygons();
                    ClipperOffset offset  = new ClipperOffset();
                    offset.AddPaths(island.outlinePolygons, JoinType.jtMiter, EndType.etClosedPolygon);
                    offset.Execute(ref outline, -Global.Values.nozzleWidth / 2);

                    for (ushort j = 0; j < Global.Values.shellThickness; j++)
                    {
                        //Place the newly created outline in its own segment
                        LayerSegment outlineSegment = new LayerSegment(SegmentType.OutlineSegment);
                        outlineSegment.segmentType     = SegmentType.OutlineSegment;
                        outlineSegment.segmentSpeed    = layer.layerSpeed;
                        outlineSegment.outlinePolygons = new Polygons(outline);

                        island.segmentList.Add(outlineSegment);

                        var distance = (-Global.Values.nozzleWidth / 2) - Global.Values.nozzleWidth * (j + 1);

                        //We now shrink the outline with one extrusion width for the next shell if any
                        offset = new ClipperOffset();
                        offset.AddPaths(island.outlinePolygons, JoinType.jtMiter, EndType.etClosedPolygon);
                        offset.Execute(ref outline, distance);
                    }

                    //We now need to store the smallest outline as the new layer outline for infill trimming purposes
                    //the current outline though is just half an extrusion width to small
                    offset = new ClipperOffset();
                    offset.AddPaths(outline, JoinType.jtMiter, EndType.etClosedPolygon);
                    offset.Execute(ref island.outlinePolygons, Global.Values.nozzleWidth);
                }
            }
        }
Exemple #27
0
        /// <summary>
        /// Gets a parallel <see cref="Loxy"/> with offset
        /// </summary>
        /// <param name="JT">Jointype</param>
        /// <param name="ET">Endtype</param>
        /// <param name="Offset">Offset</param>
        /// <returns></returns>
        public Loxy GetOffset(JoinType JT, EndType ET, double Offset)
        {
            ClipperOffset           co       = new ClipperOffset();
            List <List <IntPoint> > Solution = new List <List <IntPoint> >();

            co.AddPaths(ToClipperPoly(this), (ClipperLib.JoinType)JT, (ClipperLib.EndType)ET);
            co.Execute(ref Solution, (long)(ToInt * Offset));
            return(FromClipperLoxy(Solution));
        }
        public static Polygons Offset(this Polygons polygons, int distance)
        {
            ClipperOffset offseter = new ClipperOffset();

            offseter.AddPaths(polygons, JoinType.jtMiter, EndType.etClosedPolygon);
            Paths solution = new Polygons();

            offseter.Execute(ref solution, distance);
            return(solution);
        }
Exemple #29
0
        static public ClipperPolygons Buffer(this ClipperPolygons polygons, double distance)
        {
            ClipperPolygons result = new ClipperPolygons();

            ClipperOffset co = new ClipperOffset();
            co.AddPaths(polygons, JoinType.jtRound, EndType.etClosedPolygon);
            co.Execute(ref result, distance * Acc);

            return result;
        }
Exemple #30
0
        public static void calculateSupportSegments()
        {
            Logger.logProgress("Calculating support segments");

            if (!Global.Values.shouldSupportMaterial || Global.Values.supportMaterialDesnity <= 0)
            {
                return;
            }

            //To calculate the support segments we will keep a union of the above layers and perform a difference with them and the current layer
            Polygons topUnion = new Polygons();

            for (int i = Global.Values.layerCount - 1; i > -1; i--)
            {
                Polygons layerPolygons = new Polygons();

                foreach (Island island in Global.Values.layerComponentList[i].islandList)
                {
                    Polygons offsetResult = new Polygons();

                    ClipperOffset offset = new ClipperOffset();
                    offset.AddPaths(island.outlinePolygons, JoinType.jtMiter, EndType.etClosedPolygon);
                    offset.Execute(ref offsetResult, Global.Values.shellThickness * Global.Values.nozzleWidth);

                    Clipper clipper = new Clipper();
                    clipper.AddPaths(offsetResult, PolyType.ptClip, true);
                    clipper.AddPaths(layerPolygons, PolyType.ptSubject, true);
                    clipper.Execute(ClipType.ctUnion, layerPolygons);
                }

                Polygons supportOutline = new Polygons();
                Clipper  supportClipper = new Clipper();
                supportClipper.AddPaths(topUnion, PolyType.ptSubject, true);
                supportClipper.AddPaths(layerPolygons, PolyType.ptClip, true);
                supportClipper.Execute(ClipType.ctDifference, supportOutline);

                //We should just offset the support slightly so that it does not touch the rest of the model
                ClipperOffset clipperOffset = new ClipperOffset();
                clipperOffset.AddPaths(supportOutline, JoinType.jtMiter, EndType.etClosedPolygon);
                clipperOffset.Execute(ref supportOutline, -Global.Values.nozzleWidth);

                Island       supportIsland = new Island();
                LayerSegment segment       = new LayerSegment(SegmentType.SupportSegment);
                segment.segmentSpeed          = Global.Values.layerComponentList[i].supportSpeed;
                segment.outlinePolygons       = supportOutline;
                supportIsland.outlinePolygons = supportOutline;
                supportIsland.segmentList.Add(segment);
                Global.Values.layerComponentList[i].islandList.Add(supportIsland);

                Clipper unionClipper = new Clipper();
                unionClipper.AddPaths(topUnion, PolyType.ptClip, true);
                unionClipper.AddPaths(layerPolygons, PolyType.ptSubject, true);
                unionClipper.Execute(ClipType.ctUnion, topUnion);
            }
        }
        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 Offset(this Polygons polygons, int distance)
 {
     ClipperOffset offseter = new ClipperOffset();
     offseter.AddPaths(polygons, JoinType.jtMiter, EndType.etClosedPolygon);
     Paths solution = new Polygons();
     offseter.Execute(ref solution, distance);
     return solution;
 }
        private static void AddPath(ClipperOffset offset, Path path, JoinType joinType, EndType endType) {
            foreach (Subpath subpath in path.Subpaths) {
                if (!subpath.IsSinglePointClosed() && !subpath.IsSinglePointOpen()) {
                    EndType et;

                    if (subpath.Closed) {
                        // Offsetting is never used for path being filled
                        et = EndType.etClosedLine;
                    } else {
                        et = endType;
                    }

                    IList<Point2D> linearApproxPoints = subpath.GetPiecewiseLinearApproximation();
                    offset.AddPath(ConvertToIntPoints(linearApproxPoints), joinType, et);
                }
            }
        }
        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);
        }
        /**
         * Adds all subpaths of the path to the {@link ClipperOffset} object with one
         * note: it doesn't add degenerate subpaths.
         *
         * @return {@link java.util.List} consisting of all degenerate subpaths of the path.
         */
        private static IList<Subpath> AddPath(ClipperOffset offset, Path path, JoinType joinType, EndType endType) {
            IList<Subpath> degenerateSubpaths = new List<Subpath>();

            foreach (Subpath subpath in path.Subpaths) {
                if (subpath.IsDegenerate()) {
                    degenerateSubpaths.Add(subpath);
                    continue;
                }

                if (!subpath.IsSinglePointClosed() && !subpath.IsSinglePointOpen()) {
                    EndType et;

                    if (subpath.Closed) {
                        // Offsetting is never used for path being filled
                        et = EndType.etClosedLine;
                    } else {
                        et = endType;
                    }

                    IList<Point2D> linearApproxPoints = subpath.GetPiecewiseLinearApproximation();
                    offset.AddPath(ConvertToIntPoints(linearApproxPoints), joinType, et);
                }
            }

            return degenerateSubpaths;
        }