/// <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> /// 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(); } }
/// <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(); } }
/// <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 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> /// 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> /// 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> /// 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.Point) { 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))); }
/// <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> /// 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 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)); }
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="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)); }