Example #1
0
        public static MultiPolycurve CreateEmpty()
        {
            var result = new MultiPolycurve(new List <Linestring>(0));

            result.SetEmpty();

            return(result);
        }
Example #2
0
        public override MultiLinestring Clone()
        {
            var result = new MultiPolycurve(Linestrings)
            {
                //Id = Id
            };

            return(result);
        }
Example #3
0
        /// <summary>
        /// Cuts the source ring using the target and returns separate lists
        /// of result rings on the left/right side of the cut line.
        /// </summary>
        /// <param name="leftPolys">Result polygons on the left side of the cut line.</param>
        /// <param name="rightPolys">Result polygons on the right side of the cut line.</param>
        /// <param name="clipPolys"></param>
        /// <param name="undefinedSidePolys"></param>
        /// <param name="unCutParts"></param>
        /// <returns>Whether the cut operation was successful or not.</returns>
        public bool CutXY([NotNull] out IList <RingGroup> leftPolys,
                          [NotNull] out IList <RingGroup> rightPolys,
                          [NotNull] out IList <RingGroup> clipPolys,
                          [NotNull] out IList <MultiLinestring> undefinedSidePolys,
                          [NotNull] out MultiLinestring unCutParts)
        {
            Assert.ArgumentCondition(_subcurveNavigator.Source.IsClosed, "source must be closed.");

            // Based on Weiler–Atherton clipping algorithm, added specific logic for
            // linear intersections, un-closed target lines and multi-parts.
            // Potential enhancements: Do not insert phantom points!

            IList <Linestring> rightRings = GetRightSideRings();
            IList <Linestring> leftRings  = GetLeftSideRings();

            IList <Linestring> duplicates = new List <Linestring>();

            if (!_subcurveNavigator.Target.IsClosed &&
                _subcurveNavigator.AreIntersectionPointsNonSequential())
            {
                // Cut backs result in duplicates which are both on the left and the right!
                duplicates = RemoveDuplicateRings(leftRings, rightRings);
            }

            // Assign the cut inner rings (anti-clockwise) to un-cut outer rings...
            var unCutOuterRings = _subcurveNavigator.GetNonIntersectedSourceRings()
                                  .Where(r => r.ClockwiseOriented != false)
                                  .ToList();

            rightPolys = AssignToResultRingGroups(rightRings, unCutOuterRings);
            leftPolys  = AssignToResultRingGroups(leftRings, unCutOuterRings);

            IList <RingGroup> bothSidePolys = AssignToResultRingGroups(duplicates, unCutOuterRings);

            unCutParts =
                unCutOuterRings.Count == 1
                                        ? (MultiLinestring) new RingGroup(unCutOuterRings[0])
                                        : new MultiPolycurve(unCutOuterRings);

            // Assign the remaining interior rings;
            AssignInteriorRings(rightRings, leftPolys, rightPolys, bothSidePolys, unCutParts,
                                _subcurveNavigator.Tolerance);
            AssignInteriorRings(leftRings, leftPolys, rightPolys, bothSidePolys, unCutParts,
                                _subcurveNavigator.Tolerance);
            AssignInteriorRings(duplicates, leftPolys, rightPolys, bothSidePolys, unCutParts,
                                _subcurveNavigator.Tolerance);

            // Assign the inner rings from the original
            var unCutIslands = _subcurveNavigator.GetNonIntersectedSourceRings()
                               .Where(r => r.ClockwiseOriented == false);

            AssignInteriorRings(unCutIslands, leftPolys, rightPolys, bothSidePolys, unCutParts,
                                _subcurveNavigator.Tolerance);

            // Assign closed cut lines completely contained by an outer ring (and not by an inner ring)
            var unusedCutRings =
                _subcurveNavigator.GetNonIntersectedTargets().Where(t => t.IsClosed);

            undefinedSidePolys = bothSidePolys.Cast <MultiLinestring>().ToList();

            clipPolys = new List <RingGroup>();
            foreach (Linestring unusedCutRing in unusedCutRings)
            {
                MultiLinestring updatedUnCut;
                RingGroup       cookie;
                if (!unCutParts.IsEmpty &&
                    TryCutCookie(unusedCutRing, unCutParts, out updatedUnCut, out cookie))
                {
                    unCutParts = MultiPolycurve.CreateEmpty();
                    undefinedSidePolys.Add(updatedUnCut);
                    clipPolys.Add(cookie);
                    continue;
                }

                RingGroup updatedCut;
                if (TryCutCookie(unusedCutRing, leftPolys, out updatedCut, out cookie))
                {
                    clipPolys.Add(cookie);
                    continue;
                }

                if (TryCutCookie(unusedCutRing, rightPolys, out updatedCut, out cookie))
                {
                    clipPolys.Add(cookie);
                    continue;
                }

                if (TryCutCookie(unusedCutRing, bothSidePolys, out updatedCut, out cookie))
                {
                    clipPolys.Add(cookie);
                }
            }

            return((rightPolys.Count > 0 && leftPolys.Count > 0) ||
                   undefinedSidePolys.Count > 1 || clipPolys.Count > 0);
        }