Ejemplo n.º 1
0
        private static int AssignInteriorRing([NotNull] Linestring interiorRing,
                                              IEnumerable <RingGroup> resultPolys,
                                              double tolerance)
        {
            int assignmentCount = 0;

            foreach (RingGroup resultPoly in resultPolys)
            {
                if (GeomRelationUtils.PolycurveContainsXY(
                        resultPoly.ExteriorRing, interiorRing.StartPoint, tolerance))
                {
                    resultPoly.AddInteriorRing(interiorRing);
                    assignmentCount++;
                }
            }

            return(assignmentCount);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Creates the list of result ring groups from the processed inner/outer rings and the
        /// unprocessed outer rings by:
        /// - Adding processed outer rings to the output and remove them from the input collection
        /// - For each processed inner rings, that is contained in an un-processed outer ring:
        ///   - Add the unprocessed outer ring together with the inner ring to the result.
        ///   - Remove both the unprocessed outer and the inner ring from the respective input collection.
        /// </summary>
        /// <param name="processedResultRings"></param>
        /// <param name="unprocessedOuterRings"></param>
        /// <returns></returns>
        private IList <RingGroup> AssignToResultRingGroups(
            ICollection <Linestring> processedResultRings,
            ICollection <Linestring> unprocessedOuterRings)
        {
            var result = new List <RingGroup>();

            foreach (Linestring processedResultRing in processedResultRings.ToList())
            {
                if (processedResultRing.ClockwiseOriented != false)
                {
                    result.Add(new RingGroup(processedResultRing));
                    processedResultRings.Remove(processedResultRing);
                }
                else
                {
                    // Intersected (processed) inner rings:
                    // Find the containing un-cut outer ring, assign and remove from un-processed list
                    Linestring containing = unprocessedOuterRings.FirstOrDefault(
                        o => o.ClockwiseOriented == true &&
                        GeomRelationUtils.PolycurveContainsXY(
                            o, processedResultRing.StartPoint, _subcurveNavigator.Tolerance));

                    if (containing != null)
                    {
                        unprocessedOuterRings.Remove(containing);

                        // Add at the beginning to boost performance, assuming a few (or one) large rings contains everything
                        result.Insert(0, new RingGroup(containing, new[] { processedResultRing }));

                        // remove from the list, the remaining inner rings will be assigned afterwards;
                        processedResultRings.Remove(processedResultRing);
                    }
                }
            }

            return(result);
        }
Ejemplo n.º 3
0
        private static bool TryCutCookie <T>([NotNull] T polygon,
                                             [NotNull] Linestring cookieCutter,
                                             double tolerance,
                                             out RingGroup resultCookie,
                                             bool allowEmptyResults = false)
            where T : MultiLinestring
        {
            resultCookie = null;

            if (!GeomRelationUtils.PolycurveContainsXY(
                    polygon, cookieCutter, tolerance))
            {
                return(false);
            }

            // Remove pre-existing interior rings that are completely within cookie cutter
            List <Linestring> containedExistingIslands =
                RemoveContainedExistingIslands(polygon, cookieCutter, tolerance);

            Linestring interiorRing = cookieCutter.Clone();

            Assert.True(interiorRing.IsClosed, "Interior ring is not closed");

            interiorRing.TryOrientAnticlockwise();

            IntersectionPoint3D outerRingIntersection;
            bool ringsAreEqual;
            int  parentRingIdx = GetContainingRingIndex(
                polygon, interiorRing, tolerance, out ringsAreEqual, out outerRingIntersection);

            Assert.False(parentRingIdx < 0, "No parent ring found");

            Linestring containingRing = polygon.GetLinestring(parentRingIdx);

            if (containingRing.ClockwiseOriented == false)
            {
                // The cutter is completely within an existing island -> ignore (keep existing ring)
                return(false);
            }

            if (ringsAreEqual)
            {
                // The cutter is equal to the found ring. Positive rings cancel each other out:
                if (!allowEmptyResults)
                {
                    return(false);
                }

                polygon.RemoveLinestring(containingRing);
            }
            else if (outerRingIntersection == null)
            {
                // The cutter is completely within an existing outer ring -> add as island
                polygon.AddLinestring(interiorRing);
            }
            else
            {
                // create boundary loop:
                polygon.RemoveLinestring(containingRing);

                Linestring withBoundaryLoop = CreateWithBoundaryLoop(containingRing, interiorRing,
                                                                     outerRingIntersection,
                                                                     tolerance);

                polygon.InsertLinestring(parentRingIdx, withBoundaryLoop);
            }

            resultCookie = RingGroup.CreateProperlyOriented(cookieCutter.Clone());

            foreach (Linestring unusedCutRing in containedExistingIslands)
            {
                RingGroup cookieInCookie;
                Assert.True(TryCutCookie(resultCookie, unusedCutRing, tolerance,
                                         out cookieInCookie),
                            "Inner ring in cookie cutter cannot be cut from result cookie");
            }

            return(true);
        }