zoukankan      html  css  js  c++  java
  • ArcGIS Engine空间查询功能的实现(QueryFilterClass+SpatialFilterClass)

    地图中包含大量的信息,为了快速地了解所需信息,必须借助为空间数据专门编写的空间查询功能

    空间查询主要有两种类型

    基于属性的查询,也称为属性查询

    基于空间位置的查询,也称为空间查询

    查询类的基本思路(适用于属性查询以及空间查询)

    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二次开发,如果有不对的地方,请多多包涵!

  • 相关阅读:
    app被Rejected 的各种原因翻译
    UIView Border color
    Centos7下安装docker
    利用Yum彻底移除docker
    Docker删除全部镜像和容器
    【转】哈哈笑一笑
    【转】KAFKA分布式消息系统
    java读取properties文件
    java反序列化php序列化的对象
    Java 1.7.0_06中String类内部实现的一些变化【转】
  • 原文地址:https://www.cnblogs.com/edcoder/p/11742063.html
Copyright © 2011-2022 走看看