/// <summary> /// Reads a stream and converts the shapefile record to an equilivant 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 IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory) { int shapeTypeNum = file.ReadInt32(); ShapeGeometryTypes shapeType = (ShapeGeometryTypes)Enum.Parse(typeof(ShapeGeometryTypes), shapeTypeNum.ToString()); if (!(shapeType == ShapeGeometryTypes.MultiPoint || shapeType == ShapeGeometryTypes.MultiPointM || shapeType == ShapeGeometryTypes.MultiPointZ || shapeType == ShapeGeometryTypes.MultiPointZM)) { throw new ShapefileException("Attempting to load a non-multipoint as multipoint."); } // Read and for now ignore bounds. double[] box = new double[4]; for (int i = 0; i < 4; i++) { box[i] = file.ReadDouble(); } // Read points int numPoints = file.ReadInt32(); IPoint[] points = new IPoint[numPoints]; for (int i = 0; i < numPoints; i++) { points[i] = geometryFactory.CreatePoint(new Coordinate(file.ReadDouble(), file.ReadDouble())); } return(geometryFactory.CreateMultiPoint(points)); }
/// <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 IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory) { int shapeTypeNum = file.ReadInt32(); ShapeGeometryTypes shapeType = (ShapeGeometryTypes)Enum.Parse(typeof(ShapeGeometryTypes), shapeTypeNum.ToString()); if (!(shapeType == ShapeGeometryTypes.LineString || shapeType == ShapeGeometryTypes.LineStringM || shapeType == ShapeGeometryTypes.LineStringZ || shapeType == ShapeGeometryTypes.LineStringZM)) { throw new ShapefileException("Attempting to load a non-arc as arc."); } //read and for now ignore bounds. double[] box = new double[4]; for (int i = 0; i < 4; i++) { double d = file.ReadDouble(); box[i] = d; } int numParts = file.ReadInt32(); int numPoints = file.ReadInt32(); int[] partOffsets = new int[numParts]; for (int i = 0; i < numParts; i++) { partOffsets[i] = file.ReadInt32(); } ILineString[] lines = new LineString[numParts]; 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; CoordinateList points = new CoordinateList(); points.Capacity = length; Coordinate external; for (int i = 0; i < length; i++) { external = new Coordinate(file.ReadDouble(), file.ReadDouble()); // points.Add(geometryFactory.PrecisionModel.ToInternal(external)); new PrecisionModel(geometryFactory.PrecisionModel).MakePrecise(external); points.Add(external); } lines[part] = geometryFactory.CreateLineString((ICoordinate[])points.ToArray(typeof(ICoordinate))); } return(geometryFactory.CreateMultiLineString(lines)); }
/// <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 IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory) { int shapeTypeNum = file.ReadInt32(); ShapeGeometryTypes shapeType = (ShapeGeometryTypes)Enum.Parse(typeof(ShapeGeometryTypes), shapeTypeNum.ToString()); if (!(shapeType == ShapeGeometryTypes.Point || shapeType == ShapeGeometryTypes.PointM || shapeType == ShapeGeometryTypes.PointZ || shapeType == ShapeGeometryTypes.PointZM)) { throw new ShapefileException("Attempting to load a point as point."); } double x = file.ReadDouble(); double y = file.ReadDouble(); Coordinate external = new Coordinate(x, y); // return geometryFactory.CreatePoint(geometryFactory.PrecisionModel.ToInternal(external)); new PrecisionModel(geometryFactory.PrecisionModel).MakePrecise(external); return(geometryFactory.CreatePoint(external)); }
/// <summary> /// Initializes a new instance of the ShapefileHeader class with values read in from the stream. /// </summary> /// <remarks>Reads the header information from the stream.</remarks> /// <param name="shpBinaryReader">BigEndianBinaryReader stream to the shapefile.</param> public ShapefileHeader(BigEndianBinaryReader shpBinaryReader) { if (shpBinaryReader == null) { throw new ArgumentNullException("shpBinaryReader"); } _fileCode = shpBinaryReader.ReadInt32BE(); if (_fileCode != Shapefile.ShapefileId) { throw new ShapefileException("The first four bytes of this file indicate this is not a shape file."); } // skip 5 unsed bytes shpBinaryReader.ReadInt32BE(); shpBinaryReader.ReadInt32BE(); shpBinaryReader.ReadInt32BE(); shpBinaryReader.ReadInt32BE(); shpBinaryReader.ReadInt32BE(); _fileLength = shpBinaryReader.ReadInt32BE(); _version = shpBinaryReader.ReadInt32(); Debug.Assert(_version == 1000, "Shapefile version", String.Format("Expecting only one version (1000), but got {0}", _version)); int shapeType = shpBinaryReader.ReadInt32(); _shapeType = (ShapeGeometryTypes)Enum.Parse(typeof(ShapeGeometryTypes), shapeType.ToString()); //read in and store the bounding box double[] coords = new double[4]; for (int i = 0; i < 4; i++) { coords[i] = shpBinaryReader.ReadDouble(); } _bounds = new Envelope(coords[0], coords[2], coords[1], coords[3]); // skip z and m bounding boxes. for (int i = 0; i < 4; i++) { shpBinaryReader.ReadDouble(); } }
/// <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 IGeometry Read(BigEndianBinaryReader file, IGeometryFactory geometryFactory) { int shapeTypeNum = file.ReadInt32(); ShapeGeometryTypes shapeType = (ShapeGeometryTypes)Enum.Parse(typeof(ShapeGeometryTypes), shapeTypeNum.ToString()); if (!(shapeType == ShapeGeometryTypes.Polygon || shapeType == ShapeGeometryTypes.PolygonM || shapeType == ShapeGeometryTypes.PolygonZ || shapeType == ShapeGeometryTypes.PolygonZM)) { 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; CoordinateList points = new CoordinateList(); points.Capacity = length; for (int i = 0; i < length; i++) { Coordinate external = new Coordinate(file.ReadDouble(), file.ReadDouble()); new PrecisionModel(geometryFactory.PrecisionModel).MakePrecise(external); Coordinate internalCoord = external; points.Add(internalCoord); } ILinearRing ring = geometryFactory.CreateLinearRing((Coordinate[])points.ToArray(typeof(Coordinate))); // If shape have only a part, jump orientation check and add to shells if (numParts == 1) { shells.Add(ring); } else { // Orientation check if (CGAlgorithms.IsCCW((Coordinate[])points.ToArray(typeof(Coordinate)))) { 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 holes for (int i = 0; i < holes.Count; i++) { LinearRing testRing = (LinearRing)holes[i]; LinearRing minShell = null; IEnvelope minEnv = null; IEnvelope testEnv = testRing.EnvelopeInternal; ICoordinate testPt = testRing.GetCoordinateN(0); LinearRing tryRing; for (int j = 0; j < shells.Count; j++) { tryRing = (LinearRing)shells[j]; IEnvelope tryEnv = tryRing.EnvelopeInternal; if (minShell != null) { minEnv = minShell.EnvelopeInternal; } bool isContained = false; CoordinateList coordList = new CoordinateList(tryRing.Coordinates); if (tryEnv.Contains(testEnv) && (CGAlgorithms.IsPointInRing(testPt, (Coordinate[])coordList.ToArray(typeof(Coordinate))) || (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; } // Suggested by Brian Macomber and added 3/28/2006: // holes were being found but never added to the holesForShells array // so when converted to geometry by the factory, the inner rings were never created. ArrayList holesForThisShell = (ArrayList)holesForShells[j]; holesForThisShell.Add(holes[i]); } } } IPolygon[] 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)); }