⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shapefile.cs

📁 C# 的地图开发例子(sharp map)
💻 CS
📖 第 1 页 / 共 3 页
字号:
		#region Disposers and finalizers

		private bool disposed = false;

		/// <summary>
		/// Disposes the object
		/// </summary>
		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		private void Dispose(bool disposing)
		{
			if (!disposed)
			{
				if (disposing)
				{
					Close();
					_Envelope = null;
					tree = null;
				}
				disposed = true;
			}
		}

		/// <summary>
		/// Finalizes the object
		/// </summary>
		~ShapeFile()
		{
			this.Dispose();
		}
		#endregion

		
		/// <summary>
		/// Reads and parses the header of the .shx index file
		/// </summary>
		private void ParseHeader()
		{
			fsShapeIndex = new FileStream(_Filename.Remove(_Filename.Length - 4, 4) + ".shx", FileMode.Open, FileAccess.Read);
			brShapeIndex = new BinaryReader(fsShapeIndex, System.Text.Encoding.Unicode);
			
			brShapeIndex.BaseStream.Seek(0, 0);
			//Check file header
			if (brShapeIndex.ReadInt32() != 170328064) //File Code is actually 9994, but in Little Endian Byte Order this is '170328064'
				throw (new ApplicationException("Invalid Shapefile Index (.shx)"));

			brShapeIndex.BaseStream.Seek(24, 0); //seek to File Length
			int IndexFileSize = SwapByteOrder(brShapeIndex.ReadInt32()); //Read filelength as big-endian. The length is based on 16bit words
			_FeatureCount = (2 * IndexFileSize - 100) / 8; //Calculate FeatureCount. Each feature takes up 8 bytes. The header is 100 bytes

			brShapeIndex.BaseStream.Seek(32, 0); //seek to ShapeType
			_ShapeType = (ShapeType)brShapeIndex.ReadInt32();

			//Read the spatial bounding box of the contents
			brShapeIndex.BaseStream.Seek(36, 0); //seek to box
			_Envelope = new SharpMap.Geometries.BoundingBox(brShapeIndex.ReadDouble(), brShapeIndex.ReadDouble(), brShapeIndex.ReadDouble(), brShapeIndex.ReadDouble());

			brShapeIndex.Close();
			fsShapeIndex.Close();			
		}
		/// <summary>
		/// Reads and parses the projection if a projection file exists
		/// </summary>
		private void ParseProjection()
		{
			string projfile = Path.GetDirectoryName(Filename) + "\\" + Path.GetFileNameWithoutExtension(Filename) + ".prj";
			if (System.IO.File.Exists(projfile))
			{
				try
				{
					string wkt = System.IO.File.ReadAllText(projfile);
					_CoordinateSystem = (SharpMap.CoordinateSystems.ICoordinateSystem)SharpMap.Converters.WellKnownText.CoordinateSystemWktReader.Parse(wkt);
					_CoordsysReadFromFile = true;
				}
				catch(System.Exception ex) {
					System.Diagnostics.Trace.TraceWarning("Coordinate system file '" + projfile + "' found, but could not be parsed. WKT parser returned:" + ex.Message);
					throw (ex);
				}
			}
		}

		/// <summary>
		/// Reads the record offsets from the .shx index file and returns the information in an array
		/// </summary>
		private int[] ReadIndex()
		{
			int[] OffsetOfRecord = new int[ _FeatureCount ];
			brShapeIndex.BaseStream.Seek(100, 0);  //skip the header
			
			for (int x=0; x < _FeatureCount; ++x ) 
			{
				OffsetOfRecord[x] = 2 * SwapByteOrder(brShapeIndex.ReadInt32()); //Read shape data position // ibuffer);
				brShapeIndex.BaseStream.Seek(brShapeIndex.BaseStream.Position + 4, 0); //Skip content length
			}
			return OffsetOfRecord;
		}

		/// <summary>
		/// Gets the file position of the n'th shape
		/// </summary>
		/// <param name="n">Shape ID</param>
		/// <returns></returns>
		private int GetShapeIndex(uint n)
		{
			brShapeIndex.BaseStream.Seek(100+n*8, 0);  //seek to the position of the index
			return 2 * SwapByteOrder(brShapeIndex.ReadInt32()); //Read shape data position
		}

		///<summary>
		///Swaps the byte order of an int32
		///</summary>
		/// <param name="i">Integer to swap</param>
		/// <returns>Byte Order swapped int32</returns>
		private int SwapByteOrder (int i) 
		{
			byte[] buffer = BitConverter.GetBytes(i);
			Array.Reverse(buffer, 0, buffer.Length);	
			return BitConverter.ToInt32(buffer, 0);
		}

		/// <summary>
		/// Loads a spatial index from a file. If it doesn't exist, one is created and saved
		/// </summary>
		/// <param name="filename"></param>
		/// <returns>QuadTree index</returns>
		private Utilities.SpatialIndexing.QuadTree CreateSpatialIndexFromFile(string filename)
		{
			if (System.IO.File.Exists(filename + ".sidx"))
			{
				try
				{
					return Utilities.SpatialIndexing.QuadTree.FromFile(filename + ".sidx");
				}
				catch(Utilities.SpatialIndexing.QuadTree.ObsoleteFileFormatException)
				{
					System.IO.File.Delete(filename + ".sidx");
					return CreateSpatialIndexFromFile(filename);
				}
				catch (System.Exception ex) { throw ex; }
			}
			else
			{
				Utilities.SpatialIndexing.QuadTree tree = CreateSpatialIndex(_Filename);
				tree.SaveIndex(filename + ".sidx");
				return tree;
			}
		}

		/// <summary>
		/// Generates a spatial index for a specified shape file.
		/// </summary>
		/// <param name="filename"></param>
		private Utilities.SpatialIndexing.QuadTree CreateSpatialIndex(string filename)
		{
			List<Utilities.SpatialIndexing.QuadTree.BoxObjects> objList = new List<Utilities.SpatialIndexing.QuadTree.BoxObjects>();
			//Convert all the geometries to boundingboxes 
			uint i = 0;
			foreach (SharpMap.Geometries.BoundingBox box in GetAllFeatureBoundingBoxes())
			{
				if (!double.IsNaN(box.Left) && !double.IsNaN(box.Right) && !double.IsNaN(box.Bottom) && !double.IsNaN(box.Top))
				{
					Utilities.SpatialIndexing.QuadTree.BoxObjects g = new Utilities.SpatialIndexing.QuadTree.BoxObjects();
					g.box = box;
					g.ID = i;
					objList.Add(g);
					i++;
				}
			}

			Utilities.SpatialIndexing.Heuristic heur;
			heur.maxdepth = (int)Math.Ceiling(Math.Log(this.GetFeatureCount(), 2));
			heur.minerror = 10;
			heur.tartricnt = 5;
			heur.mintricnt = 2;
			return new Utilities.SpatialIndexing.QuadTree(objList, 0, heur);
		}

		private void LoadSpatialIndex() { LoadSpatialIndex(false,false); }
		private void LoadSpatialIndex(bool LoadFromFile) { LoadSpatialIndex(false, LoadFromFile); }
		private void LoadSpatialIndex(bool ForceRebuild, bool LoadFromFile)
		{
			//Only load the tree if we haven't already loaded it, or if we want to force a rebuild
			if (tree == null || ForceRebuild)
			{
				// Is this a web application? If so lets store the index in the cache so we don't
				// need to rebuild it for each request
				if (System.Web.HttpContext.Current != null)
				{
					//Check if the tree exists in the cache
					if (System.Web.HttpContext.Current.Cache[_Filename] != null)
						tree = (Utilities.SpatialIndexing.QuadTree)System.Web.HttpContext.Current.Cache[_Filename];
					else
					{
						if (!LoadFromFile)
							tree = CreateSpatialIndex(_Filename);
						else
							tree = CreateSpatialIndexFromFile(_Filename);
						//Store the tree in the web cache
						//TODO: Remove this when connection pooling is implemented
						System.Web.HttpContext.Current.Cache.Insert(_Filename, tree, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromDays(1));
					}
				}
				else
					if (!LoadFromFile)
						tree = CreateSpatialIndex(_Filename);
					else
						tree = CreateSpatialIndexFromFile(_Filename);
			}
		}

		/// <summary>
		/// Forces a rebuild of the spatial index. If the instance of the ShapeFile provider
		/// uses a file-based index the file is rewritten to disk.
		/// </summary>
		public void RebuildSpatialIndex()
		{
			if (this._FileBasedIndex)
			{
				if (System.IO.File.Exists(_Filename + ".sidx"))
					System.IO.File.Delete(_Filename + ".sidx");
				tree = CreateSpatialIndexFromFile(_Filename);
			}
			else
				tree = CreateSpatialIndex(_Filename);
			if (System.Web.HttpContext.Current != null)
				//TODO: Remove this when connection pooling is implemented:
				System.Web.HttpContext.Current.Cache.Insert(_Filename, tree, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromDays(1));
		}

		/// <summary>
		/// Reads all boundingboxes of features in the shapefile. This is used for spatial indexing.
		/// </summary>
		/// <returns></returns>
		private List<SharpMap.Geometries.BoundingBox> GetAllFeatureBoundingBoxes()
		{
			int[] offsetOfRecord = ReadIndex(); //Read the whole .idx file

			List<SharpMap.Geometries.BoundingBox> boxes = new List<SharpMap.Geometries.BoundingBox>();
			
			if (_ShapeType == ShapeType.Point)
			{
				for (int a = 0; a < _FeatureCount; ++a)
				{
					fsShapeFile.Seek(offsetOfRecord[a]+8, 0); //skip record number and content length
					if ((ShapeType)brShapeFile.ReadInt32() != ShapeType.Null)
					{
						double x = brShapeFile.ReadDouble();
						double y = brShapeFile.ReadDouble();
						boxes.Add(new SharpMap.Geometries.BoundingBox(x, y, x, y));
					}
				}
			}
			else
			{
				for (int a = 0; a < _FeatureCount; ++a)
				{
					fsShapeFile.Seek(offsetOfRecord[a] + 8, 0); //skip record number and content length
					if ((ShapeType)brShapeFile.ReadInt32() != ShapeType.Null)
						boxes.Add(new SharpMap.Geometries.BoundingBox(brShapeFile.ReadDouble(), brShapeFile.ReadDouble(), brShapeFile.ReadDouble(), brShapeFile.ReadDouble()));
				}
			}
			return boxes;
		}

		#region IProvider Members

		/// <summary>
		/// Returns geometries whose bounding box intersects 'bbox'
		/// </summary>
		/// <remarks>
		/// <para>Please note that this method doesn't guarantee that the geometries returned actually intersect 'bbox', but only
		/// that their boundingbox intersects 'bbox'.</para>
		/// <para>This method is much faster than the QueryFeatures method, because intersection tests
		/// are performed on objects simplifed by their boundingbox, and using the Spatial Index.</para>
		/// </remarks>
		/// <param name="bbox"></param>
		/// <returns></returns>
		public Collection<SharpMap.Geometries.Geometry> GetGeometriesInView(SharpMap.Geometries.BoundingBox bbox)
		{
			//Use the spatial index to get a list of features whose boundingbox intersects bbox
			Collection<uint> objectlist = GetObjectIDsInView(bbox);
			if (objectlist.Count == 0) //no features found. Return an empty set
				return new Collection<SharpMap.Geometries.Geometry>();

            //Collection<SharpMap.Geometries.Geometry> geometries = new Collection<SharpMap.Geometries.Geometry>(objectlist.Count);
            Collection<SharpMap.Geometries.Geometry> geometries = new Collection<SharpMap.Geometries.Geometry>();

			for (int i = 0; i < objectlist.Count; i++)
			{
				SharpMap.Geometries.Geometry g = GetGeometryByID(objectlist[i]);
				if(g!=null)
					geometries.Add(g);
			}
			return geometries;
		}			

		/// <summary>
		/// Returns all objects whose boundingbox intersects bbox.
		/// </summary>
		/// <remarks>
		/// <para>
		/// Please note that this method doesn't guarantee that the geometries returned actually intersect 'bbox', but only
		/// that their boundingbox intersects 'bbox'.
		/// </para>
		/// </remarks>
		/// <param name="bbox"></param>
		/// <param name="ds"></param>
		/// <returns></returns>
		public void ExecuteIntersectionQuery(SharpMap.Geometries.BoundingBox bbox, SharpMap.Data.FeatureDataSet ds)
		{
			//Use the spatial index to get a list of features whose boundingbox intersects bbox
			Collection<uint> objectlist = GetObjectIDsInView(bbox);
			SharpMap.Data.FeatureDataTable dt = dbaseFile.NewTable;

			for (int i = 0; i < objectlist.Count; i++)
			{
				SharpMap.Data.FeatureDataRow fdr = dbaseFile.GetFeature(objectlist[i], dt);
				fdr.Geometry = ReadGeometry(objectlist[i]);
				if (fdr.Geometry != null)
					if (fdr.Geometry.GetBoundingBox().Intersects(bbox))
						if (FilterDelegate == null || FilterDelegate(fdr))
							dt.AddRow(fdr);
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -