private MultiPolygon CreateMP1() { Polygon[] polygons = new Polygon[2]; LineString[] rings = new LineString[2]; Coordinates coords = new Coordinates(); Coordinate 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); GeometryFactory gf = new GeometryFactory(_precMod, _sRID); LinearRing exterior1 = gf.CreateLinearRing(coords); polygons[0] = gf.CreatePolygon(exterior1); rings[0] = exterior1 as LineString; 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); LinearRing exterior2 = gf.CreateLinearRing(coords); polygons[1] = gf.CreatePolygon(exterior2); rings[1] = exterior2; _mls1 = gf.CreateMultiLineString(rings); return gf.CreateMultiPolygon(polygons); }
/// <summary> /// Initializes a new instance of the MultiPolygon class. /// </summary> /// <param name="polygons"> /// The Polygons for this MultiPolygon, or null or an empty array to create /// the empty geometry. Elements may be empty Polygons, but not nulls. The /// polygons must conform to the assertions specified in the /// OpenGIS Simple Features Specification. /// </param> /// <param name="precisionModel">The specification of the grid of allowable /// points for this MultiPolygon.</param> /// <param name="SRID"> /// The ID of the Spatial Reference System used by this MultiPolygon. /// </param> internal MultiPolygon(Polygon[] polygons, PrecisionModel precisionModel, int SRID) : base(polygons, precisionModel, SRID) { if(polygons == null) { polygons = new Polygon[]{}; } if (HasNullElements(polygons)) { throw new ArgumentNullException("Polygon array must not contain null elements."); } _geometries = polygons; }
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> /// Converts a Polygon to <Polygon Text> format, then /// Appends it to the writer. /// </summary> /// <param name="polygon">The Polygon to process.</param> /// <param name="level"></param> /// <param name="indentFirst"></param> /// <param name="writer"></param> protected void AppendPolygonText(Polygon polygon, int level, bool indentFirst, StringWriter writer) { if ( polygon.IsEmpty() ) { writer.Write("EMPTY"); } else { if (indentFirst) Indent(level, writer); writer.Write("("); AppendLineStringText(polygon.Shell, level, false, writer); for (int i = 0; i < polygon.GetNumInteriorRing(); i++) { writer.Write(", "); AppendLineStringText(polygon.Holes[i], level + 1, true, writer); } writer.Write(")"); } }
/// <summary> /// Converts a Polygon to <Polygon Tagged Text> format, /// then Appends it to the writer. /// </summary> /// <param name="polygon">Th Polygon to process.</param> /// <param name="level"></param> /// <param name="writer">The stream writer to Append to.</param> protected void AppendPolygonTaggedText(Polygon polygon, int level, StringWriter writer) { writer.Write("POLYGON "); AppendPolygonText(polygon, level, false, writer); }
/// <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; } } }
/// <summary> /// Converts a Polygon to <Polygon Text> format, then /// Appends it to the writer. /// </summary> /// <param name="polygon">The Polygon to process.</param> /// <param name="writer"></param> protected void AppendPolygonText(Polygon polygon, TextWriter writer) { if (polygon.IsEmpty()) { //writer.Write("EMPTY"); } else { AppendLineStringText(polygon.Shell,writer); for (int i = 0; i < polygon.GetNumInteriorRing(); i++) { AppendLineStringText(polygon.Holes[i], writer); } writer.Write(" Z "); } }
private void ComputeInside(Coordinate pt, Polygon poly) { if (Location.Exterior != _ptLocator.Locate(pt, poly)) { _minDistance = 0.0; } }
/// <summary> /// Converts the List to an array. /// </summary> /// <param name="polygons">The List to convert.</param> /// <returns>The List in array format.</returns> public static Polygon[] ToPolygonArray(ArrayList polygons) { Polygon[] polygonArray = new Polygon[polygons.Count]; return (Polygon[]) polygons.ToArray(typeof(Polygon)); }
} // 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> /// Tests that no hole is nested inside another hole. /// </summary> /// <remarks> /// This routine assumes that the holes are disjoint. /// To ensure this, holes have previously been tested /// to ensure that: /// <ul> /// <li>they do not partially overlap /// (Checked by CheckRelateConsistency)</li> /// <li>they are not identical /// (Checked by CheckRelateConsistency)</li> /// <li>they do not touch at a vertex /// (Checked by ????)</li> /// </ul> /// </remarks> /// <param name="p"></param> /// <param name="graph"></param> private void CheckHolesNotNested(Polygon p, GeometryGraph graph) { QuadtreeNestedRingTester nestedTester = new QuadtreeNestedRingTester(graph); //SimpleNestedRingTester nestedTester = new SimpleNestedRingTester(_arg[0]); //SweeplineNestedRingTester nestedTester = new SweeplineNestedRingTester(_arg[0]); for (int i = 0; i < p.GetNumInteriorRing(); i++) { LinearRing innerHole = p.GetInteriorRingN( i ); nestedTester.Add(innerHole); } bool isNonNested = nestedTester.IsNonNested(); if ( ! isNonNested ) { _validErr = new TopologyValidationError( TopologyValidationError.NestedHoles, nestedTester.GetNestedPoint()); } }
private void OLDCheckHolesInShell(Polygon p) { // awc: probably do'nt need this - but copy it anyway /*LinearRing shell = (LinearRing) p.getExteriorRing(); Coordinate[] shellPts = shell.getCoordinates(); for (int i = 0; i < p.getNumInteriorRing(); i++) { Coordinate holePt = findPtNotNode(p.getInteriorRingN(i).getCoordinates(), shell, arg[0]); Assert.isTrue(holePt != null, "Unable to find a hole point not a vertex of the shell"); bool onBdy = cga.isOnLine(holePt, shellPts); bool inside = cga.isPointInPolygon(holePt, shellPts); bool outside = ! (onBdy || inside); if ( outside ) { _validErr = new TopologyValidationError( TopologyValidationError.HOLE_OUTSIDE_SHELL, holePt); return; } }*/ throw new NotImplementedException(); }
/// <summary> /// Creates a new multipolygon given an array of polygons. /// </summary> /// <param name="polygons">The array of polygons to be used to create the multipolygon.</param> /// <returns>A new multipolygon.</returns> public MultiPolygon CreateMultiPolygon(Polygon[] polygons) { return new MultiPolygon(polygons, _precisionModel, _SRID); }
/// <summary> /// Projects all the points in a multipolygon and returns a new multipolygon object. /// </summary> /// <param name="coordinateTransform">The coordinate transformation to use for projection.</param> /// <returns>The projected multipolygon object.</returns> public override Geometry Project(ICoordinateTransformation coordinateTransform) { if (coordinateTransform==null) { throw new ArgumentNullException("coordinateTransform"); } if (!(coordinateTransform.MathTransform is Geotools.CoordinateTransformations.MapProjection)) { throw new ArgumentException("transform must be a MapProjection."); } Polygon[] projectedPolygons = new Polygon[_geometries.Length]; IGeometry projectedPolygon; for(int i=0; i<_geometries.Length; i++) { projectedPolygon = _geometries[i].Project(coordinateTransform); projectedPolygons[i] = (Polygon)projectedPolygon; } return _geometryFactory.CreateMultiPolygon(projectedPolygons); }
/// <summary> /// Writes a polygon. /// </summary> /// <param name="poly">The polygon to be written.</param> private void WritePolygon(Polygon poly, byte format) { //Get the number of rings in this polygon. int numRings = poly.GetNumInteriorRing() + 1; //Write the number of rings to the stream (add one for the shell) _bWriter.Write(numRings); //Get the shell of this polygon. WriteLineString(poly.Shell, format); //Loop on the number of rings - 1 because we already wrote the shell. for(int i = 0; i < numRings-1; i++) { //Populate the linearRing. LinearRing lr = poly.GetInteriorRingN( i ); //Write the (lineString)LinearRing. WriteLineString((LineString)lr, format); } }
/// <summary> /// Reads a stream and converts the shapefile record to an equilivent geometry object. /// </summary> /// <param name="file">The stream to read.</param> /// <param name="geometryFactory">The geometry factory to use when making the object.</param> /// <returns>The Geometry object that represents the shape file record.</returns> public override Geometry Read(BigEndianBinaryReader file, GeometryFactory geometryFactory) { int shapeTypeNum = file.ReadInt32(); ShapeType shapeType = (ShapeType)Enum.Parse(typeof(ShapeType),shapeTypeNum.ToString()); if (shapeType != ShapeType.Polygon) { throw new ShapefileException("Attempting to load a non-polygon as polygon."); } //read and for now ignore bounds. double[] box = new double[4]; for (int i = 0; i < 4; i++) { box[i] = file.ReadDouble(); } int[] partOffsets; int numParts = file.ReadInt32(); int numPoints = file.ReadInt32(); partOffsets = new int[numParts]; for (int i = 0; i < numParts; i++) { partOffsets[i] = file.ReadInt32(); } ArrayList shells = new ArrayList(); ArrayList holes = new ArrayList(); int start, finish, length; for (int part = 0; part < numParts; part++) { start = partOffsets[part]; if (part == numParts - 1) { finish = numPoints; } else { finish = partOffsets[part + 1]; } length = finish - start; Coordinates points = new Coordinates(); points.Capacity=length; for (int i = 0; i < length; i++) { Coordinate external = new Coordinate(file.ReadDouble(), file.ReadDouble() ); Coordinate internalCoord = geometryFactory.PrecisionModel.ToInternal(external); points.Add(internalCoord); } LinearRing ring = geometryFactory.CreateLinearRing(points); //Debug.Assert(ring.IsValid()==false,"Ring is not valid."); if (_cga.IsCCW(points)) { holes.Add(ring); } else { shells.Add(ring); } } //now we have a list of all shells and all holes ArrayList holesForShells = new ArrayList(shells.Count); for (int i = 0; i < shells.Count; i++) { holesForShells.Add(new ArrayList()); } //find homes for (int i = 0; i < holes.Count; i++) { LinearRing testRing = (LinearRing) holes[i]; LinearRing minShell = null; Envelope minEnv = null; Envelope testEnv = testRing.GetEnvelopeInternal(); Coordinate testPt = testRing.GetCoordinateN(0); LinearRing tryRing; for (int j = 0; j < shells.Count; j++) { tryRing = (LinearRing) shells[j]; Envelope tryEnv = tryRing.GetEnvelopeInternal(); if (minShell != null) { minEnv = minShell.GetEnvelopeInternal(); } bool isContained = false; Coordinates coordList = tryRing.GetCoordinates() ; if (tryEnv.Contains(testEnv) && (_cga.IsPointInRing(testPt,coordList ) || (PointInList(testPt,coordList)))) { isContained = true; } // check if this new containing ring is smaller than the // current minimum ring if (isContained) { if (minShell == null || minEnv.Contains(tryEnv)) { minShell = tryRing; } } } //if (minShell==null) //{ // throw new InvalidOperationException("Could not find shell for a hole. Try a different precision model."); //} } Polygon[] polygons = new Polygon[shells.Count]; for (int i = 0; i < shells.Count; i++) { polygons[i] = geometryFactory.CreatePolygon((LinearRing) shells[i], (LinearRing[])((ArrayList) holesForShells[i]).ToArray(typeof(LinearRing))); } if (polygons.Length == 1) { return polygons[0]; } //it's a multi part return geometryFactory.CreateMultiPolygon(polygons); }
/// <summary> /// Creates a multipolygon from the wkb. /// </summary> /// <returns>A geometry.</returns> private Geometry CreateWKBMultiPolygon() { //Get the number of Polygons. int numPolygons = (int)_bReader.ReadUInt32(); //Create a new array for the Polygons. Polygon[] polygons = new Polygon[numPolygons]; //Loop on the number of polygons. for(int i = 0; i < numPolygons; i++) { // read polygon header _bReader.ReadByte(); _bReader.ReadUInt32(); //Create the next polygon and add it to the array. polygons[i] = (Polygon)CreateWKBPolygon(); } //Create and return the MultiPolygon. return _geometryFactory.CreateMultiPolygon(polygons); }
/// <summary> /// Converts a Polygon to <Polygon Tagged Text> format, /// then Appends it to the writer. /// </summary> /// <param name="polygon">Th Polygon to process.</param> /// <param name="writer">The stream writer to Append to.</param> protected void AppendPolygonTaggedText(Polygon polygon, TextWriter writer) { AppendPath(writer); AppendPolygonText(polygon, writer); AppendEndPath(writer); }
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 void CheckValid(Polygon g) { GeometryGraph graph = new GeometryGraph(0, g); CheckTooFewPoints(graph); if (_validErr != null) return; CheckConsistentArea(graph); if (_validErr != null) return; CheckNoSelfIntersectingRings(graph); if (_validErr != null) return; CheckHolesInShell(g, graph); if (_validErr != null) return; //SLOWcheckHolesNotNested(g); CheckHolesNotNested(g, graph); if (_validErr != null) return; CheckConnectedInteriors(graph); }