Example #1
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>
        /// <returns>A new closed Polygon offset in all directions by offset from the polyline.</returns>
        public virtual Polygon[] Offset(double offset, EndType endType)
        {
            var path = this.ToClipperPath();

            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 * CLIPPER_SCALE);  // important, scale also used here

            var result = new Polygon[solution.Count];

            for (var i = 0; i < result.Length; i++)
            {
                result[i] = solution[i].ToPolygon();
            }
            return(result);
        }
Example #2
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);
        }
Example #3
0
        /// <summary>
        /// Adds all iText
        /// <see cref="iText.Kernel.Geom.Subpath"/>
        /// s of the iText
        /// <see cref="List<IntPoint>"/>
        /// 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);
        }
Example #4
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());
    }
Example #5
0
        /// <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)
            {
                ReadOnlySpan <Vector2> vectors = MemoryMarshal.Cast <PointF, Vector2>(p.Points.Span);
                var points = new List <IntPoint>(vectors.Length);
                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));
        }
Example #6
0
        private static 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);
        }
        /// <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.Butt)
        {
            var offset = new ClipperOffset()
            {
                MiterLimit = MiterOffsetDelta
            };

            var style           = Convert(jointStyle);
            var 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);
                for (int i = 0; i < vectors.Count; i++)
                {
                    var v = vectors[i];
                    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));
        }
Example #8
0
        /// <summary>
        /// Create a slice from an open path with the given width
        /// </summary>
        /// <param name="path"></param>
        /// <param name="width"></param>
        /// <param name="plane"></param>
        public Slice(LineStrip path, float width, Plane plane, bool closed = false)
        {
            this.plane       = plane;
            transform        = plane.CreateMatrix();
            transform        = Matrix4.Mult(transform, Matrix4.CreateScale(scale));
            inverseTransform = Matrix4.Invert(transform);
            polyTree         = new PolyTree();

            ClipperOffset co = new ClipperOffset();

            co.ArcTolerance = scale * 0.0001f;
            if (closed)
            {
                co.AddPath(LineStripToPolygon(path), JoinType.jtRound, EndType.etClosedLine);
            }
            else
            {
                co.AddPath(LineStripToPolygon(path), JoinType.jtRound, EndType.etOpenRound);
            }
            co.Execute(ref this.polyTree, scale * width / 2.0f);
        }
Example #9
0
        } /// <summary>

        /// 线两侧偏移后为矩形,偏移距离须与点的放大倍数一致
        /// </summary>
        public static Paths Offset(this Path _Path, double _offset, double magnification, EndType endType)
        {
            Paths         solution = new Paths();
            ClipperOffset _Co      = new ClipperOffset();

            _Co.MiterLimit = 3;
            _Co.AddPath(_Path, JoinType.jtMiter, endType);
            _Co.Execute(ref solution, _offset * magnification);
            //solution = Clipper.CleanPolygons(solution, Precision_.clipperMultiple * (0.003));
            //solution = Clipper.SimplifyPolygons(solution);
            return(solution);
        }
Example #10
0
        static void AddClip(ClipperOffset c, GraphicsPath psubject)
        {
            psubject.Flatten();

            List <IntPoint> subject = new List <IntPoint>(psubject.PathPoints.Count());

            foreach (PointF p in psubject.PathPoints)
            {
                subject.Add(new IntPoint(p.X * resolution, p.Y * resolution));
            }

            c.AddPath(subject, JoinType.jtRound, EndType.etClosedPolygon);
        }
Example #11
0
        public static List <NestPath> polygonOffset(NestPath polygon, double offset)
        {
            List <NestPath> result = new List <NestPath>();

            if (offset == 0 || GeometryUtil.almostEqual(offset, 0))
            {
                /**
                 * return EmptyResult
                 */
                return(result);
            }
            Path p = new Path();

            foreach (Segment s in polygon.getSegments())
            {
                ClipperCoor cc = toClipperCoor(s.getX(), s.getY());
                p.Add(new IntPoint(cc.getX(), cc.getY()));
            }

            int           miterLimit = 2;
            ClipperOffset co         = new ClipperOffset(miterLimit, Config.CURVE_TOLERANCE * Config.CLIIPER_SCALE);

            co.AddPath(p, JoinType.jtRound, EndType.etClosedPolygon);

            Paths newpaths = new Paths();

            co.Execute(ref newpaths, offset * Config.CLIIPER_SCALE);


            /**
             * 这里的length是1的话就是我们想要的
             */
            for (int i = 0; i < newpaths.Count; i++)
            {
                result.Add(CommonUtil.clipperToNestPath(newpaths[i]));
            }

            if (offset > 0)
            {
                NestPath from = result[0];
                if (GeometryUtil.polygonArea(from) > 0)
                {
                    from.reverse();
                }
                from.add(from.get(0)); from.getSegments().RemoveAt(0);
            }


            return(result);
        }
Example #12
0
        public List <GameObject> CreateStreets(List <List <Vector3> > streetsPoly)
        {
            List <GameObject> streets = new List <GameObject> ();

            for (int i = 0; i < streetsPoly.Count; i++)
            {
                GameObject street = new GameObject("street" + i, typeof(MeshRenderer), typeof(MeshFilter));
                street.transform.parent = this.transform;
                street.GetComponent <MeshRenderer> ().material = (Material)Resources.Load("StreetMat");

                List <List <IntPoint> > solution = new List <List <IntPoint> > ();
                //transform vertices of each mesh in points for clipper
                List <IntPoint> intPoint = FromVecToIntPoint(streetsPoly [i].ToArray());
                //offset each mesh
                ClipperOffset co = new ClipperOffset();
                co.AddPath(intPoint, JoinType.jtRound, EndType.etOpenRound);
                co.Execute(ref solution, 700.0);

                List <Vector2> vertices2D = new List <Vector2> ();
                for (int j = 0; j < solution.Count; j++)
                {
                    vertices2D = vertices2D.Concat(FromIntPointToVec(solution [j])).ToList();
                }

                // Use the triangulator to get indices for creating triangles
                Triangulator tr      = new Triangulator(vertices2D.ToArray());
                int[]        indices = tr.Triangulate();

                // Create the Vector3 vertices
                Vector3[] vertices = new Vector3[vertices2D.Count];
                for (int k = 0; k < vertices.Length; k++)
                {
                    vertices [k] = new Vector3(vertices2D [k].x, 0f, vertices2D [k].y);
                }
                // Create the mesh
                Mesh msh = new Mesh();
                msh.vertices  = vertices;
                msh.triangles = indices;
                msh.RecalculateNormals();
                msh.RecalculateBounds();

                // Set up game object with mesh;
                street.GetComponent <MeshFilter> ().mesh = msh;
                street.AddComponent <MeshCollider> ();
                street.transform.position = new Vector3(street.transform.position.x, 0.02f, street.transform.position.z);
                streets.Add(street);
            }
            DrawStreetLineMesh(streetsPoly, streets);
            return(streets);
        }
Example #13
0
        public static Paths offset(Paths paths, float offset)
        {
            // Set cleaning precision
            IntRect brect = Clipper.GetBounds(paths);
            int     cleanPolygonPrecision = 2;

            if ((brect.right - brect.left) > 10000)
            {
                cleanPolygonPrecision = 30;
            }


            // Clean...
            AXClipperLib.JoinType jt = AXClipperLib.JoinType.jtSquare;
            paths = AXGeometryTools.Utilities.cleanPaths(paths, cleanPolygonPrecision);



            Paths resPaths = new Paths();

            AXClipperLib.PolyTree resPolytree = null;


            // OFFSETTER
            ClipperOffset co = new ClipperOffset();

            co.MiterLimit = 2.0f;



            foreach (Path path in paths)
            {
                co.Clear();
                resPolytree = null;

                co.AddPath(path, jt, AXClipperLib.EndType.etClosedPolygon);                  //JoinType.jtSquare, AXClipperLib.EndType.etClosedPolygon);

                // this resPolytree has transformed curves in it
                resPolytree = new AXClipperLib.PolyTree();
                co.Execute(ref resPolytree, (double)(offset * AXGeometryTools.Utilities.IntPointPrecision));
                resPaths.AddRange(Clipper.ClosedPathsFromPolyTree(resPolytree));
            }

            return(resPaths);
        }
Example #14
0
        /// <summary>
        /// Offset this polyline by the specified amount.
        /// </summary>
        /// <param name="offset">The amount to offset.</param>
        /// <returns>A new polyline offset by offset.</returns>
        public IList <Polygon> Offset(double offset)
        {
            var path = this.ToClipperPath();

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

            co.AddPath(path, JoinType.jtMiter, EndType.etClosedPolygon);
            co.Execute(ref solution, offset * scale);  // important, scale also used here

            var result = new List <Polygon>();

            foreach (var loop in solution)
            {
                result.Add(loop.ToPolygon());
            }
            return(result);
        }
Example #15
0
        /// <summary>
        /// Offset this polygon by the specified amount.
        /// </summary>
        /// <param name="offset">The amount to offset.</param>
        /// <returns>A new Polygon offset by offset.</returns>
        public Polygon[] Offset(double offset)
        {
            var path = this.ToClipperPath();

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

            co.AddPath(path, JoinType.jtMiter, EndType.etClosedPolygon);
            co.Execute(ref solution, offset * scale);  // important, scale also used here

            var result = new Polygon[solution.Count];

            for (var i = 0; i < result.Length; i++)
            {
                result[i] = solution[i].ToPolygon();
            }
            return(result);
        }
Example #16
0
        /// <summary>
        /// Split a set of profiles with a collection of open polylines, with an optional gap between results.
        /// </summary>
        /// <param name="profiles">The profiles to split</param>
        /// <param name="splitLines">The polylines defining the splits.</param>
        /// <param name="gapSize">An optional gap size between split pieces. If splits are failing, it can be helpful to increase this.</param>
        /// <param name="tolerance">An optional tolerance.</param>
        public static List <Profile> Split(IEnumerable <Profile> profiles, IEnumerable <Polyline> splitLines, double gapSize = 0, double tolerance = Vector3.EPSILON)
        {
            // We're doing something a little bit questionable here — we're offsetting the split curves by a hair's width
            // so that clipper can handle them as a subtraction, since it doesn't have a built-in split mechanism.
            // We increase the tolerance so that the result is well within the specified tolerance of the expected result.
            // This is imperfect, but no more imperfect than all of the other clipper-based operations we currently employ.

            var     internalTolerance = tolerance / 10; // to keep splits within tolerance, we execute clipper at a 10x smaller tolerance.
            Clipper clipper           = new Clipper();

            foreach (var profile in profiles)
            {
                var clipperPaths = profile.ToClipperPaths(internalTolerance);
                clipper.AddPaths(clipperPaths, PolyType.ptSubject, true);
            }

            foreach (var line in splitLines)
            {
                var unionClipper = new Clipper();

                // This is basically the same as
                // line.Offset(offsetDist, EndType.Butt, internalTolerance),
                // but without the unneccessary conversion back to Elements geometry.
                var co             = new ClipperOffset();
                var offsetSolution = new List <List <IntPoint> >();
                var offsetPath     = line.ToClipperPath(internalTolerance);
                var offsetDist     = (internalTolerance) + gapSize;
                var clipperScale   = 1.0 / internalTolerance;
                co.AddPath(offsetPath, JoinType.jtMiter, ClipperLib.EndType.etOpenButt);
                co.Execute(ref offsetSolution, offsetDist * clipperScale);

                List <List <IntPoint> > unionSolution = new List <List <IntPoint> >();
                unionClipper.AddPaths(offsetSolution, PolyType.ptSubject, true);
                unionClipper.Execute(ClipType.ctUnion, unionSolution, PolyFillType.pftNonZero);

                clipper.AddPaths(unionSolution, PolyType.ptClip, true);
            }
            PolyTree solution = new PolyTree();

            clipper.Execute(ClipType.ctDifference, solution, PolyFillType.pftNonZero);
            var joinedProfiles = solution.ToProfiles(internalTolerance);

            return(joinedProfiles);
        }
Example #17
0
        /// <summary>
        /// increase of decrease polygon points offseting
        /// </summary>
        public static IEnumerable <Vector3D> Offset(this IReadOnlyList <Vector3D> pts, double tol, double offset)
        {
            var intmap = new Int64Map(tol, pts.SelectMany(x => x.Coordinates));

            var clipper = new ClipperOffset();
            {
                var path = pts.Select(p => new IntPoint(intmap.ToInt64(p.X), intmap.ToInt64(p.Y))).ToList();
                // http://www.angusj.com/delphi/clipper.php
                clipper.AddPath(path, JoinType.jtMiter, EndType.etClosedPolygon);
            }

            var intoffset = intmap.ToInt64(intmap.Origin + offset) - intmap.ToInt64(intmap.Origin);

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

            clipper.Execute(ref sol, intoffset);

            return(sol.SelectMany(s => s.Select(si => new Vector3D(intmap.FromInt64(si.X), intmap.FromInt64(si.Y), 0))));
        }
Example #18
0
        public void DrawSegment(List <Vector3> segment, List <Mesh> intersectionPolys, List <GameObject> lines)
        {
            List <List <IntPoint> > solution = new List <List <IntPoint> > ();
            //transform vertices of each mesh in points for clipper
            List <IntPoint> intPoint = FromVecToIntPoint(segment.ToArray());
            //offset each mesh
            ClipperOffset co = new ClipperOffset();

            co.AddPath(intPoint, JoinType.jtRound, EndType.etOpenRound);
            co.Execute(ref solution, 100.0);

            List <Vector2> vertices2D = new List <Vector2> ();

            for (int j = 0; j < solution.Count; j++)
            {
                vertices2D = vertices2D.Concat(FromIntPointToVec(solution [j])).ToList();
            }

            // Use the triangulator to get indices for creating triangles
            Triangulator tr = new Triangulator(vertices2D.ToArray());

            int[] indices = tr.Triangulate();

            // Create the Vector3 vertices
            Vector3[] vertices = new Vector3[vertices2D.Count];
            for (int k = 0; k < vertices.Length; k++)
            {
                vertices [k] = new Vector3(vertices2D [k].x, 0f, vertices2D [k].y);
            }
            // Create the mesh
            Mesh msh = new Mesh();

            msh.vertices  = vertices;
            msh.triangles = indices;
            msh.RecalculateNormals();
            msh.RecalculateBounds();

            Mesh       newMesh     = ExecuteMultiDifferencePoly(msh, intersectionPolys);
            GameObject lineSegment = new GameObject("segment", typeof(MeshFilter), typeof(MeshRenderer));

            lineSegment.GetComponent <MeshFilter> ().sharedMesh = newMesh;
            lines.Add(lineSegment);
        }
Example #19
0
        public DominoPath getOffsetRectangle(int offset)
        {
            List <IntPoint> intpoints = points.Select(p => new IntPoint(p.X, p.Y)).ToList();

            intpoints.Add(new IntPoint(points[0].X, points[0].Y));
            List <List <IntPoint> > solution = new List <List <IntPoint> >();
            ClipperOffset           co       = new ClipperOffset();

            co.AddPath(intpoints, JoinType.jtMiter, EndType.etClosedLine);
            co.Execute(ref solution, offset);
            if (solution.Count == 0)
            {
                return(this);
            }
            return(new DominoPath()
            {
                points = solution[0].Select(p => new Point(p.X, p.Y)).ToArray()
            });
        }
Example #20
0
        public List <Vector2> ExtendPolygon(List <Vector2> points, float radius, GMLGeometry.GeometryType type)
        {
            Path polygon = points.ConvertAll(p => new IntPoint(p.x, p.y));

            Paths solution = new Paths();

            ClipperOffset c = new ClipperOffset();

            c.AddPath(polygon, JoinType.jtRound, type == GMLGeometry.GeometryType.Polygon ? EndType.etClosedPolygon : EndType.etOpenRound);
            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);
        }
Example #21
0
        internal void ExtendThePolygon(ref List <IntPoint> enterPoints, ref Vector2[] extendedPoints, float extraOffset)
        {
            double distance = (AgentRadius + extraOffset) * (float)_Accuracy;

            _ClipperOffset.Clear();
            _ExitExtendPoints.Clear();

            _ClipperOffset.AddPath(enterPoints, JoinType.jtMiter, EndType.etClosedPolygon);
            _ClipperOffset.Execute(ref _ExitExtendPoints, distance);

            if (_ExitExtendPoints[0].Count != extendedPoints.Length)
            {
                extendedPoints = new Vector2[_ExitExtendPoints[0].Count];
            }

            for (int i = 0; i < _ExitExtendPoints[0].Count; ++i)
            {
                extendedPoints[i] = ParseToVector2(_ExitExtendPoints[0][i]);
            }
        }
Example #22
0
    public static Polyline Offset(Polyline polyline, double distance)
    {
        if (polyline.Count < 2)
        {
            return(new Polyline());
        }

        var region = polyline.ToRegion();
        var offset = new ClipperOffset();

        offset.AddPath(region, JoinType.jtRound, EndType.etClosedPolygon);
        PolyTree tree = new PolyTree();

        offset.Execute(ref tree, distance / Tol);

        var height = polyline[0].Z;
        var first  = tree.ToPolylines(height).MaxBy(p => p.Length).FirstOrDefault();

        return(first ?? new Polyline(0));
    }
Example #23
0
        public void DrawSitePicture(Site site, Graphics g, bool fillShapes, bool showOutlines, int fullWidth, int fullHeight)
        {
            double xscale = ((double)fullWidth) / ((double)_boundingBox.Width);
            double yscale = ((double)fullHeight) / ((double)_boundingBox.Height);

            g.InterpolationMode = InterpolationMode.High;
            g.SmoothingMode     = SmoothingMode.AntiAlias;

            int minX = site.RegionPoints.Min(pt => pt.X);
            int minY = site.RegionPoints.Min(pt => pt.Y);

            //var offsetPoints = site.RegionPoints.Select(pt => new Point(pt.X - minX + 5, pt.Y - minY + 5)).ToArray();
            var offsetPoints = site.RegionPoints
                               .Select(pt => new Point((int)(xscale * ((double)pt.X - minX)) + 2 * ImageOffset, (int)(yscale * ((double)pt.Y - minY) + 2 * ImageOffset))).ToArray();

            if (fillShapes)
            {
                g.FillPolygon(new SolidBrush(site.Color), offsetPoints);
            }

            if (showOutlines)
            {
                g.DrawPolygon(Pens.Black, offsetPoints);
            }

            if (showOutlines)
            {
                ClipperOffset offset = new ClipperOffset();

                offset.AddPath(offsetPoints.Select(op => new IntPoint(op.X, op.Y)).ToList(), JoinType.jtMiter, EndType.etClosedLine);

                List <List <IntPoint> > solution = new List <List <IntPoint> >();
                offset.Execute(ref solution, ImageOffset);

                if (solution.Count > 0)
                {
                    var offsetPoly = solution[0];
                    g.DrawPolygon(Pens.Red, offsetPoly.Select(ip => new Point((int)ip.X, (int)ip.Y)).ToArray());
                }
            }
        }
        public static IEnumerable <IPolyLine2D> BuildOffset(IPolygon2D polygon, double delta, JoinType joinType, EndType endType, double mitterLimit, double maxDiscretizationAngle = 5)
        {
            bool containsCircArc = false;
            var  p = CreatePolygon(polygon);

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

            var co = new ClipperOffset(mitterLimit);

            co.AddPath(p, 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));
            }
        }
Example #25
0
        public static NativeArray <RigidTransform> OffsetPath(
            NativeArray <RigidTransform> samples,
            float distance,
            bool looped,
            Allocator allocator)
        {
            var solution = new List <List <IntPoint> >();
            var polygon  = FromSamplesToClipper(samples);

            if (!Clipper.Orientation(polygon))
            {
                distance *= -1;
            }

            var clipperOffset = new ClipperOffset();

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

            return(IntPointsToRigidTransforms(solution[0], looped, allocator));
        }
        public static IEnumerable <IPolyLine2D> BuildOffset(IPolyLine2D polyline, 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
            };
            var p = CreatePolygon(polyline, discretizator, true);

            bool containsCircArc = joinType == JoinType.jtRound || endType == EndType.etOpenRound;

            if (!containsCircArc)
            {
                containsCircArc = polyline.Segments.FirstOrDefault(s => s is CircularArcSegment2D) != null;
            }

            var co = new ClipperOffset(mitterLimit);

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

            co.Execute(ref solution, delta * ClipperScale);
            if (sort && polyline.IsClosed && !containsCircArc && joinType == JoinType.jtMiter && (endType == EndType.etClosedLine || endType == EndType.etClosedPolygon) && solution.Count == 1)
            {
                // try to sort offset path according to source path
                var newPolyline = CreatePolyline(solution[0], containsCircArc, maxDiscretizationAngle + 1);
                TrySortSegments(polyline, newPolyline, delta);
                yield return(newPolyline);
            }
            else
            {
                foreach (var polygon in solution)
                {
                    yield return(CreatePolyline(polygon, containsCircArc, maxDiscretizationAngle + 1));
                }
            }
        }
Example #27
0
    void ShrinkPolygon(double scale, ref PolygonCollider2D poly)
    {
        List <IntPoint>         subj;
        List <List <IntPoint> > solution = new List <List <IntPoint> >();
        ClipperOffset           co       = new ClipperOffset();

        Vector2[] path;
        Vector2   tempPoint;
        int       pathNdx  = 0;
        int       pointNdx = 0;

        for (int ndx = 0; ndx < poly.pathCount; ndx++)
        {
            subj = new List <IntPoint>();
            foreach (Vector2 point in poly.GetPath(0))
            {
                subj.Add(new IntPoint(point.x * 1000, point.y * 1000));
            }
            co.AddPath(subj, JoinType.jtMiter, EndType.etClosedPolygon);
        }
        co.Execute(ref solution, scale);

        foreach (List <IntPoint> list in solution)
        {
            path     = new Vector2[solution[pathNdx].Count];
            pointNdx = 0;
            foreach (IntPoint point in list)
            {
                tempPoint   = new Vector2();
                tempPoint.x = (float)point.X / 1000;
                tempPoint.y = (float)point.Y / 1000;
                path.SetValue(tempPoint, pointNdx);
                pointNdx++;
            }
            poly.SetPath(pathNdx, path);
            pathNdx++;
        }
    }
Example #28
0
        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);
                }
            }
        }
Example #29
0
        /// <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>
        /// <returns>A new path representing the outline.</returns>
        public static IPath GenerateOutline(this IPath path, float width)
        {
            var offset = new ClipperOffset();

            // 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 : EndType.etOpenButt;

                offset.AddPath(points, JoinType.jtSquare, type);
            }

            return(ExecuteOutliner(width, offset));
        }
Example #30
0
        public static IEnumerable <Rhino.Geometry.Curve> Offset(IEnumerable <Rhino.Geometry.Curve> curves, double distance, JoinType joinType, EndType endType, double miter, double arcTolerance, Plane?plane)
        {
            var curveList = curves as IList <Rhino.Geometry.Curve> ?? curves.ToList();

            plane = GetPlane(curveList, plane);


            var polylines2D = curveList.Select(o => Polyline2D.FromCurve(o, plane.Value))
                              .Where(o => o != null)
                              .ToList();


            double  unit;
            Point2d center;

            CalculateUnit(polylines2D, miter * distance, out unit, out center);


            var polylinesInt = polylines2D.Select(o => PolylineInt.FromPolyline2D(o, center, unit))
                               .ToList();


            var clipper = new ClipperOffset(miter, arcTolerance / unit);

            foreach (var polygon in polylinesInt)
            {
                clipper.AddPath(polygon, joinType, polygon.Closed ? EndType.etClosedPolygon : endType);
            }


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

            clipper.Execute(ref solution, distance / unit);


            return(solution.Select(o => o.ToCurve(plane.Value, center, unit)));
        }
        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);
                }
            }
        }
Example #32
0
        /**
         * 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;
        }