public static MultiPolycurve CreateEmpty() { var result = new MultiPolycurve(new List <Linestring>(0)); result.SetEmpty(); return(result); }
public override MultiLinestring Clone() { var result = new MultiPolycurve(Linestrings) { //Id = Id }; return(result); }
/// <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); }