Example #1
0
        /// <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!
        }
Example #2
0
        /// <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);
        }