/// <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); }
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> /// Writes a Geometry to the given binary wirter. /// </summary> /// <param name="geometry">The geometry to write.</param> /// <param name="file">The file stream to write to.</param> /// <param name="geometryFactory">The geometry factory to use.</param> public override void Write(Geometry geometry, System.IO.BinaryWriter file, GeometryFactory geometryFactory) { if (geometry.IsValid()==false) { Trace.WriteLine("Invalid polygon being written."); } GeometryCollection multi; if(geometry is GeometryCollection) { multi = (GeometryCollection) geometry; } else { GeometryFactory gf = new GeometryFactory(geometry.PrecisionModel, geometry.GetSRID()); //multi = new MultiPolygon(new Polygon[]{(Polygon) geometry}, geometry.PrecisionModel, geometry.GetSRID()); multi = gf.CreateMultiPolygon( new Polygon[]{(Polygon) geometry} ); } //file.setLittleEndianMode(true); file.Write(int.Parse(Enum.Format(typeof(ShapeType),this.ShapeType,"d"))); Envelope box = multi.GetEnvelopeInternal(); Envelope bounds = ShapeHandler.GetEnvelopeExternal(geometryFactory.PrecisionModel, box); file.Write(bounds.MinX); file.Write(bounds.MinY); file.Write(bounds.MaxX); file.Write(bounds.MaxY); int numParts = GetNumParts(multi); int numPoints = multi.GetNumPoints(); file.Write(numParts); file.Write(numPoints); // write the offsets to the points int offset=0; for (int part = 0; part < multi.Count; part++) { // offset to the shell points Polygon polygon = (Polygon)multi[part]; file.Write(offset); offset = offset + polygon.Shell.GetNumPoints(); // offstes to the holes foreach (LinearRing ring in polygon.Holes) { file.Write(offset); offset = offset + ring.GetNumPoints(); } } // write the points for (int part = 0; part < multi.Count; part++) { Polygon poly = (Polygon)multi[part]; Coordinates points = poly.Shell.GetCoordinates(); if (_cga.IsCCW(points)==true) { //points = points.ReverseCoordinateOrder(); } WriteCoords(points, file, geometryFactory); foreach(LinearRing ring in poly.Holes) { Coordinates points2 = ring.GetCoordinates(); if (_cga.IsCCW(points2)==false) { //points2 = points2.ReverseCoordinateOrder(); } WriteCoords(points2, file, geometryFactory); } } }
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); }