private int _crossings = 0; // number of segment/ray crossings #region Constructor /// <summary> /// Initializes a new instance of the IntTreePointInRing with the specified properties. /// </summary> /// <param name="ring">The LinearRing to use.</param> public SIRtreePointInRing(LinearRing ring) { this._ring = ring; BuildIndex(); }
private Polygon Poly1() { _coords1 = new Coordinates(); Coordinate coord = new Coordinate(5, 1); _coords1.Add(coord); coord = new Coordinate(6, 2); _coords1.Add(coord); coord = new Coordinate(7, 3); _coords1.Add(coord); coord = new Coordinate(6, 4); _coords1.Add(coord); coord = new Coordinate(5, 5); _coords1.Add(coord); coord = new Coordinate(4, 4); _coords1.Add(coord); coord = new Coordinate(3, 3); _coords1.Add(coord); coord = new Coordinate(4, 2); _coords1.Add(coord); coord = new Coordinate(5, 1); _coords1.Add(coord); _gf = new GeometryFactory(_precMod, _sRID); _exterior1 = _gf.CreateLinearRing(_coords1); Polygon polygon = _gf.CreatePolygon(_exterior1); return polygon; }
/// <summary> /// Find a point from the list of testCoords /// that is NOT a node in the edge for the list of searchCoords /// </summary> /// <param name="testCoords"></param> /// <param name="searchRing"></param> /// <param name="graph"></param> /// <returns>return the point found, or null if none found</returns> public static Coordinate FindPtNotNode( Coordinates testCoords, LinearRing searchRing, GeometryGraph graph) { // find edge corresponding to searchRing. Edge searchEdge = graph.FindEdge(searchRing ); // find a point in the testCoords which is not a node of the searchRing EdgeIntersectionList eiList = searchEdge.EdgeIntersectionList; // somewhat inefficient - is there a better way? (Use a node map, for instance?) for (int i = 0 ; i < testCoords.Count; i++) { Coordinate pt = testCoords[i]; if (! eiList.IsIntersection(pt)) { return pt; } } return null; }
/// <summary> /// Initializes a Polygon with the given exterior boundary. The shell and holes /// must conform to the assertions specified in the OpenGIS Simple Features /// Specification for SQL. /// </summary> /// <param name="shell"> /// The outer boundary of the new Polygon, or null or an empty LinearRing if the empty /// geometry is to be created. Must be oriented clockwise. /// </param> /// <param name="holes"> /// The inner boundaries of the new Polygon, or null or empty LinearRings if the empty /// geometry is to be created. Each must be oriented counterclockwise. /// </param> /// <param name="precisionModel"> /// The specification of the grid of allowable points for this Polygon. /// </param> /// <param name="SRID"> /// The ID of the Spatial Reference System used by this Polygon. /// </param> internal Polygon(LinearRing shell, LinearRing[] holes, PrecisionModel precisionModel, int SRID) : base(precisionModel, SRID) { if (shell == null) { shell = _geometryFactory.CreateLinearRing(null); } if (holes == null) { holes = new LinearRing[]{}; } //OPTIMIZE: - if fully optimzed, don't bother doing this test. if (HasNullElements(holes)) { throw new ArgumentNullException("holes must not contain null elements"); } if (shell.IsEmpty() && HasNonEmptyElements(holes)) { throw new ArgumentException("shell is empty but holes are not"); } _shell = shell; _holes = holes; }
public void Add(LinearRing ring) { _rings.Add(ring); }
} // private int Locate( Coordinate p, LineString l ) /// <summary> /// /// </summary> /// <param name="p"></param> /// <param name="ring"></param> /// <returns></returns> private int Locate( Coordinate p, LinearRing ring ) { if ( _cga.IsOnLine( p, ring.GetCoordinates() ) ) { return Location.Boundary; } if ( _cga.IsPointInRing( p, ring.GetCoordinates() ) ) { return Location.Interior; } return Location.Exterior; } // private int Locate( Coordinate p, LinearRing ring )
/// <summary> /// Compute a LinearRing from the point list previously collected. /// Test if the ring is a hole (i.e. if it is CCW) and set the hole flag /// accordingly. /// </summary> public void ComputeRing() { if ( _ring != null ) return; // don't compute more than once // create ring using geometry factory. _ring = _geometryFactory.CreateLinearRing( _pts ); _isHole = _cga.IsCCW( _ring.GetCoordinates() ); }
/// <summary> /// /// </summary> /// <param name="coordinates"> /// The vertices of a linear ring, which may or may not be flattened (i.e. vertices collinear) /// </param> /// <returns> /// A 2-vertex LineStringif the vertices are collinear; otherwise, a Polygon with /// unnecessary (collinear) vertices removed /// </returns> private Geometry LineOrPolygon(Coordinates coordinates) { coordinates = CleanRing(coordinates); if (coordinates.Count == 3) { Coordinates coords = new Coordinates(); coords.Add(coordinates[0]); coords.Add(coordinates[1]); return new LineString(coords, _geometry.PrecisionModel, _geometry.GetSRID()); } LinearRing linearRing = new LinearRing(coordinates, _geometry.PrecisionModel, _geometry.GetSRID()); return new Polygon(linearRing, _geometry.PrecisionModel, _geometry.GetSRID()); }
/// <summary> /// Initializes a Polygon with the given exterior boundary. The shell and holes /// must conform to the assertions specified in the OpenGIS Simple Features /// Specification for SQL. /// </summary> /// <param name="shell"> /// The outer boundary of the new Polygon, or null or an empty LinearRing if the empty /// geometry is to be created. Must be oriented clockwise. /// </param> /// <param name="precisionModel"> /// The specification of the grid of allowable points for this Polygon. /// </param> /// <param name="SRID"> /// The ID of the Spatial Reference System used by this Polygon. /// </param> internal Polygon(LinearRing shell, PrecisionModel precisionModel, int SRID) : this(shell, new LinearRing[] {}, precisionModel, SRID) { }
/// <summary> /// Creates a Polygon from the wkb. /// </summary> /// <returns>A geometry.</returns> private Geometry CreateWKBPolygon() { //Get the Number of rings in this Polygon. int numRings = (int)_bReader.ReadUInt32(); Debug.Assert(numRings>=1, "Number of rings in polygon must be 1 or more."); LinearRing shell = CreateWKBLinearRing(); //Create a new array of linearrings for the interior rings. LinearRing[] interiorRings = new LinearRing[numRings-1]; for(int i = 0; i < numRings-1; i++) { interiorRings[i] = CreateWKBLinearRing(); } //Create and return the Poylgon. return _geometryFactory.CreatePolygon(shell, interiorRings); }
public void Add(LinearRing ring) { _rings.Add(ring); _totalEnv.ExpandToInclude(ring.GetEnvelopeInternal()); }
/// <summary> /// Creates a polygon given a linearring representing the shell of /// the polygon and an array of linearrings representing the interior holes of the polygon.. /// </summary> /// <param name="shell">The linearring to be used to create the shell of the polygon.</param> /// <param name="holes">The array of linearrings to be used to create the interior /// holes of the polygon.</param> /// <returns></returns> public Polygon CreatePolygon(LinearRing shell, LinearRing[] holes) { return(new Polygon(shell, holes, _precisionModel, _SRID)); }
/// <summary> /// Converts the List to an array. /// </summary> /// <param name="linearRings">The List to convert.</param> /// <returns>The List in array format.</returns> public static LinearRing[] ToLinearRingArray(ArrayList linearRings) { LinearRing[] linearRingArray = new LinearRing[linearRings.Count]; return((LinearRing[])linearRings.ToArray(typeof(LinearRing))); //throw new NotImplementedException(); }
/// <summary> /// The side and left and right topological location arguments assume that the ring is oriented CW. /// If the ring is in the opposite orientation, the left and right locations must be interchanged /// and the side flipped. /// </summary> /// <param name="lr">lr the LinearRing around which to create the buffer</param> /// <param name="distance">distance the distance at which to create the buffer</param> /// <param name="side">side the side of the ring on which to construct the buffer line</param> /// <param name="cwLeftLoc">cwLeftLoc the location on the L side of the ring (if it is CW)</param> /// <param name="cwRightLoc">cwRightLoc the location on the R side of the ring (if it is CW)</param> private void AddPolygonRing(LinearRing lr, double distance, int side, int cwLeftLoc, int cwRightLoc) { Coordinates coord = Coordinates.RemoveRepeatedPoints(lr.GetCoordinates()); int leftLoc = cwLeftLoc; int rightLoc = cwRightLoc; if (_cga.IsCCW(coord)) { leftLoc = cwRightLoc; rightLoc = cwLeftLoc; side = Position.Opposite(side); } ArrayList lineList = _lineBuilder.GetRingBuffer(coord, side, distance); AddEdges(lineList, leftLoc, rightLoc); /* This section was already commented out in the java code. Leave it commented out... Edge e = new Edge(coord, new Label(0, Location.BOUNDARY, left, right)); insertEdge(e); // insert the endpoint as a node, to mark that it is on the boundary insertPoint(argIndex, coord[0], Location.BOUNDARY); */ }
/// <summary> /// This routine Checks to see if a shell is properly contained in a hole. /// </summary> /// <param name="shell"></param> /// <param name="hole"></param> /// <param name="graph"></param> private void CheckShellInsideHole(LinearRing shell, LinearRing hole, GeometryGraph graph) { Coordinates shellPts = shell.GetCoordinates(); Coordinates holePts = hole.GetCoordinates(); // TODO: improve performance of this - by sorting pointlists for instance? Coordinate shellPt = FindPtNotNode(shellPts, hole, graph); // if point is on shell but not hole, Check that the shell is inside the hole if (shellPt != null) { bool insideHole = _cga.IsPointInRing(shellPt, holePts); if (! insideHole) _validErr = new TopologyValidationError( TopologyValidationError.NestedShells, shellPt); return; } Coordinate holePt = FindPtNotNode(holePts, shell, graph); // if point is on hole but not shell, Check that the hole is outside the shell if (holePt != null) { bool insideShell = _cga.IsPointInRing(holePt, shellPts); if (insideShell) { _validErr = new TopologyValidationError( TopologyValidationError.NestedShells, holePt); } return; } throw new InvalidOperationException("Points in shell and hole appear to be equal."); }
/// <summary> /// Creates a polygon given a linearring representing the shell of /// the polygon and an array of linearrings representing the interior holes of the polygon.. /// </summary> /// <param name="shell">The linearring to be used to create the shell of the polygon.</param> /// <param name="holes">The array of linearrings to be used to create the interior /// holes of the polygon.</param> /// <returns></returns> public Polygon CreatePolygon(LinearRing shell, LinearRing[] holes) { return new Polygon(shell, holes, _precisionModel, _SRID); }
///<summary> /// Returns the boundary, or the empty geometry if this Geometry is empty. /// </summary> /// <remarks>For a discussion of this function, see the OpenGIS Simple Features Specification. As stated in SFS /// Section 2.1.13.1, "the boundary of a Geometry is a set of Geometries of the next lower dimension." /// </remarks> ///<returns>Returns the closure of the combinatorial boundary of this Geometry.</returns> public override Geometry GetBoundary() { if ( IsEmpty() ) { return _geometryFactory.CreateGeometryCollection(null); } LinearRing[] rings = new LinearRing[_holes.Length + 1]; rings[0] = _shell; for (int i = 0; i < _holes.Length; i++) { rings[i + 1] = _holes[i]; } return _geometryFactory.CreateMultiLineString(rings); }
/// <summary> /// The left and right topological location arguments assume that the ring is oriented CW. /// If the ring is in the opposite orientation, the left and right locations must be interchanged. /// </summary> /// <param name="lr"></param> /// <param name="cwLeft"></param> /// <param name="cwRight"></param> private void AddPolygonRing( LinearRing lr, int cwLeft, int cwRight ) { Coordinates coord = Coordinates.RemoveRepeatedPoints(lr.GetCoordinates()); if (coord.Count<4) { _hasTooFewPoints=true; _invalidPoint=coord[0]; } int left = cwLeft; int right = cwRight; if ( _cga.IsCCW( coord ) ) { left = cwRight; right = cwLeft; } Edge e = new Edge(coord, new Label(_argIndex, Location.Boundary, left, right)); _lineEdgeMap[ lr]= e; InsertEdge( e ); // insert the endpoint as a node, to mark that it is on the boundary InsertPoint( _argIndex, coord[0], Location.Boundary ); }
/// <summary> /// Creates an exact copy of this Polygon. /// </summary> /// <returns>A geometry containing an exact copy of the original polygon.</returns> public override Geometry Clone() { //create deep clone of the holes LinearRing[] holesCopy = new LinearRing[_holes.Length]; for(int i=0; i<_holes.Length; i++) { holesCopy[i]= (LinearRing)_holes[i].Clone(); } return _geometryFactory.CreatePolygon((LinearRing)_shell.Clone(), holesCopy); }
/// <summary> /// /// </summary> /// <param name="pts"></param> /// <returns></returns> private Coordinates Reduce(Coordinates pts) { BigQuad bigQuad = this.BigQuadrant(pts); // Build a linear ring defining a big poly. Coordinates bigPoly = new Coordinates(); bigPoly.Add(bigQuad._westmost); if (!bigPoly.Contains(bigQuad._northmost)) { bigPoly.Add(bigQuad._northmost); } if (!bigPoly.Contains(bigQuad._eastmost)) { bigPoly.Add(bigQuad._eastmost); } if (!bigPoly.Contains(bigQuad._southmost)) { bigPoly.Add(bigQuad._southmost); } if (bigPoly.Count < 3) { return pts; } bigPoly.Add(bigQuad._westmost); LinearRing bQ = new LinearRing(bigPoly, _geometry.PrecisionModel, _geometry.GetSRID()); // load an array with all points not in the big poly // and the defining points. Coordinates reducedSet = new Coordinates(bigPoly); for (int i = 0; i < pts.Count; i++) { if (_pointLocator.Locate(pts[i], bQ) == Location.Exterior) { reducedSet.Add(pts[i]); } } //Coordinates rP = (Coordinates) reducedSet.toArray(new Coordinate[0]); // Return this array as the reduced problem. return reducedSet; }
///<summary> /// Converts a linearring to be sure it is clockwise. ///</summary> ///<remarks>Normal form is a unique representation /// for Geometry's. It can be used to test whether two Geometrys are equal in a way that is /// independent of the ordering of the coordinates within them. Normal form equality is a stronger /// condition than topological equality, but weaker than pointwise equality. The definitions for /// normal form use the standard lexicographical ordering for coordinates. Sorted in order of /// coordinates means the obvious extension of this ordering to sequences of coordinates. ///</remarks> private void Normalize( LinearRing ring, bool clockwise ) { if ( ring.IsEmpty() ) { return; } Coordinates uniqueCoordinates = new Coordinates(); for ( int i=0; i < ring.GetNumPoints()-1; i++ ) { uniqueCoordinates.Add( ring.GetCoordinateN( i ) ); // copy all but last one into uniquecoordinates } Coordinate minCoordinate = MinCoordinate( ring.GetCoordinates() ); Scroll( uniqueCoordinates, minCoordinate ); Coordinates ringCoordinates = ring.GetCoordinates(); ringCoordinates.Clear(); ringCoordinates.AddRange( uniqueCoordinates ); ringCoordinates.Add( uniqueCoordinates[0].Clone() ); // add back in the closing point. if ( _cgAlgorithms.IsCCW( ringCoordinates ) == clockwise ) { ReversePointOrder( ringCoordinates ); } }
private MultiPolygon CreateMP2() { Polygon[] polygons = new Polygon[2]; GeometryFactory gf = new GeometryFactory(_precMod, _sRID); Coordinates coords = new Coordinates(); Coordinate coord = new Coordinate(10, 13); coords.Add(coord); coord = new Coordinate(11, 13); coords.Add(coord); coord = new Coordinate(12, 13); coords.Add(coord); coord = new Coordinate(13, 14); coords.Add(coord); coord = new Coordinate(14, 15); coords.Add(coord); coord = new Coordinate(15, 16); coords.Add(coord); coord = new Coordinate(15, 17); coords.Add(coord); coord = new Coordinate(15, 18); coords.Add(coord); coord = new Coordinate(14, 19); coords.Add(coord); coord = new Coordinate(13, 20); coords.Add(coord); coord = new Coordinate(12, 21); coords.Add(coord); coord = new Coordinate(11, 21); coords.Add(coord); coord = new Coordinate(10, 21); coords.Add(coord); coord = new Coordinate(9, 20); coords.Add(coord); coord = new Coordinate(8, 19); coords.Add(coord); coord = new Coordinate(7, 18); coords.Add(coord); coord = new Coordinate(7, 17); coords.Add(coord); coord = new Coordinate(7, 16); coords.Add(coord); coord = new Coordinate(8, 15); coords.Add(coord); coord = new Coordinate(9, 14); coords.Add(coord); coord = new Coordinate(10, 13); coords.Add(coord); LinearRing exterior = gf.CreateLinearRing(coords); coords = new Coordinates(); coord = new Coordinate(10, 16); coords.Add(coord); coord = new Coordinate(11, 17); coords.Add(coord); coord = new Coordinate(10, 18); coords.Add(coord); coord = new Coordinate(9, 17); coords.Add(coord); coord = new Coordinate(10, 16); coords.Add(coord); LinearRing interior = gf.CreateLinearRing(coords); LinearRing[] linearRings = new LinearRing[1]; linearRings[0] = interior; polygons[0] = gf.CreatePolygon(exterior, linearRings); coords = new Coordinates(); coord = new Coordinate(5, 1); coords.Add(coord); coord = new Coordinate(6, 2); coords.Add(coord); coord = new Coordinate(7, 3); coords.Add(coord); coord = new Coordinate(6, 4); coords.Add(coord); coord = new Coordinate(5, 5); coords.Add(coord); coord = new Coordinate(4, 4); coords.Add(coord); coord = new Coordinate(3, 3); coords.Add(coord); coord = new Coordinate(4, 2); coords.Add(coord); coord = new Coordinate(5, 1); coords.Add(coord); exterior = gf.CreateLinearRing(coords); polygons[1] = gf.CreatePolygon(exterior); return gf.CreateMultiPolygon(polygons); }
/// <summary> /// Projects a geometry using the given transformation. /// </summary> /// <param name="coordinateTransform">The transformation to use.</param> /// <returns>A projected line string object.</returns> public override Geometry Project(ICoordinateTransformation coordinateTransform) { LinearRing projectedShell = (LinearRing)this._shell.Project(coordinateTransform); LinearRing[] projectedHoles = new LinearRing[_holes.Length]; for(int i=0;i<_holes.Length; i++) { projectedHoles[i]=(LinearRing)_holes[i].Project(coordinateTransform); } return _geometryFactory.CreatePolygon(projectedShell,projectedHoles); }
/// <summary> /// /// </summary> /// <param name="geometryFactory"></param> /// <returns></returns> public Polygon ToPolygon(GeometryFactory geometryFactory) { LinearRing[] holeLR = new LinearRing[ _holes.Count ]; for (int i = 0; i < _holes.Count; i++) { holeLR[i] = ( (EdgeRing)_holes[i] ).GetLinearRing(); } Polygon poly = geometryFactory.CreatePolygon( GetLinearRing(), holeLR ); return poly; }
/// <summary> /// Initializes a Polygon with the given exterior boundary. The shell and holes /// must conform to the assertions specified in the OpenGIS Simple Features /// Specification for SQL. /// </summary> /// <param name="shell"> /// The outer boundary of the new Polygon, or null or an empty LinearRing if the empty /// geometry is to be created. Must be oriented clockwise. /// </param> /// <param name="precisionModel"> /// The specification of the grid of allowable points for this Polygon. /// </param> /// <param name="SRID"> /// The ID of the Spatial Reference System used by this Polygon. /// </param> internal Polygon(LinearRing shell, PrecisionModel precisionModel, int SRID) : this( shell, new LinearRing[]{}, precisionModel, SRID) { }
private Polygon Poly2() { Coordinates coords = new Coordinates(); Coordinate coord = new Coordinate(10, 13); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(11, 13); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(12, 13); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(13, 14); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(14, 15); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(15, 16); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(15, 17); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(15, 18); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(14, 19); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(13, 20); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(12, 21); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(11, 21); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(10, 21); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(9, 20); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(8, 19); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(7, 18); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(7, 17); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(7, 16); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(8, 15); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(9, 14); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(10, 13); _coords2.Add(coord); coords.Add(coord); _gf = new GeometryFactory(_precMod, _sRID); _exterior2 = _gf.CreateLinearRing(coords); coords = new Coordinates(); coord = new Coordinate(10, 16); _coords2.Add(coord); coords.Add(coord); coord = new Coordinate(11, 17); coords.Add(coord); _coords2.Add(coord); coord = new Coordinate(10, 18); coords.Add(coord); _coords2.Add(coord); coord = new Coordinate(9, 17); coords.Add(coord); _coords2.Add(coord); coord = new Coordinate(10, 16); coords.Add(coord); _coords2.Add(coord); _interior2 = _gf.CreateLinearRing(coords); LinearRing[] linearRings = new LinearRing[1]; linearRings[0] = _interior2; _gf = new GeometryFactory(); Polygon polygon = _gf.CreatePolygon(_exterior2, linearRings); return polygon; }
/// <summary> /// Converts the List to an array. /// </summary> /// <param name="linearRings">The List to convert.</param> /// <returns>The List in array format.</returns> public static LinearRing[] ToLinearRingArray(ArrayList linearRings) { LinearRing[] linearRingArray = new LinearRing[linearRings.Count]; return (LinearRing[]) linearRings.ToArray(typeof(LinearRing)); //throw new NotImplementedException(); }
/// <summary> /// Initializes a new instance of the SimplePointInRing class. /// </summary> public SimplePointInRing(LinearRing ring) { _pts = ring.GetCoordinates(); }
/// <summary> /// Creates a new linear ring given a set of coordinates. /// </summary> /// <remarks>Throws an argument exception if the number of coordiates is less than 1.</remarks> /// <param name="coordinates">The coordinates to be used to create the linear ring.</param> /// <returns>A new linear ring.</returns> public LinearRing CreateLinearRing(Coordinates coordinates) { LinearRing linearRing = new LinearRing(coordinates, _precisionModel, _SRID); if (coordinates != null && coordinates.Count > 0 && !coordinates[0].Equals2D(coordinates[coordinates.Count - 1])) { throw new ArgumentException("LinearRing not closed"); } return linearRing; //throw new NotImplementedException(); }
private bool IsInside(LinearRing innerRing, LinearRing searchRing) { Coordinates innerRingPts = innerRing.GetCoordinates(); Coordinates searchRingPts = searchRing.GetCoordinates(); if (! innerRing.GetEnvelopeInternal().Intersects(searchRing.GetEnvelopeInternal())) return false; Coordinate innerRingPt = IsValidOp.FindPtNotNode(innerRingPts, searchRing, _graph); //Assert.isTrue(innerRingPt != null, "Unable to find a ring point not a node of the search ring"); bool isInside = _cga.IsPointInRing(innerRingPt, searchRingPts); if (isInside) { _nestedPt = innerRingPt; return true; } return false; }
/// <summary> /// Check if a shell is incorrectly nested within a polygon. This is the case /// if the shell is inside the polygon shell, but not inside a polygon hole. /// If the shell is inside a polygon hole, the nesting is valid.) /// /// The algorithm used relies on the fact that the rings must be properly contained. /// E.g. they cannot partially overlap (this has been previously Checked by /// CheckRelateConsistency /// </summary> /// <param name="shell"></param> /// <param name="p"></param> /// <param name="graph"></param> private void CheckShellNotNested(LinearRing shell, Polygon p, GeometryGraph graph) { Coordinates shellPts = shell.GetCoordinates(); // test if shell is inside polygon shell LinearRing polyShell = (LinearRing) p.GetExteriorRing(); Coordinates polyPts = polyShell.GetCoordinates(); Coordinate shellPt = FindPtNotNode(shellPts, polyShell, graph); // if no point could be found, we can assume that the shell is outside the polygon if (shellPt == null) return; bool insidePolyShell = _cga.IsPointInRing(shellPt, polyPts); if (! insidePolyShell) return; // if no holes, this is an error! if (p.GetNumInteriorRing() <= 0) { _validErr = new TopologyValidationError( TopologyValidationError.NestedShells, shellPt); return; } for (int i = 0; i < p.GetNumInteriorRing(); i++) { LinearRing hole = p.GetInteriorRingN( i ); CheckShellInsideHole(shell, hole, graph); if (_validErr != null) return; } }