Пример #1
0
        public static List <List <Vector2> > Simplify(List <Vector2> polygon, FillMode fillMode, out PolyTree tree)
        {
            Clipper.Clear();
            Clipper.AddPath(polygon, PolyType.ptSubject, true);
            Clipper.AddPath(polygon, PolyType.ptClip, true);

            tree = new PolyTree();
            PolyFillType fillType = fillMode.ToPolyFillType();

            Clipper.Execute(ClipType.ctUnion, tree, fillType, fillType);
            return(Clipper.ClosedPathsFromPolyTree(tree));
        }
Пример #2
0
        /// <summary>
        /// Returns a region which is the result of mergin region1 and region2. Original regions are not modified.
        /// </summary>
        /// <returns>The merge.</returns>
        /// <param name="region1">Region1.</param>
        /// <param name="region2">Region2.</param>
        public Region RegionMerge(Region region1, Region region2)
        {
            Region newRegion = region1.Clone();

            RegionMagnet(newRegion, region2);
            Clipper clipper = new Clipper();

            clipper.AddPath(newRegion, PolyType.ptSubject);
            clipper.AddPath(region2, PolyType.ptClip);
            clipper.Execute(ClipType.ctUnion, newRegion);
            return(newRegion);
        }
        private List <List <Vector2> > GetIntersectionPolygon(Vector2[] subjectPoly, out bool isIntersecting)
        {
            List <List <Vector2> > intersectionPoly = new List <List <Vector2> >();

            Clipper clipper = new Clipper();
            Paths   solutionPath = new Paths();
            Path    subjPath = new Path();
            Path    clipPath = new Path();
            int     len, len2;

            isIntersecting = true;

            len = subjectPoly.Length;
            for (int i = 0; i < len; i++)
            {
                subjPath.Add(new IntPoint(subjectPoly[i].x * scaleFactor, subjectPoly[i].y * scaleFactor));
            }

            len = clipPolygon.Count;
            for (int i = 0; i < len; i++)
            {
                clipPath.Add(new IntPoint(clipPolygon[i].x * scaleFactor, clipPolygon[i].y * scaleFactor));
            }

            clipper.AddPath(subjPath, PolyType.ptSubject, true);
            clipper.AddPath(clipPath, PolyType.ptClip, true);
            clipper.Execute(ClipType.ctIntersection, solutionPath, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            if (solutionPath.Count != 0)
            {
                len = solutionPath.Count;

                for (int i = 0; i < len; i++)
                {
                    len2 = solutionPath[i].Count;
                    List <Vector2> list = new List <Vector2>();

                    for (int j = 0; j < len2; j++)
                    {
                        list.Add(new Vector2(solutionPath[i][j].X / scaleFactor, solutionPath[i][j].Y / scaleFactor));
                    }

                    intersectionPoly.Add(list);
                }
                return(intersectionPoly);
            }
            else
            {
                isIntersecting = false;
                return(null);
            }
        }
        private IntersectResult Intersect2Curves(Curve a, Curve b)
        {
            int             clipperPrecision = 100;
            IntersectResult result           = new IntersectResult();

            if (Curve.PlanarCurveCollision(a, b, Plane.WorldXY, 0.001f))
            {
                Clipper clipper  = new Clipper();
                Path    subjectA = CurveToPath(a, clipperPrecision);
                Path    subjectB = CurveToPath(b, clipperPrecision);
                Paths   solution = new Paths();

                clipper.AddPath(subjectA, PolyType.ptClip, true);
                clipper.AddPath(subjectB, PolyType.ptSubject, true);

                clipper.Execute(ClipType.ctIntersection, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

                if (solution.Count > 0)
                {
                    result.intersect = true;
                    PolylineCurve pl = PathToPolyline(solution[0], clipperPrecision);
                    result.unionCurve = pl;

                    Point3d minPoint = pl.GetBoundingBox(false).Min;
                    Point3d maxPoint = pl.GetBoundingBox(false).Max;

                    if (maxPoint.X - minPoint.X > maxPoint.Y - minPoint.Y)
                    {
                        result.reboundingVector = new Vector2d(0, -(maxPoint.Y - minPoint.Y));
                        if (AreaMassProperties.Compute(a).Centroid.Y > AreaMassProperties.Compute(b).Centroid.Y)
                        {
                            result.reboundingVector.Y *= -1;
                        }
                    }
                    else
                    {
                        result.reboundingVector = new Vector2d(-(maxPoint.X - minPoint.X), 0);
                        if (AreaMassProperties.Compute(a).Centroid.X > AreaMassProperties.Compute(b).Centroid.X)
                        {
                            result.reboundingVector.X *= -1;
                        }
                    }
                }
            }
            else
            {
                result.intersect        = false;
                result.reboundingVector = Vector2d.Unset;
                result.unionCurve       = null;
            }
            return(result);
        }
Пример #5
0
        public static PolyNode mergeSubjPathAndClipPath(Path subj_p, Path clip_p)
        {
            Clipper c = new Clipper(Clipper.ioPreserveCollinear);

            c.AddPath(subj_p, PolyType.ptSubject, true);
            c.AddPath(clip_p, PolyType.ptClip, true);

            PolyTree polyTree = new AXClipperLib.PolyTree();

            c.Execute(ClipType.ctDifference, polyTree, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

            return(polyTree);
        }
Пример #6
0
        /// <summary>
        /// Checks whether this key overlaps with another specified key definition.
        /// </summary>
        /// <param name="otherKey">The other key to check for overlapping on.</param>
        /// <returns><c>True</c> if the keys overlap, <c>false</c> otherwise.</returns>
        public bool BordersWith(MouseKeyDefinition otherKey)
        {
            var clipper = new Clipper();

            clipper.AddPath(this.GetPath(), PolyType.ptSubject, true);
            clipper.AddPath(otherKey.GetPath(), PolyType.ptClip, true);

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

            clipper.Execute(ClipType.ctUnion, union);

            return(union.Count == 1);
        }
Пример #7
0
        /// <summary>
        /// Tests if the supplied Polygon shares one or more areas with this Polygon when compared on a shared plane.
        /// </summary>
        /// <param name="polygon">The Polygon to compare with this Polygon.</param>
        /// <returns>
        /// Returns true if the supplied Polygon shares one or more areas with this Polygon when compared on a shared plane. Returns false if the supplied Polygon does not share an area with this Polygon or if the supplied Polygon is null.
        /// </returns>
        public bool Intersects(Polygon polygon)
        {
            if (polygon == null)
            {
                return(false);
            }
            var clipper  = new Clipper();
            var solution = new List <List <IntPoint> >();

            clipper.AddPath(this.ToClipperPath(), PolyType.ptSubject, true);
            clipper.AddPath(polygon.ToClipperPath(), PolyType.ptClip, true);
            clipper.Execute(ClipType.ctIntersection, solution);
            return(solution.Count != 0);
        }
Пример #8
0
        public void MergeAdjacentRegions(IAdminEntity entity)
        {
            // Searches for adjacency - merges in first region
            int regionCount = entity.regions.Count;

            for (int k = 0; k < regionCount; k++)
            {
                Region region1 = entity.regions [k];
                if (region1 == null || region1.points == null || region1.points.Length == 0)
                {
                    continue;
                }
                for (int j = k + 1; j < regionCount; j++)
                {
                    Region region2 = entity.regions [j];
                    if (region2 == null || region2.points == null || region2.points.Length == 0)
                    {
                        continue;
                    }
                    if (!region1.Intersects(region2))
                    {
                        continue;
                    }
                    RegionMagnet(region1, region2);
                    Clipper clipper = new Clipper();
                    clipper.AddPath(region1, PolyType.ptSubject);
                    clipper.AddPath(region2, PolyType.ptClip);
                    clipper.Execute(ClipType.ctUnion);

                    // Add new neighbours
                    int rnCount = region2.neighbours.Count;
                    for (int n = 0; n < rnCount; n++)
                    {
                        Region neighbour = region2.neighbours [n];
                        if (neighbour != null && neighbour != region1 && !region1.neighbours.Contains(neighbour))
                        {
                            region1.neighbours.Add(neighbour);
                        }
                    }
                    // Remove merged region

                    entity.regions.RemoveAt(j);
                    region1.sanitized = false;
                    j = k;
                    regionCount--;
                    entity.mainRegionIndex = 0;                         // will need to refresh country definition later in the process
                }
            }
        }
Пример #9
0
        private IEnumerable <IPath> Clip(IPath shape, params IPath[] hole)
        {
            Clipper clipper = new Clipper();

            clipper.AddPath(shape, ClippingType.Subject);
            if (hole != null)
            {
                foreach (IPath s in hole)
                {
                    clipper.AddPath(s, ClippingType.Clip);
                }
            }

            return(clipper.GenerateClippedShapes());
        }
Пример #10
0
        /// <summary>
        /// Clips the rulings to the area.
        /// <para>Warning: force xMin to be in p1, xMax to be in p2, might lead to odd stuff if not vertical or horizontal.</para>
        /// </summary>
        /// <param name="rulings"></param>
        /// <param name="area"></param>
        public static List <Ruling> CropRulingsToArea(IReadOnlyList <Ruling> rulings, PdfRectangle area)
        {
            // use clipper
            var clipper = new Clipper();

            clipper.AddPath(Clipper.ToClipperIntPoints(area), PolyType.ptClip, true);

            foreach (Ruling r in rulings)
            {
                clipper.AddPath(Clipper.ToClipperIntPoints(r), PolyType.ptSubject, false);
            }

            var solutions = new PolyTree();

            if (clipper.Execute(ClipType.ctIntersection, solutions))
            {
                List <Ruling> rv = new List <Ruling>();
                foreach (var solution in solutions.Childs)
                {
                    var    x0   = solution.Contour[0].X / 10_000.0;
                    var    x1   = solution.Contour[1].X / 10_000.0;
                    double xmin = Math.Min(x0, x1);
                    double xmax = Math.Max(x0, x1);

                    // warning
                    // force xmin to be in p1, xmax to be in p2, might lead to odd stuff if not vertic or horiz
                    // do not bother with y for the moment, will throw an error anyway in Ruling()
                    // needed for testExtractColumnsCorrectly3() and testSpreadsheetExtractionIssue656() to succeed
                    rv.Add(new Ruling(new PdfPoint(xmin, solution.Contour[0].Y / 10_000.0),
                                      new PdfPoint(xmax, solution.Contour[1].Y / 10_000.0)));
                }
                return(rv);
            }
            else
            {
                return(new List <Ruling>());
            }

            //List<Ruling> rv = new List<Ruling>();
            //foreach (Ruling r in rulings)
            //{
            //    if (r.intersects(area))
            //    {
            //        rv.Add(r.intersect(area));
            //    }
            //}
            //return rv;
        }
Пример #11
0
        void CountrySubstractCountryEnclaves(int countryIndex, Region region, Poly2Tri.Polygon poly)
        {
            List <Region> negativeRegions = new List <Region> ();
            int           countryCount    = _countriesOrderedBySize.Count;

            for (int ops = 0; ops < countryCount; ops++)
            {
                int op = _countriesOrderedBySize [ops];
                if (op == countryIndex)
                {
                    continue;
                }
                Country opCountry       = _countries [op];
                Region  opCountryRegion = opCountry.regions [opCountry.mainRegionIndex];
                if (opCountryRegion.points.Length >= 5 && opCountry.mainRegion.rect2DArea < region.rect2DArea && opCountryRegion.rect2D.Overlaps(region.rect2D, true))
                {
                    if (region.Contains(opCountryRegion))                               // just check main region of province for speed purposes
                    {
                        negativeRegions.Add(opCountryRegion.Clone());
                    }
                }
            }
            // Collapse negative regions in big holes
            for (int nr = 0; nr < negativeRegions.Count - 1; nr++)
            {
                for (int nr2 = nr + 1; nr2 < negativeRegions.Count; nr2++)
                {
                    if (negativeRegions [nr].Intersects(negativeRegions [nr2]))
                    {
                        Clipper clipper = new Clipper();
                        int     control = negativeRegions [nr].points.Length;
                        clipper.AddPath(negativeRegions [nr], PolyType.ptSubject);
                        clipper.AddPath(negativeRegions [nr2], PolyType.ptClip);
                        clipper.Execute(ClipType.ctUnion);
                        negativeRegions.RemoveAt(nr2);
                        nr = -1;
                        break;
                    }
                }
            }

            // Substract holes
            for (int r = 0; r < negativeRegions.Count; r++)
            {
                Poly2Tri.Polygon polyHole = new Poly2Tri.Polygon(negativeRegions [r].points);
                poly.AddHole(polyHole);
            }
        }
Пример #12
0
        public void addShapeCollider(List <Vector2> points, Vector3 position)
        {
            points = new List <Vector2>(points);

            updatePointList(points, position);

            List <List <IntPoint> > pathclip = filterCollider(Vector2ArrayToListIntPoint(points.ToArray()));

            if (pathclip.Count == 0)
            {
                return;
            }

            if (collider.pathCount == 0)
            {
                for (int i = 0; i < pathclip.Count; i++)
                {
                    collider.pathCount = i + 1;
                    collider.SetPath(i, ListIntPointToVector2Array(pathclip[i]));
                }
                return;
            }
            else
            {
                Clipper c = new Clipper();

                foreach (List <IntPoint> p in pathclip)
                {
                    c.AddPath(p, PolyType.ptClip, true);
                }

                for (int i = 0; i < collider.pathCount; i++)
                {
                    c.AddPath(Vector2ArrayToListIntPoint(collider.GetPath(i)), PolyType.ptSubject, true);
                }

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

                c.Execute(ClipType.ctUnion, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

                collider.pathCount = solution.Count;

                for (int i = 0; i < solution.Count; i++)
                {
                    collider.SetPath(i, ListIntPointToVector2Array(solution[i]));
                }
            }
        }
    /// <summary>
    /// Sets the Collider in Children as Difference or Intersection from baseCollider with Clippers
    /// </summary>
    /// <param name="ct">ct.Intersection or ct.Difference based on Operation you want to do</param>
    /// <param name="clippers">list of Polygons to intersect/difference the baseCollider</param>
    void SetColliderAs(ClipType ct, List <PolygonCollider2D> clippers)
    {
        List <List <IntPoint> > solution = new List <List <IntPoint> >();
        Clipper clipper = new Clipper();

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

        for (int j = 0; j < baseCollider.Count; j++)
        {
            subj.Add(ConvertToIntPoint(transform.localToWorldMatrix * baseCollider[j] + (Vector4)transform.position));
        }

        foreach (PolygonCollider2D cl in clippers)
        {
            List <IntPoint> clip = new List <IntPoint>();
            for (int j = 0; j < cl.points.Length; j++)
            {
                clip.Add(ConvertToIntPoint(cl.transform.localToWorldMatrix * cl.points[j] + (Vector4)cl.transform.position));
            }
            clipper.AddPath(clip, PolyType.ptClip, true);
        }

        clipper.AddPath(subj, PolyType.ptSubject, true);

        if (ct == ClipType.ctDifference)
        {
            clipper.Execute(ct, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
        }

        if (ct == ClipType.ctIntersection)
        {
            clipper.Execute(ct, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
        }

        childPolyCollider.pathCount = solution.Count;

        for (int i = 0; i < solution.Count; i++)
        {
            List <Vector2> unitedPolygon = new List <Vector2>();

            foreach (IntPoint point in solution[i])
            {
                unitedPolygon.Add(transform.worldToLocalMatrix * (ConvertToVector2(point) - (Vector2)transform.position));
            }

            childPolyCollider.SetPath(i, unitedPolygon.ToArray());
        }
    }
Пример #14
0
        /// <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>
        /// Updates the key definition to occupy a region of itself plus the specified other keys.
        /// </summary>
        /// <param name="keys">The keys to union with.</param>
        /// <returns>A new key definition with the updated region.</returns>
        private KeyboardKeyDefinition UnionWith(IList <KeyboardKeyDefinition> keys)
        {
            var newBoundaries = this.Boundaries.Select(b => new TPoint(b.X, b.Y)).ToList();

            if (keys.Any())
            {
                var cl = new Clipper();
                cl.AddPath(this.GetPath(), PolyType.ptSubject, true);
                cl.AddPaths(keys.Select(x => x.GetPath()).ToList(), PolyType.ptClip, true);
                var union = new List <List <IntPoint> >();
                cl.Execute(ClipType.ctUnion, union);

                if (union.Count > 1)
                {
                    throw new ArgumentException("Cannot union two non-overlapping keys.");
                }

                newBoundaries = union.Single().ConvertAll <TPoint>(x => x);
            }

            return(new KeyboardKeyDefinition(
                       this.Id,
                       newBoundaries,
                       this.KeyCodes,
                       this.Text,
                       this.ShiftText,
                       this.ChangeOnCaps));
        }
Пример #16
0
        /// <summary>
        /// 处理主通道占据空间 直接 转义为 clipper 语境
        /// </summary>
        public Paths HandleMainRoadSpace(CurveArray mianRoadCurves, CurveArray roadCurves, double MainRoadWidth, double roadWidth)
        {
            int   mainRoadCurvesCount = mianRoadCurves.Size;
            Paths mainRoadRegion      = new Paths();//地库主车道占据空间

            if (mainRoadCurvesCount == 0)
            {
                return(mainRoadRegion);
            }
            else if (mainRoadCurvesCount > 0)
            {
                Paths wdMainOffset = new Paths();//拿到所有的主车道偏移后的围合点,需要将围合区域做并集
                foreach (Curve _curve in mianRoadCurves)
                {
                    wdMainOffset.Add(clipper_methods._GetOffsetPonts_clipper_line(_curve, MainRoadWidth / 2));//添加每根车道中心线偏移后的矩形点集
                }
                foreach (Curve _curve in roadCurves)
                {
                    wdMainOffset.Add(clipper_methods._GetOffsetPonts_clipper_line(_curve, roadWidth / 2)); //添加每根车道中心线偏移后的矩形点集
                }
                Clipper cTemp = new Clipper();                                                             //开展 所有线段的偏移矩形点击进行 clipper 合并
                cTemp.AddPaths(wdMainOffset, PolyType.ptSubject, true);
                cTemp.AddPath(wdMainOffset.First(), PolyType.ptClip, true);
                cTemp.Execute(ClipType.ctUnion, mainRoadRegion, PolyFillType.pftNonZero, PolyFillType.pftNonZero);//需要把每根主车道偏移出的空间,进行合并
            }
            return(mainRoadRegion);
        }
Пример #17
0
        public void Execute(ref List <List <IntPoint> > solution, double delta)
        {
            solution.Clear();
            FixOrientations();
            DoOffset(delta);
            Clipper clipper = new Clipper(0);

            clipper.AddPaths(m_destPolys, PolyType.ptSubject, true);
            if (delta > 0.0)
            {
                clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
            }
            else
            {
                IntRect         bounds = ClipperBase.GetBounds(m_destPolys);
                List <IntPoint> list   = new List <IntPoint>(4);
                list.Add(new IntPoint(bounds.left - 10, bounds.bottom + 10));
                list.Add(new IntPoint(bounds.right + 10, bounds.bottom + 10));
                list.Add(new IntPoint(bounds.right + 10, bounds.top - 10));
                list.Add(new IntPoint(bounds.left - 10, bounds.top - 10));
                clipper.AddPath(list, PolyType.ptSubject, true);
                clipper.ReverseSolution = true;
                clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                if (solution.Count > 0)
                {
                    solution.RemoveAt(0);
                }
            }
        }
Пример #18
0
        /// <summary>
        /// Returns true if the rectangle and the line intersect.
        /// Takes in account the rectangle border by expanding its area by 1 on each side.
        /// <para>Uses clipper.</para>
        /// </summary>
        /// <param name="line">The line to check.</param>
        public bool IntersectsLine(PdfLine line)
        {
            var clipper = new Clipper();

            clipper.AddPath(Clipper.ToClipperIntPoints(Expand(this.BoundingBox)), PolyType.ptClip, true);

            clipper.AddPath(Clipper.ToClipperIntPoints(line), PolyType.ptSubject, false);

            var solutions = new PolyTree();

            if (clipper.Execute(ClipType.ctIntersection, solutions))
            {
                return(solutions.Childs.Count > 0);
            }
            return(false);
        }
Пример #19
0
        private void UpdatePlayerOverlap()
        {
            if (CurrentOnsetDrawing == _collidedBeatIndex || CurrentOnset >= Onsets.Count)
            {
                ParentStage.Overlap = 0;
                return;
            }
            var c = new Clipper();

            c.AddPaths(_onsetDrawing.GetPolygonBounds(CurrentOnsetDrawing), PolyType.ptSubject, true);
            if (CurrentOnsetDrawing < _onsetDrawing.DrawingCount - 1)
            {
                c.AddPaths(_onsetDrawing.GetPolygonBounds(CurrentOnsetDrawing + 1), PolyType.ptSubject, true);
            }
            c.AddPath(Player.GetBounds(), PolyType.ptClip, true);

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

            c.Execute(ClipType.ctIntersection, soln);

            //ParentStage.Overlap = soln.Count > 0 ? (int)((Clipper.Area(soln[0]) / Clipper.Area(Player.GetBounds())) * 100) : 0;
            ParentStage.Overlap = 0;
            foreach (var a in soln)
            {
                ParentStage.Overlap += (int)((Clipper.Area(a) / Clipper.Area(Player.GetBounds())) * (100.0f));
            }
            if (ParentStage.Overlap > 80)
            {
                ParentStage.Multiplier = -1;
                Player.Hits++;
                _collidedBeatIndex = CurrentOnsetDrawing;
                //_polygons[_collidedBeatIndex].SetColour(_colours.EvenCollisionColour, _colours.EvenCollisionOutlineColour, _colours.OddCollisionColour, _colours.OddCollisionOutlienColour);
                CenterPolygon.SetColour(_colours.EvenCollisionColour, _colours.EvenCollisionOutlineColour, _colours.OddCollisionColour, _colours.OddCollisionOutlienColour);
            }
        }
Пример #20
0
        public void GenerateMarchingSquaresAndLines(Action <double, string> progressReporter, ImageBuffer image, IThresholdFunction thresholdFunction)
        {
            if (image != null)
            {
                // Regenerate outline
                var marchingSquaresData = new MarchingSquaresByte(
                    image,
                    thresholdFunction.ZeroColor,
                    thresholdFunction.Threshold,
                    0);

                progressReporter?.Invoke(0, "Creating Outline");

                marchingSquaresData.CreateLineSegments();
                progressReporter?.Invoke(.1, null);

                int pixelsToIntPointsScale = 1000;
                var lineLoops = marchingSquaresData.CreateLineLoops(pixelsToIntPointsScale);

                progressReporter?.Invoke(.15, null);

                var min = new IntPoint(-10, -10);
                var max = new IntPoint(10 + image.Width * pixelsToIntPointsScale, 10 + image.Height * pixelsToIntPointsScale);

                var boundingPoly = new Polygon();
                boundingPoly.Add(min);
                boundingPoly.Add(new IntPoint(min.X, max.Y));
                boundingPoly.Add(max);
                boundingPoly.Add(new IntPoint(max.X, min.Y));

                // now clip the polygons to get the inside and outside polys
                var clipper = new Clipper();
                clipper.AddPaths(lineLoops, PolyType.ptSubject, true);
                clipper.AddPath(boundingPoly, PolyType.ptClip, true);

                var polygonShape = new Polygons();
                progressReporter?.Invoke(.3, null);

                clipper.Execute(ClipType.ctIntersection, polygonShape);

                progressReporter?.Invoke(.55, null);

                polygonShape = Clipper.CleanPolygons(polygonShape, 100);

                progressReporter?.Invoke(.75, null);

                VertexStorage rawVectorShape = polygonShape.PolygonToPathStorage();

                var aabb   = this.VisibleMeshes().FirstOrDefault().GetAxisAlignedBoundingBox();
                var xScale = aabb.XSize / image.Width;

                var affine = Affine.NewScaling(1.0 / pixelsToIntPointsScale * xScale);
                affine *= Affine.NewTranslation(-aabb.XSize / 2, -aabb.YSize / 2);

                rawVectorShape.transform(affine);
                this.VertexSource = rawVectorShape;

                progressReporter?.Invoke(1, null);
            }
        }
Пример #21
0
        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);
        }
Пример #22
0
        //public Paths intersection(Paths other_pologon)
        //{
        //    Paths solution3 = new Paths();
        //    Clipper co1 = new Clipper(0);          //不知道怎么用,在Polygons中有使用
        //    co1.AddPaths(polygons, ClipperLib.PolyType.ptSubject, true);
        //    co1.AddPaths(other_pologon,ClipperLib.PolyType.ptClip,true);
        //    co1.Execute(ClipperLib.ClipType.ctIntersection, solution3);
        //    return solution3;
        //}


        public Paths intersection(Paths other_pologon, int rownum, ref List <maddtionpologonIndex> outAddtionPathsIndex)
        {
            Paths solution4 = new Paths();
            Path  tempnull  = new Path();  //用来占位用   2016-04-22

            for (int j = 0; j < polygons.Count; j++)
            {
                Paths   solution3 = new Paths();
                Clipper co1       = new Clipper(0);   //不知道怎么用,在Polygons中有使用

                //之前使用04_22晚间
                co1.AddPath(polygons[j], ClipperLib.PolyType.ptSubject, true);
                co1.AddPaths(other_pologon, ClipperLib.PolyType.ptClip, true);

                //co1.AddPath(temppath, ClipperLib.PolyType.ptClip, true);
                //co1.AddPaths(other_pologon, ClipperLib.PolyType.ptSubject, true);
                co1.Execute(ClipperLib.ClipType.ctIntersection, solution3);

                //为了占位,形成n*n的格子,不相交的地方用空格子占位,由于一次只比较一个格子,所以只有一个分区块,不考虑被分成两部分
                if (solution3.Count < 1)
                {
                    solution4.Add(tempnull);
                }
                else
                {
                    solution4.Add(solution3[0]);
                    for (int i = 1; i < solution3.Count; ++i)
                    {
                        outAddtionPathsIndex.Add(new maddtionpologonIndex(solution3[i], rownum, j));
                    }
                }
            }
            return(solution4);
        }
Пример #23
0
        private void Clip(NavigationPolygon floor, NavigationPolygons staticObjects)
        {
            Clipper clipper = new Clipper();

            if (!clipper.AddPath(floor, PolyType.ptSubject, true))
            {
                throw new Exception("Can't add Paths (Subject).");
            }

            if (staticObjects.Count > 0 && !clipper.AddPaths(staticObjects, PolyType.ptClip, true))
            {
                throw new Exception("Can't add Paths (Clip).");
            }

            // we do it twice (it's easier than deep copy the polygons), since this is loading screen time... We don't mind performance too much here
            if (!clipper.Execute(ClipType.ctDifference, floorWithStaticObjects, PolyFillType.pftNonZero))
            {
                throw new Exception("Can't clip floorWithStaticObjects.");
            }

            if (!clipper.Execute(ClipType.ctDifference, FloorWithDynamicObjects, PolyFillType.pftNonZero))
            {
                throw new Exception("Can't clip floorWithStaticObjects.");
            }

            clipper.Reset();
        }
Пример #24
0
        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);
        }
Пример #25
0
        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);
        }
Пример #26
0
        //------------------------------------------------------------------------------

        public void Execute(ref List <List <IntPoint> > solution, double delta)
        {
            solution.Clear();
            FixOrientations();
            DoOffset(delta);
            //now clean up 'corners' ...
            Clipper clpr = new Clipper();

            clpr.AddPaths(m_destPolys, PolyType.ptSubject, true);
            if (delta > 0)
            {
                clpr.Execute(ClipType.ctUnion, solution,
                             PolyFillType.pftPositive, PolyFillType.pftPositive);
            }
            else
            {
                IntRect         r     = Clipper.GetBounds(m_destPolys);
                List <IntPoint> outer = new List <IntPoint>(4);

                outer.Add(new IntPoint(r.left - 10, r.bottom + 10));
                outer.Add(new IntPoint(r.right + 10, r.bottom + 10));
                outer.Add(new IntPoint(r.right + 10, r.top - 10));
                outer.Add(new IntPoint(r.left - 10, r.top - 10));

                clpr.AddPath(outer, PolyType.ptSubject, true);
                clpr.ReverseSolution = true;
                clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                if (solution.Count > 0)
                {
                    solution.RemoveAt(0);
                }
            }
        }
Пример #27
0
        /// <summary>
        /// Constructs the geometric difference between this Polygon and the supplied Polygons.
        /// </summary>
        /// <param name="difPolys">The list of intersecting Polygons.</param>
        /// <param name="tolerance">An optional tolerance value.</param>
        /// <returns>
        /// Returns a list of Polygons representing the subtraction of the supplied Polygons from this Polygon.
        /// Returns null if the area of this Polygon is entirely subtracted.
        /// Returns a list containing a representation of the perimeter of this Polygon if the two Polygons do not intersect.
        /// </returns>
        public IList <Polygon> Difference(IList <Polygon> difPolys, double tolerance = Vector3.EPSILON)
        {
            var thisPath  = this.ToClipperPath(tolerance);
            var polyPaths = new List <List <IntPoint> >();

            foreach (Polygon polygon in difPolys)
            {
                polyPaths.Add(polygon.ToClipperPath(tolerance));
            }
            Clipper clipper = new Clipper();

            clipper.AddPath(thisPath, PolyType.ptSubject, true);
            clipper.AddPaths(polyPaths, PolyType.ptClip, true);
            var solution = new List <List <IntPoint> >();

            clipper.Execute(ClipType.ctDifference, solution);
            if (solution.Count == 0)
            {
                return(null);
            }
            var polygons = new List <Polygon>();

            foreach (List <IntPoint> path in solution)
            {
                try
                {
                    polygons.Add(PolygonExtensions.ToPolygon(path.Distinct().ToList(), tolerance));
                }
                catch
                {
                    // swallow invalid polygons
                }
            }
            return(polygons);
        }
Пример #28
0
        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);
        }
Пример #29
0
        /// <summary>
        /// Constructs the geometric difference between this Polygon and the supplied Polygons.
        /// </summary>
        /// <param name="difPolys">The list of intersecting Polygons.</param>
        /// <returns>
        /// Returns a list of Polygons representing the subtraction of the supplied Polygons from this Polygon.
        /// Returns null if the area of this Polygon is entirely subtracted.
        /// Returns a list containing a representation of the perimeter of this Polygon if the two Polygons do not intersect.
        /// </returns>
        public IList <Polygon> Difference(IList <Polygon> difPolys)
        {
            var thisPath  = this.ToClipperPath();
            var polyPaths = new List <List <IntPoint> >();

            foreach (Polygon polygon in difPolys)
            {
                polyPaths.Add(polygon.ToClipperPath());
            }
            Clipper clipper = new Clipper();

            clipper.AddPath(thisPath, PolyType.ptSubject, true);
            clipper.AddPaths(polyPaths, PolyType.ptClip, true);
            var solution = new List <List <IntPoint> >();

            clipper.Execute(ClipType.ctDifference, solution);
            if (solution.Count == 0)
            {
                return(null);
            }
            var polygons = new List <Polygon>();

            foreach (List <IntPoint> path in solution)
            {
                polygons.Add(PolygonExtensions.ToPolygon(path.Distinct().ToList()));
            }
            return(polygons);
        }
Пример #30
0
        IEnumerator AddHexagons(IAdminEntity[] entities)
        {
            Cell[]  cells   = _map.cells;
            Clipper clipper = new Clipper();

            for (int j = 0; j < cells.Length; j++)
            {
                if (j % 100 == 0)
                {
                    if (hexifyContext.progress != null)
                    {
                        if (hexifyContext.progress((float)j / cells.Length, hexifyContext.title, "Pass 3/6: adding hexagons to frontiers..."))
                        {
                            cancelled = true;
                            hexifyContext.finish(true);
                            yield break;
                        }
                    }
                    yield return(null);
                }

                int entityIndex = procCells [j].entityIndex;
                if (entityIndex < 0)
                {
                    continue;
                }
                Cell cell = cells [j];

                // Create a region for the cell
                IAdminEntity entity    = entities [entityIndex];
                Vector2[]    newPoints = new Vector2[6];
                for (int k = 0; k < 6; k++)
                {
                    newPoints [k].x = hexagonPoints [k].x + cell.center.x;
                    newPoints [k].y = hexagonPoints [k].y + cell.center.y;
                }
                procCells [j].cellRegion = new Region(entity, entity.regions.Count);
                procCells [j].cellRegion.UpdatePointsAndRect(newPoints);

                // Add region to target entity's polygon - only if the entity is touching or crossing target entity frontier
                Region targetRegion = procCells [j].entityRegion;
                clipper.Clear();
                clipper.AddPath(targetRegion, PolyType.ptSubject);
                clipper.AddPath(procCells [j].cellRegion, PolyType.ptClip);
                clipper.Execute(ClipType.ctUnion);
            }
        }
Пример #31
0
        //------------------------------------------------------------------------------
        public List<List<Point>> Execute(double deltap, double eps = double.Epsilon)
        {
            var solution = new List<List<Point>>();
            FixPerimeters();
            DoOffset(deltap, eps);
            //now clean up 'corners' ...

            var clpr = new Clipper();

            clpr.AddPaths(destPolys, PolyType.Subject);

            if (deltap > 0)
            {
                clpr.Execute(ClipType.Union, solution, PolyFillType.Positive, PolyFillType.Positive);
            }
            else
            {
                var r = destPolys.GetBounds();

                var outer = new List<Point>(4)
                {
                    new Point(r.Left - 10, r.Bottom + 10),
                    new Point(r.Right + 10, r.Bottom + 10),
                    new Point(r.Right + 10, r.Top - 10),
                    new Point(r.Left - 10, r.Top - 10)
                };

                clpr.AddPath(outer, PolyType.Subject);
                clpr.ReverseSolution = true;
                clpr.Execute(ClipType.Union, solution, PolyFillType.Negative, PolyFillType.Negative);
                if (solution.Count > 0) solution.RemoveAt(0);
            }

            return solution;
        }
Пример #32
0
		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;
		}
Пример #33
0
 private static void AddPath(Clipper clipper, Path path) {
     foreach (Subpath subpath in path.Subpaths) {
         if (!subpath.IsSinglePointClosed() && !subpath.IsSinglePointOpen()) {
             IList<Point2D> linearApproxPoints = subpath.GetPiecewiseLinearApproximation();
             clipper.AddPath(ConvertToIntPoints(linearApproxPoints), PolyType.ptSubject, subpath.Closed);
         }
     }
 }
Пример #34
0
 private static void AddRect(Clipper clipper, Point2D[] rectVertices, PolyType polyType) {
     clipper.AddPath(ConvertToIntPoints(new List<Point2D>(rectVertices)), polyType, true);
 }