Пример #1
0
        private static List <Linestring> RemoveContainedExistingIslands <T>(
            [NotNull] T fromPolygon,
            [NotNull] Linestring cookieCutter,
            double tolerance) where T : MultiLinestring
        {
            List <Linestring> existingInnerRings = fromPolygon
                                                   .GetLinestrings()
                                                   .Where(l => l.ClockwiseOriented == false)
                                                   .ToList();

            Assert.NotNull(cookieCutter.ClockwiseOriented);

            var containedExistingIslands = new List <Linestring>();

            foreach (Linestring existingInnerRing in existingInnerRings)
            {
                bool?islandWithinCookie = GeomRelationUtils.AreaContainsXY(
                    cookieCutter, existingInnerRing.StartPoint, tolerance, true);

                // TODO: handle the case where the inner ring touches cutter in StartPoint
                if (islandWithinCookie == true)
                {
                    containedExistingIslands.Add(existingInnerRing);
                    fromPolygon.RemoveLinestring(existingInnerRing);
                }
            }

            return(containedExistingIslands);
        }
Пример #2
0
        /// <summary>
        /// Returns source rings disjoint from target and target rings disjoint from source.
        /// </summary>
        /// <param name="ringPredicate"></param>
        /// <returns></returns>
        private IEnumerable <Linestring> GetRingsDisjointFromOtherPoly(
            Predicate <Linestring> ringPredicate)
        {
            var result = new List <Linestring>();

            // W.r.t. AreaContainsXY returning null: if the start point is on the boundary there
            // are duplicate rings which need to be identified elsewhere.
            ISegmentList target = _subcurveNavigator.Target;

            foreach (Linestring ring in _subcurveNavigator.GetNonIntersectedSourceRings()
                     .Where(r => ringPredicate(r)))
            {
                bool?contains = GeomRelationUtils.AreaContainsXY(
                    target, ring.StartPoint, _subcurveNavigator.Tolerance);

                if (contains == false)
                {
                    // disjoint
                    result.Add(ring);
                }
            }

            ISegmentList source = _subcurveNavigator.Source;

            foreach (Linestring ring in _subcurveNavigator.GetNonIntersectedTargets()
                     .Where(r => ringPredicate(r)))
            {
                bool?contains = GeomRelationUtils.AreaContainsXY(
                    source, ring.StartPoint, _subcurveNavigator.Tolerance);

                if (contains == false)
                {
                    result.Add(ring);
                }
            }

            return(result);
        }
Пример #3
0
        private static int GetContainingRingIndex([NotNull] MultiLinestring polygon,
                                                  [NotNull] Linestring containedRing,
                                                  double tolerance,
                                                  out bool ringsAreEqual,
                                                  out IntersectionPoint3D touchPoint)
        {
            IList <IntersectionPoint3D> intersectionPoints =
                GeomTopoOpUtils.GetIntersectionPoints(polygon, containedRing, tolerance);

            ringsAreEqual = false;
            touchPoint    = null;

            // Equal to outer ring -> removes outer ring in original
            // or equal to inner ring -> ignore cookie cutter
            if (intersectionPoints.Count == 2 &&
                intersectionPoints[0].SourcePartIndex == intersectionPoints[1].SourcePartIndex &&
                intersectionPoints[0].Point.Equals(intersectionPoints[1].Point) &&
                intersectionPoints[0].Type == IntersectionPointType.LinearIntersectionStart &&
                intersectionPoints[1].Type == IntersectionPointType.LinearIntersectionEnd)
            {
                ringsAreEqual = true;
                return(intersectionPoints[0].SourcePartIndex);
            }

            var outerRingIntersections =
                intersectionPoints
                .Where(i => polygon.GetLinestring(i.SourcePartIndex).ClockwiseOriented == true)
                .ToList();

            // Touching outer ring in one point -> boundary loop in original
            if (outerRingIntersections.Count > 0)
            {
                Assert.True(outerRingIntersections.Count < 2,
                            "Unexpected number of touching points.");

                touchPoint = outerRingIntersections[0];

                return(touchPoint.SourcePartIndex);
            }

            // Inside an inner ring -> ignore cookie cutter
            for (int i = 0; i < polygon.PartCount; i++)
            {
                Linestring ring = polygon.GetLinestring(i);

                if (ring.ClockwiseOriented == true)
                {
                    continue;
                }

                int currentIdx = i;

                bool?areaContainsXY = GeomRelationUtils.AreaContainsXY(
                    ring, containedRing,
                    intersectionPoints.Where(ip => ip.SourcePartIndex == currentIdx),
                    tolerance, true);

                if (areaContainsXY == true)
                {
                    return(i);
                }
            }

            // Inside an outer ring but not an inner ring: Add as island
            for (int i = 0; i < polygon.PartCount; i++)
            {
                Linestring ring = polygon.GetLinestring(i);

                if (ring.ClockwiseOriented == false)
                {
                    continue;
                }

                if (GeomRelationUtils.AreaContainsXY(ring, containedRing.StartPoint,
                                                     tolerance) == true)
                {
                    return(i);
                }
            }

            return(-1);
        }