/// <summary> /// Initializes a new instance of the <see cref="ShapefileReader">ShapefileReader</see> class with the given parameters. /// </summary> /// <param name="filename">The filename of the shape file to read (with .shp).</param> /// <param name="factory">The <b>GeometryFactory</b> to use when creating Geometry objects.</param> public ShapefileReader(string filename, GeometryFactory factory) { if (filename == null) { throw new ArgumentNullException("filename"); } if (factory == null) { throw new ArgumentNullException("geometryFactory"); } _filename = filename; Trace.WriteLineIf(Shapefile.TraceSwitch.Enabled,"Reading filename:"+filename); _geometryFactory = factory; // read header information. note, we open the file, read the header information and then // close the file. This means the file is not opened again until GetEnumerator() is requested. // For each call to GetEnumerator() a new BinaryReader is created. using (BigEndianBinaryReader shpBinaryReader = new BigEndianBinaryReader(File.OpenRead(filename))) { _mainHeader = new ShapefileHeader(shpBinaryReader); } }
/// <summary> /// Reads a stream and converts the shapefile record to an equilivent geometry object. /// </summary> /// <param name="reader">The stream to read.</param> /// <param name="factory">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 reader, GeometryFactory factory) { if (this.GetShapeType(reader) != ShapeType.Point) { throw new ShapefileException("Attempting to load a non-point as point."); } Coordinate coord = new Coordinate(reader.ReadDouble(), reader.ReadDouble()); factory.getPrecisionModel().makePrecise(coord); return factory.createPoint(coord); }
/// <summary> /// Reads a stream and converts the shapefile record to an equilivent geometry object. /// </summary> /// <param name="reader">The stream to read.</param> /// <param name="factory">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 reader, GeometryFactory factory) { int shapeTypeNum = reader.ReadInt32(); ShapeType shapeType = (ShapeType)Enum.Parse(typeof(ShapeType),shapeTypeNum.ToString()); if (shapeType != ShapeType.Arc) { 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= reader.ReadDouble(); box[i] =d; } int numParts = reader.ReadInt32(); int numPoints = reader.ReadInt32(); int[] partOffsets = new int[numParts]; for (int i = 0; i < numParts; i++) { partOffsets[i] = reader.ReadInt32(); } LineString[] 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; Coordinate[] coords = new Coordinate[length]; for (int i = 0; i < length; i++) { Coordinate coord = new Coordinate(reader.ReadDouble(), reader.ReadDouble()); factory.getPrecisionModel().makePrecise(coord); coords[i] = coord; } lines[part] = factory.createLineString(new PackedCoordinateSequence.Float(coords, 2)); } return factory.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 Geometry Read(BigEndianBinaryReader file, GeometryFactory geometryFactory) { int shapeTypeNum = file.ReadInt32(); ShapeType shapeType = (ShapeType)Enum.Parse(typeof(ShapeType),shapeTypeNum.ToString()); if (shapeType != ShapeType.Arc) { 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(); } LineString[] 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; Coordinates points = new Coordinates(); 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)); } lines[part] = geometryFactory.CreateLineString(points); } return geometryFactory.CreateMultiLineString(lines); }
/// <summary> /// Initializes a new instance of the <see cref="ShapefileHeader">ShapefileHeader</see> class with values read in from the stream. /// </summary> /// <remarks>Reads the header information from the stream.</remarks> /// <param name="reader">BigEndianBinaryReader stream to the shapefile.</param> public ShapefileHeader(BigEndianBinaryReader reader) { if (reader == null) { throw new ArgumentNullException("reader"); } _fileCode = reader.ReadIntBE(); 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 for (int i = 0; i < 5; i++) { reader.ReadIntBE(); } _fileLength = reader.ReadIntBE(); _version = reader.ReadInt32(); Debug.Assert(_version == 1000, "Shapefile version", String.Format(System.Globalization.CultureInfo.InvariantCulture, "Expecting only one version (1000), but got {0}", _version)); int shapeType = reader.ReadInt32(); if (Enum.IsDefined(typeof(ShapeType), shapeType)) { _shapeType = (ShapeType)shapeType; } else { throw new ShapefileException("Invalid shape type"); } // Read in and store the bounding box double[] coords = new double[4]; for (int i = 0; i < coords.Length; i++) { coords[i] = reader.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++) { reader.ReadDouble(); } }
public DataTable Query(Envelope extents) { DataTable table = this.GetDataTable(); ArrayList indexes = new ArrayList(_spatialIndex.query(extents).toArray()); // Sort the results so we can go through the files sequentially indexes.Sort(); ShapeHandler handler = null; switch (_type) { case ShapeType.Point: handler = new PointHandler(); break; case ShapeType.Arc: handler = new MultiLineHandler(); break; case ShapeType.Polygon: handler = new PolygonHandler(); break; } using (BinaryReader dbfReader = new BinaryReader(File.OpenRead(Path.Combine(Path.GetDirectoryName(_path), Path.GetFileNameWithoutExtension(_path) + ".dbf")))) using (BigEndianBinaryReader shpReader = new BigEndianBinaryReader(File.OpenRead(_path))) { foreach (ShapefileRecordPointer pointer in indexes) { ArrayList record = new ArrayList(); // Step 1: Get the geometry // NOTE: We add 8 here to skip the content length and record numer - we // already have that information in the pointer object. shpReader.BaseStream.Position = pointer.GeometryOffset + 8; record.Add(handler.Read(shpReader, _factory)); // Step 2: Get the attributes dbfReader.BaseStream.Position = pointer.AttributesOffset; record.AddRange(DbaseFileReader.ReadRecord(dbfReader, _dbfHeader)); table.Rows.Add(record.ToArray()); } } return table; }
/// <summary> /// Initializes a new instance of the ShapefileEnumerator class. /// </summary> public ShapefileEnumerator(ShapefileReader shapefile) { _parent = shapefile; // create a file stream for each enumerator that is given out. This allows the same file // to have one or more enumerator. If we used the parents stream - than only one IEnumerator // could be given out. FileStream stream = new FileStream(_parent._filename, System.IO.FileMode.Open, FileAccess.Read, FileShare.Read); _shpBinaryReader = new BigEndianBinaryReader(stream); // skip header - since parent has already read this. _shpBinaryReader.ReadBytes(100); ShapeType type = _parent._mainHeader.ShapeType; _handler = Shapefile.GetShapeHandler(type); if (_handler == null) { throw new NotSupportedException("Unsuported shape type:" + type); } }
/// <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.ReadIntBE(); 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.ReadIntBE(); shpBinaryReader.ReadIntBE(); shpBinaryReader.ReadIntBE(); shpBinaryReader.ReadIntBE(); shpBinaryReader.ReadIntBE(); _fileLength = shpBinaryReader.ReadIntBE(); _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 = (ShapeType)Enum.Parse(typeof(ShapeType),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> /// Initializes a new instance of the Shapefile class with the given parameters. /// </summary> /// <param name="filename">The filename of the shape file to read (with .shp).</param> /// <param name="geometryFactory">The GeometryFactory to use when creating Geometry objects.</param> public ShapefileReader(string filename, GeometryFactory geometryFactory) { if (filename == null) { throw new ArgumentNullException("filename"); } if (geometryFactory == null) { throw new ArgumentNullException("geometryFactory"); } _filename = filename; Trace.WriteLineIf(Shapefile.TraceSwitch.Enabled, "Reading filename:" + filename); _geometryFactory = geometryFactory; // read header information. note, we open the file, read the header information and then // close the file. This means the file is not opened again until GetEnumerator() is requested. // For each call to GetEnumerator() a new BinaryReader is created. FileStream stream = new FileStream(filename, System.IO.FileMode.Open, FileAccess.Read, FileShare.Read); BigEndianBinaryReader shpBinaryReader = new BigEndianBinaryReader(stream); _mainHeader = new ShapefileHeader(shpBinaryReader); shpBinaryReader.Close(); }
/// <summary> /// Reads a stream and converts the shapefile record to an equilivent <b>Geometry</b> object. /// </summary> /// <param name="reader">The stream reader.</param> /// <param name="geometryFactory">The <b>GeometryFactory</b> to use when making the object.</param> /// <returns>The <b>Geometry</b> object that represents the shape file record.</returns> public abstract Geometry Read(BigEndianBinaryReader reader, GeometryFactory geometryFactory);
/// <summary> /// Returns the <see cref="ShapeType">ShapeType</see> for the current record. /// </summary> /// <param name="reader">The reader.</param> /// <returns>The <see cref="ShapeType">ShapeType</see> for the current record.</returns> /// <exception cref="ShapefileException">The shape type is invalid.</exception> protected ShapeType GetShapeType(BigEndianBinaryReader reader) { int type = reader.ReadInt32(); if (!Enum.IsDefined(typeof(ShapeType), type)) { throw new ShapefileException("Invalid shape type."); } return (ShapeType)type; }
/// <summary> /// Initializes a new instance of the <see cref="ShapefileWriter">ShapefileWriter</see> class with the specified filename and factory . /// </summary> /// <param name="filename">The name of the file to write.</param> /// <param name="factory">The <b>GeometryFactory</b> to use.</param> /// <param name="append"></param> /// <exception cref="ArgumentNullException">The factory is a null reference (Nothing in Visual Basic).</exception> public ShapefileWriter(string filename, GeometryFactory factory, bool append) { if (factory == null) { throw new ArgumentNullException("factory"); } _factory = factory; string shxFilename = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename) + ".shx"); if (append) { if (File.Exists(filename)==false || File.Exists(shxFilename)==false) { throw new ArgumentException("Cannot append to a file that does not exist."); } ShapefileHeader shpHeader = null; ShapefileHeader shxHeader = null; using (Stream stream = File.Open(filename, FileMode.Open)) { using (BigEndianBinaryReader beBinaryReader = new BigEndianBinaryReader(stream)) { shpHeader = new ShapefileHeader(beBinaryReader); } } using (Stream stream = File.Open(shxFilename, FileMode.Open)) { using (BigEndianBinaryReader beBinaryReader = new BigEndianBinaryReader(stream)) { shxHeader = new ShapefileHeader(beBinaryReader); } } this._type = shpHeader.ShapeType; this._shpLength = shpHeader.FileLength; this._bounds = shpHeader.Bounds; this._count = (shxHeader.FileLength-50)/4; _shpWriter = new BigEndianBinaryWriter(File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)); _shxWriter = new BigEndianBinaryWriter(File.Open(shxFilename, FileMode.Open,FileAccess.ReadWrite, FileShare.ReadWrite)); // Write dummy headers as place holders this.WriteHeader(_shpWriter,0); this.WriteHeader(_shxWriter,0); _shpWriter.BaseStream.Position = _shpWriter.BaseStream.Length; _shxWriter.BaseStream.Position = _shxWriter.BaseStream.Length; } else { _shpWriter = new BigEndianBinaryWriter(File.Open(filename, FileMode.CreateNew)); _shxWriter = new BigEndianBinaryWriter(File.Open(shxFilename, FileMode.CreateNew)); // Write dummy headers as place holders this.WriteHeader(_shpWriter,0); this.WriteHeader(_shxWriter,0); } }
/// <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); }
public ShapefileIndexReader(string path) { _reader = new BigEndianBinaryReader(File.OpenRead(path)); _header = new ShapefileHeader(_reader); }
private void Initialize() { // Cache the .dbf header _dbfHeader = new DbaseFileHeader(); using (BinaryReader dbfReader = new BinaryReader(File.OpenRead(Path.Combine(Path.GetDirectoryName(_path), Path.GetFileNameWithoutExtension(_path) + ".dbf")))) { _dbfHeader.ReadHeader(dbfReader); _dbfHeaderOffset = dbfReader.BaseStream.Position; } // Need to make one pass over the geometries and pull out the bounding boxes _spatialIndex = new com.vividsolutions.jts.index.strtree.STRtree(); _extents = new Envelope(); using (BigEndianBinaryReader shpReader = new BigEndianBinaryReader(File.OpenRead(_path))) using (ShapefileIndexReader shxReader = new ShapefileIndexReader(Path.Combine(Path.GetDirectoryName(_path), Path.GetFileNameWithoutExtension(_path) + ".shx"))) { // Get the shape type _type = new ShapefileHeader(shpReader).ShapeType; while (shxReader.Read()) { int offset = shxReader.GetOffest(); int length = shxReader.GetLength(); // Move to the start of geometry shpReader.BaseStream.Position = offset * 2; double xMin; double yMin; double xMax; double yMax; int recordNumber = shpReader.ReadIntBE(); int contentLength = shpReader.ReadIntBE(); // Read shape type int type = shpReader.ReadInt32(); if (type != 1) { xMin = shpReader.ReadDouble(); yMin = shpReader.ReadDouble(); xMax = shpReader.ReadDouble(); yMax = shpReader.ReadDouble(); } else { // Point - read x and y xMin = shpReader.ReadDouble(); yMin = shpReader.ReadDouble(); xMax = yMin; yMax = yMin; } // Build the envelope Envelope extents = new Envelope(xMin, xMax, yMin, yMax); // Add to total extents _extents.expandToInclude(extents); // Insert the index of the record into the spatial index _spatialIndex.insert(extents, new ShapefileRecordPointer(recordNumber, offset * 2, contentLength, (int)_dbfHeaderOffset + (_dbfHeader.RecordLength * (recordNumber - 1)))); } // Build the index once _spatialIndex.build(); } }
/// <summary> /// Reads a stream and converts the shapefile record to an equilivent geometry object. /// </summary> /// <param name="reader">The stream to read.</param> /// <param name="factory">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 reader, GeometryFactory factory) { if (this.GetShapeType(reader) != 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 < box.Length; i++) { box[i] = reader.ReadDouble(); } int numParts = reader.ReadInt32(); int numPoints = reader.ReadInt32(); int[] partOffsets = new int[numParts]; for (int i = 0; i < numParts; i++) { partOffsets[i] = reader.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; Coordinate[] coords = new Coordinate[length]; for (int i = 0; i < length; i++) { Coordinate coord = new Coordinate(reader.ReadDouble(), reader.ReadDouble()); factory.getPrecisionModel().makePrecise(coord); coords[i] = coord; } LinearRing ring = factory.createLinearRing(new PackedCoordinateSequence.Float(coords, 2)); if (com.vividsolutions.jts.algorithm.RobustCGAlgorithms.isCCW(coords)) { 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; Coordinate[] coordList = tryRing.getCoordinates(); if (tryEnv.contains(testEnv) && (com.vividsolutions.jts.algorithm.RobustCGAlgorithms.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; } ArrayList list = (ArrayList)holesForShells[j]; list.Add(testRing); } } 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] = factory.createPolygon((LinearRing) shells[i], (LinearRing[])((ArrayList) holesForShells[i]).ToArray(typeof(LinearRing))); } if (polygons.Length == 1) { return polygons[0]; } //it's a multi part return factory.createMultiPolygon(polygons); }
/// <summary> /// Reads a stream and converts the shapefile record to an equilivent geometry object. /// </summary> /// <param name="reader">The stream to read.</param> /// <param name="factory">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 reader, GeometryFactory factory) { if (this.GetShapeType(reader) != 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 < box.Length; i++) { box[i] = reader.ReadDouble(); } int numParts = reader.ReadInt32(); int numPoints = reader.ReadInt32(); int[] partOffsets = new int[numParts]; for (int i = 0; i < numParts; i++) { partOffsets[i] = reader.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; Coordinate[] coords = new Coordinate[length]; for (int i = 0; i < length; i++) { Coordinate coord = new Coordinate(reader.ReadDouble(), reader.ReadDouble()); factory.getPrecisionModel().makePrecise(coord); coords[i] = coord; } LinearRing ring = factory.createLinearRing(new PackedCoordinateSequence.Float(coords, 2)); if (com.vividsolutions.jts.algorithm.RobustCGAlgorithms.isCCW(coords)) { 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; Coordinate[] coordList = tryRing.getCoordinates(); if (tryEnv.contains(testEnv) && (com.vividsolutions.jts.algorithm.RobustCGAlgorithms.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; } ArrayList list = (ArrayList)holesForShells[j]; list.Add(testRing); } } 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] = factory.createPolygon((LinearRing)shells[i], (LinearRing[])((ArrayList)holesForShells[i]).ToArray(typeof(LinearRing))); } if (polygons.Length == 1) { return(polygons[0]); } //it's a multi part return(factory.createMultiPolygon(polygons)); }
/// <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 abstract Geometry Read(BigEndianBinaryReader file, GeometryFactory geometryFactory);
/// <summary> /// Initializes a new instance of the Shapefile class with the given parameters. /// </summary> /// <param name="filename">The filename of the shape file to read (with .shp).</param> /// <param name="geometryFactory">The GeometryFactory to use when creating Geometry objects.</param> public ShapefileReader(string filename, GeometryFactory geometryFactory) { if (filename==null) { throw new ArgumentNullException("filename"); } if (geometryFactory==null) { throw new ArgumentNullException("geometryFactory"); } _filename = filename; Trace.WriteLineIf(Shapefile.TraceSwitch.Enabled,"Reading filename:"+filename); _geometryFactory = geometryFactory; // read header information. note, we open the file, read the header information and then // close the file. This means the file is not opened again until GetEnumerator() is requested. // For each call to GetEnumerator() a new BinaryReader is created. FileStream stream = new FileStream(filename, System.IO.FileMode.Open, FileAccess.Read, FileShare.Read); BigEndianBinaryReader shpBinaryReader = new BigEndianBinaryReader(stream); _mainHeader = new ShapefileHeader(shpBinaryReader); shpBinaryReader.Close(); }
/// <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)); }