private void AddPolygon( Polygon p ) { AddPolygonRing( (LinearRing) p.GetExteriorRing(), Location.Exterior, Location.Interior ); for ( int i = 0; i < p.GetNumInteriorRing(); i++ ) { // Holes are topologically labelled opposite to the shell, since // the interior of the polygon lies on their opposite side // (on the left, if the hole is oriented CW) LinearRing interiorRing = p.GetInteriorRingN( i ); AddPolygonRing( interiorRing, Location.Interior, Location.Exterior); } }
} // private int Locate( Coordinate p, LinearRing ring ) private int Locate( Coordinate p, Polygon poly ) { if ( poly.IsEmpty() ) { return Location.Exterior; } LinearRing shell = (LinearRing) poly.GetExteriorRing(); int shellLoc = Locate( p, shell ); if ( shellLoc == Location.Exterior ) { return Location.Exterior; } if ( shellLoc == Location.Boundary ) { return Location.Boundary; } // now test if the point lies in or on the holes for ( int i = 0; i < poly.GetNumInteriorRing(); i++ ) { int holeLoc = Locate( p, poly.GetInteriorRingN( i ) ); if ( holeLoc == Location.Interior ) { return Location.Exterior; } if ( holeLoc == Location.Boundary ) { return Location.Boundary; } } // for ( int i = 0; i < poly.NumInteriorRings; i++ ) return Location.Interior; } // private int Locate( Coordinate p, Polygon poly )
} // private static bool ContainsPoint(Coordinate p, Geometry geom) private static bool ContainsPointInPolygon(Coordinate p, Polygon poly) { if ( poly.IsEmpty() ) return false; LinearRing shell = (LinearRing) poly.GetExteriorRing(); if ( ! _cga.IsPointInRing( p, shell.GetCoordinates() ) ) { return false; } // now test if the point lies in or on the holes for (int i = 0; i < poly.GetNumInteriorRing(); i++) { LinearRing lr = poly.GetInteriorRingN( i ); if ( _cga.IsPointInRing( p, lr.GetCoordinates() ) ) { return false; } } return true; } // private static bool ContainsPointInPolygon(Coordinate p, Polygon poly)
private bool HasRepeatedPoint(Polygon p) { LinearRing exteriorRing1; exteriorRing1 = (LinearRing)p.GetExteriorRing(); if (HasRepeatedPoint(exteriorRing1.GetCoordinates() )) { return true; } for (int i = 0; i < p.GetNumInteriorRing(); i++) { LinearRing interiorRing = p.GetInteriorRingN(i); if (HasRepeatedPoint( (interiorRing).GetCoordinates() )) return true; } return false; }
/// <summary> /// Add a Polygon to the graph. /// </summary> /// <param name="p">The polygon to add.</param> private void AddPolygon(Polygon p) { double lineDistance = _distance; int side = Position.Left; if (_distance < 0.0) { lineDistance = -_distance; side = Position.Right; } int holeSide = (side == Position.Left) ? Position.Right : Position.Left; AddPolygonRing( (LinearRing) p.GetExteriorRing(), lineDistance, side, Location.Exterior, Location.Interior); for (int i = 0; i < p.GetNumInteriorRing(); i++) { // Holes are topologically labelled opposite to the shell, since // the interior of the polygon lies on their opposite side // (on the left, if the hole is oriented CCW) LinearRing interiorRing = p.GetInteriorRingN( i ); AddPolygonRing( interiorRing, lineDistance, Position.Opposite(side), Location.Interior, Location.Exterior); } }
/// <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; } }
/// <summary> /// Test that each hole is inside the polygon shell. /// This routine assumes that the holes have previously been tested /// to ensure that all vertices lie on the shell or inside it. /// A simple test of a single point in the hole can be used, /// provide the point is chosen such that it does not lie on the /// boundary of the shell. /// </summary> /// <param name="p">The polygon to be tested for hole inclusion.</param> /// <param name="graph">Graph a GeometryGraph incorporating the polygon.</param> private void CheckHolesInShell(Polygon p, GeometryGraph graph) { LinearRing shell = (LinearRing) p.GetExteriorRing(); Coordinates shellPts = shell.GetCoordinates(); //PointInRing pir = new SimplePointInRing(shell); //PointInRing pir = new SIRtreePointInRing(shell); IPointInRing pir = new MCPointInRing(shell); for (int i = 0; i < p.GetNumInteriorRing(); i++) { LinearRing hole = (LinearRing) p.GetInteriorRingN(i); Coordinate holePt = FindPtNotNode(hole.GetCoordinates(), shell, graph); if (holePt == null) { throw new InvalidOperationException("Unable to find a hole point not a vertex of the shell."); } bool outside = ! pir.IsInside(holePt); if ( outside ) { _validErr = new TopologyValidationError( TopologyValidationError.HoleOutsideShell, holePt); return; } } }