예제 #1
0
        /// <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);
            }
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        /// <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);
        }
예제 #4
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.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);
		}
예제 #5
0
        /// <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();
            }
        }
예제 #6
0
        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;
        }
예제 #7
0
			/// <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);
				}
			}
예제 #8
0
		/// <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();	
			}
		}
예제 #9
0
        /// <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();
        }
예제 #10
0
 /// <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);
예제 #11
0
        /// <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;
        }
예제 #12
0
        /// <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);
            }
        }
예제 #13
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);

		}
예제 #14
0
 public ShapefileIndexReader(string path)
 {
     _reader = new BigEndianBinaryReader(File.OpenRead(path));
     _header = new ShapefileHeader(_reader);
 }
예제 #15
0
        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();
            }
        }
예제 #16
0
 public ShapefileIndexReader(string path)
 {
     _reader = new BigEndianBinaryReader(File.OpenRead(path));
     _header = new ShapefileHeader(_reader);
 }
예제 #17
0
        /// <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);
        }
예제 #18
0
        /// <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));
        }
예제 #19
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 abstract  Geometry Read(BigEndianBinaryReader file, GeometryFactory geometryFactory);
예제 #20
0
        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();
                }
        }
예제 #21
0
		/// <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();
		}
예제 #22
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));
        }