地圖中包含大量的信息,為了快速地了解所需信息,必須借助為空間數據專門編寫的空間查詢功能。
空間查詢主要有兩種類型:
基於屬性的查詢,也稱為屬性查詢。
基於空間位置的查詢,也稱為空間查詢。
查詢類的基本思路(適用於屬性查詢以及空間查詢)
1、屬性查詢
基於屬性的查詢,即屬性查詢,是通過對要素的屬性信息設定查詢條件來查詢、定位空間位置。
QueryFilterClass是專門用於屬性查詢的屬性查詢過濾器。
被稱為過濾器是因為擁有WhereClause屬性——能夠設置查詢條件的Sql語句。
注意:
使用WhereClause應該注意以下幾點:
(1)大小寫——字段值不區分大小寫。
(2)通配符的使用——“?”代表單個字符,“*”代表一組字符。
(3)不支持Orderby關鍵字,可以通過ITablesort接口完成。
2、空間查詢
基於空間位置查詢,即空間查詢,是根據要素之間的空間位置關系進行的查詢,查詢結果包括了被查詢對象的空間信息以及屬性信息。
SpatialFilterClass對象類被稱為空間查詢過濾器。它是屬性過濾器的子類,它擁有的ISpatialFilter也繼承了IQueryFilter接口。
因此,空間查詢過濾器既能進行空間查詢也能進行屬性查詢。
一般地,要素之間的空間關系,即查詢范圍與被查詢對象的空間關系主要有以下幾種:
相交(Intersect)、疊加(Overlap)、穿越(Cross)、在內部(Within)和包含(Con-tain)。
空間關系(SpatialRel)屬性成員不需要用戶自定義,系統以枚舉常量的方式(即ESRISpatialRelEnum)向用戶提供了多種空間關系。
(1)ESRISpatialRellntersects:空間相交
(2)ESRISpatialRelTouches:空間相接
(3)ESRISpatialRelOverlaps:覆蓋
(4)ESRISpatialRelCrosses:穿越
(5)ESRISpatialRelWithin:在內部
(6)ESRISpatialRelContains:包含
I.數據類型轉換(底層模塊)
/// <summary> /// 轉換數據類型 /// </summary> /// <param name="type"></param> /// <returns></returns> private static string ParseFieldType(esriFieldType FieldType) { switch (FieldType) { case esriFieldType.esriFieldTypeInteger: return "System.Int32"; case esriFieldType.esriFieldTypeOID: return "System.Int32"; case esriFieldType.esriFieldTypeDouble: return "System.Double"; case esriFieldType.esriFieldTypeDate: return "System.DateTime"; default: return "System.String"; } }
II.屬性查詢實現模塊
/// <summary> /// 核心屬性查詢函數 /// </summary> /// <param name="pFtClass"></param> /// <param name="pWhereClause"></param> /// <returns></returns> public static DataTable Search(IFeatureClass pFtClass, string pWhereClause) { //定義過濾器對象 IQueryFilter pQueryFilter = new QueryFilter(); //設置sql查詢語句 pQueryFilter.WhereClause = pWhereClause; //設置游標 //調用.Search方法;false表示游標到達最后一條要素以后不回收 //IFeatureCursor Search(IQueryFilter filter, bool Recycling); IFeatureCursor pFtCursor = pFtClass.Search(pQueryFilter, false); //聲明一個pFt要素並將查詢結果中的第一條Feature賦值給它 IFeature pFt = pFtCursor.NextFeature(); //實例化一個DataTable內存表對象, 用以存儲從要素中讀取出來的各屬性字段值 DataTable DT = new DataTable(); for (int i = 0; i < pFtCursor.Fields.FieldCount; i++) { //構建表結構:字段名和數據類型 DataColumn dc = new DataColumn(pFtCursor.Fields.get_Field(i).Name, System.Type.GetType(ParseFieldType(pFtCursor.Fields.get_Field(i).Type))); //字段生成完成后添加到DT的列中 DT.Columns.Add(dc); } //當pFt不為空, 遍歷查詢屬性值放到DataTable中顯示 while (pFt != null) { //遍歷查詢結果逐個寫入到DT中 DataRow dr = DT.NewRow(); //以DT的表結構新建行對象 for (int i = 0; i < pFt.Fields.FieldCount; i++) { dr[i] = pFt.get_Value(i); } //完成某一行的字段值錄入后向DT中添加此行對象 DT.Rows.Add(dr); //指向下一個要素 pFt = pFtCursor.NextFeature(); } return DT;//返回DataTable對象 }
III.空間查詢實現模塊
/// <summary> /// 核心空間查詢函數 /// </summary> /// <param name="pFtClass">查詢要素類</param> /// <param name="pWhereClause">SQL語句</param> /// <param name="pGeometry">空間查詢范圍</param> /// <param name="pSpRel">空間關系</param> /// <returns></returns> private DataTable SpatialSearch(IFeatureClass pFtClass, string pWhereClause, IGeometry pGeometry, esriSpatialRelEnum pSpRel) { //定義空間查詢過濾器對象 ISpatialFilter pSpatialFilter = new SpatialFilterClass(); //設置sql查詢語句 pSpatialFilter.WhereClause = pWhereClause; //設置查詢范圍 pSpatialFilter.Geometry = pGeometry; //給定范圍與查詢對象的空間關系 pSpatialFilter.SpatialRel = pSpRel; //查詢結果以游標的形式返回(下面與屬性查詢一樣) IFeatureCursor pFtCursor = pFtClass.Search(pSpatialFilter, false); IFeature pFt = pFtCursor.NextFeature(); DataTable DT = new DataTable(); for (int i = 0; i < pFtCursor.Fields.FieldCount; i++) { DataColumn dc = new DataColumn(pFtCursor.Fields.get_Field(i).Name, System.Type.GetType(ParseFieldType((pFtCursor.Fields.get_Field(i).Type)))); DT.Columns.Add(dc); } while (pFt != null) { DataRow dr = DT.NewRow(); for (int i = 0; i < pFt.Fields.FieldCount; i++) { dr[i] = pFt.get_Value(i); } DT.Rows.Add(dr); pFt = pFtCursor.NextFeature(); } return DT; }
IV.調用方法、顯示
1、屬性查詢
向ListBox中添加圖層字段:
/// <summary> /// 獲取ComboBox被選定的索引號 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void cboSelectLayer_SelectedIndexChanged(object sender, EventArgs e) { AddFields(); } /// <summary> /// 向ListBox中添加圖層字段 /// </summary> private void AddFields() { //清空ListBox lbShow.Items.Clear(); //將pWorkspace強轉成要素工作空間 IFeatureWorkspace pFtWorkspace = pWorkspace as IFeatureWorkspace; //通過要素工作空間打開cboSelectLayer選擇的圖層, 並放在要素類中 IFeatureClass pFtClass = pFtWorkspace.OpenFeatureClass(cboSelectLayer.Text); //打開游標, null為查詢全部, false表示游標到達最后一條要素以后不回收 IFeatureCursor pFtCursor = pFtClass.Search(null, false); //使用for循環逐一添加圖層字段 for (int i = 0; i < pFtCursor.Fields.FieldCount; i++) { IField pField = pFtCursor.Fields.get_Field(i); //獲取字段的下標 lbShow.Items.Add(pField.Name.ToString());//將字段名加到ListBox中 } }
獲取唯一值:
/// <summary> /// 獲取唯一值 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnGetValue_Click(object sender, EventArgs e) { lbValue.Items.Clear(); //將pWorkspace強轉成要素工作空間 IFeatureWorkspace pFtWorkspace = pWorkspace as IFeatureWorkspace; //通過要素工作空間打開cboSelectLayer選擇的圖層, 並放在要素類中 IFeatureClass pFtClass = pFtWorkspace.OpenFeatureClass(cboSelectLayer.Text); //打開游標, null為查詢全部, false表示游標到達最后一條要素以后不回收 IFeatureCursor pFtCursor = pFtClass.Search(null, false); //聲明一個pFt要素並將查詢結果中的第一條Feature賦值給它 IFeature pFt = pFtCursor.NextFeature(); //聲明index作為下標使用 int index = 0; //將index賦值為找到選中字段下標 index = pFtCursor.FindField(lbShow.Text); //當要素不為空時 while(pFt!=null) { //如果lbValue中包含要素下標則游標到下一個要素, 跳過本次循環 if(lbValue.Items.Contains(pFt.get_Value(index))) { pFt = pFtCursor.NextFeature(); continue; } //將游標的的要素加到lbValue中 lbValue.Items.Add(pFt.get_Value(index)); //轉到下一個要素 pFt = pFtCursor.NextFeature(); } }
查詢按鈕:
private void btnSelect_Click(object sender, EventArgs e) { //將工作空間強轉成要素工作空間 IFeatureWorkspace pFtWorkspace = pWorkspace as IFeatureWorkspace; //通過要素工作空間打開cboSelectLayer選擇的圖層, 並放在要素類中 IFeatureClass pFtClass = pFtWorkspace.OpenFeatureClass(cboSelectLayer.Text); try { //調用核心查詢方法, 返回類型為DataTable Global.myDGV1.DataSource = Search(pFtClass, txtSql.Text.Trim()); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
2、空間查詢
主視圖的OnMouseDown事件:
/// <summary> /// 主視圖的OnMouseDown事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void axMapControl1_OnMouseDown(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseDownEvent e) { //當空間查詢的狀態為真時 if (IsSpatialSearch) { //獲取精確圖層 ILayer pLayer = axMapControl1.get_Layer(Get_Layer("北部灣")); //將圖層強轉成要素圖層 IFeatureLayer pFtLayer = pLayer as IFeatureLayer; //將要素圖層的圖層類強轉成要素類 IFeatureClass pFtClass = pFtLayer.FeatureClass as IFeatureClass; //隨着鼠標拖動得到一個矩形框 IEnvelope pEnvelope = axMapControl1.TrackRectangle(); //調用核心空間查詢函數(采用空間相交的方法esriSpatialRelIntersects) dataGridView1.DataSource = SpatialSearch(pFtClass,"", pEnvelope,esriSpatialRelEnum.esriSpatialRelIntersects); axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null); } }
獲得精確圖層名下的index
/// <summary> /// 獲得精確圖層名下的index /// </summary> /// <param name="LayerName">圖層名字</param> /// <returns></returns> private int Get_Layer(string LayerName) { //遍歷主視圖的圖層 for (int i = 0; i < axMapControl1.LayerCount; i++) { //如果圖層索引對應的名字和用戶輸入的名字相同則返回索引 if (axMapControl1.get_Layer(i).Name.Equals(LayerName)) { return i; } } return -1;//返回-1 }
用於判斷空間查詢的狀態:
//用於判斷空間查詢的狀態 bool IsSpatialSearch = false;
謝謝觀看!本人初學GIS二次開發,如果有不對的地方,請多多包涵!