/// <summary> /// Determines whether the specified closed polycurve contains (including the boundary) the /// specified test geometry. This method ignores the orientation. /// </summary> /// <param name="closedPolycurve"></param> /// <param name="targetSegments"></param> /// <param name="tolerance"></param> /// <param name="knownIntersections"></param> /// <returns></returns> public static bool PolycurveContainsXY( [NotNull] ISegmentList closedPolycurve, [NotNull] Linestring targetSegments, double tolerance, IEnumerable <SegmentIntersection> knownIntersections = null) { if (AreBoundsDisjoint(closedPolycurve, targetSegments, tolerance)) { return(false); } if (knownIntersections == null) { knownIntersections = SegmentIntersectionUtils.GetSegmentIntersectionsXY( closedPolycurve, targetSegments, tolerance); } // TODO: GeomUtils.IEnumerable<IntersectionPoint3D> GetIntersectionPointsWithDeviation() for better performance var intersectionPoints = GeomTopoOpUtils.GetIntersectionPoints(closedPolycurve, targetSegments, tolerance, knownIntersections, false); Pnt3D nonIntersectingTargetPnt = GetNonIntersectingTargetPoint(targetSegments, intersectionPoints); IEnumerable <Pnt3D> checkPoints = nonIntersectingTargetPnt != null ? new[] { nonIntersectingTargetPnt } : targetSegments.GetPoints(); return(checkPoints.All(p => PolycurveContainsXY(closedPolycurve, p, tolerance))); // The check points are assumed not to be on the boundary! }
/// <summary> /// Determines whether the provided rings touch in xy. If available, the spatial index of the second ring is used. /// </summary> /// <param name="ring1"></param> /// <param name="ring2"></param> /// <param name="tolerance"></param> /// <param name="ringsAreDisjoint">Whether the two rings are disjoint.</param> /// <param name="disregardRingOrientation">Whether the ring orientation can be used to determine /// the inside/outside. Use true if the rings are known not to be simple in terms of ring orientation.</param> /// <param name="ring2CanHaveLinearSelfIntersections">Whether the second ring can have self-intersections, /// for example because it is vertical. If true, it will be reported as touching if it does not intersect /// the interior of ring1, even if there are linear intersections in both directions. This does not exactly /// conform with Clementini logic.</param> /// <returns></returns> public static bool TouchesXY([NotNull] Linestring ring1, [NotNull] Linestring ring2, double tolerance, out bool ringsAreDisjoint, bool disregardRingOrientation = false, bool ring2CanHaveLinearSelfIntersections = false) { Assert.ArgumentCondition(ring1.IsClosed && ring2.IsClosed, "Both rings must be closed."); IEnumerable <SegmentIntersection> segmentIntersections = SegmentIntersectionUtils.GetSegmentIntersectionsXY( ring1, ring2, tolerance); ringsAreDisjoint = true; var allIntersections = new List <SegmentIntersection>(); // Quick checks and list collection bool?linearIntersectionsInverted = null; foreach (SegmentIntersection intersection in segmentIntersections) { ringsAreDisjoint = false; if (intersection.SingleInteriorIntersectionFactor != null) { return(false); } if (intersection.HasLinearIntersection) { //// TODO/Experimental: Test with more exception cases //if (intersection.IsPotentialPseudoLinearIntersection( // ring1[intersection.SourceIndex], ring2[intersection.TargetIndex], // tolerance)) //{ // continue; //} if (!intersection.IsSegmentZeroLength2D) { if (!disregardRingOrientation && !intersection.LinearIntersectionInOppositeDirection) { // Optimization if the ring orientation is known to be correct return(false); } if (linearIntersectionsInverted == null) { linearIntersectionsInverted = intersection.LinearIntersectionInOppositeDirection; } else if (linearIntersectionsInverted.Value != intersection.LinearIntersectionInOppositeDirection && !ring2CanHaveLinearSelfIntersections) { return(false); } } } allIntersections.Add(intersection); } IList <IntersectionPoint3D> intersectionPoints = GeomTopoOpUtils.GetIntersectionPoints( ring1, ring2, tolerance, allIntersections, false); if (HasSourceCrossingIntersections(ring1, ring2, intersectionPoints)) { return(false); } // No intersection or no deviation of target from source or all deviations to the same side bool contained = RingsContainEachOther(ring1, ring2, intersectionPoints, tolerance, disregardRingOrientation, ring2CanHaveLinearSelfIntersections); ringsAreDisjoint = ringsAreDisjoint && !contained; return(!contained); }