/// <summary> /// Find the innermost enclosing shell EdgeRing containing the argument EdgeRing, if any. /// The innermost enclosing ring is the <i>smallest</i> enclosing ring. /// The algorithm used depends on the fact that: /// ring A contains ring B iff envelope(ring A) contains envelope(ring B). /// This routine is only safe to use if the chosen point of the hole /// is known to be properly contained in a shell /// (which is guaranteed to be the case if the hole does not touch its shell). /// </summary> /// <param name="shellList"></param> /// <param name="testEr"></param> /// <returns>Containing EdgeRing, if there is one <br/> /// or <c>null</c> if no containing EdgeRing is found.</returns> public static EdgeRing FindEdgeRingContaining(EdgeRing testEr, IList <EdgeRing> shellList) { var testRing = testEr.Ring; var testEnv = testRing.EnvelopeInternal; //var testPt = testRing.GetCoordinateN(0); EdgeRing minShell = null; Envelope minShellEnv = null; foreach (var tryShell in shellList) { var tryShellRing = tryShell.Ring; var tryShellEnv = tryShellRing.EnvelopeInternal; if (minShell != null) { minShellEnv = minShell.Ring.EnvelopeInternal; } // the hole envelope cannot equal the shell envelope // (also guards against testing rings against themselves) if (tryShellEnv.Equals(testEnv)) { continue; } // hole must be contained in shell if (!tryShellEnv.Contains(testEnv)) { continue; } var testPt = CoordinateArrays.PointNotInList(testRing.Coordinates, tryShellRing.Coordinates); bool isContained = PointLocation.IsInRing(testPt, tryShellRing.Coordinates); // check if this new containing ring is smaller than the current minimum ring if (isContained) { if (minShell == null || minShellEnv.Contains(tryShellEnv)) { minShell = tryShell; minShellEnv = minShell.Ring.EnvelopeInternal; } } } return(minShell); }