ArcEngine空间编辑(开始编辑与选择要素举例)

来源:互联网 发布:c语言中用户标识符 编辑:程序博客网 时间:2024/06/05 00:09

最近琢磨了一下ArcEngine的空间编辑功能,包括开始/保存/结束编辑,选择要素,移动要素,删除要素,剪切要素,粘贴要素,添加要素,点线面的绘画,属性编辑,撤销和恢复着几项。其实这些空间编辑功能有一些是可以直接调用类库命令来进行编辑的,有些是需要自定义一个继承了ICommand和ITool的类来添加命令。 

我在这里就举以上选择要素的例子来说明如何自定义类来添加命令。首先介绍一下开始编辑。

一、开始编辑


在开始编辑之前我们必须要选定图层,即对那个图层进行编辑命令,所以在窗口上需要添加一个ComboBox控件,用来选择需要编辑的图层。我们需要将加载出来的mxd文件中的各个图层名放入ComboBox中。

1、定义一个函数用于获取当前地图文档所有图层集合,具体函数如下:

        /// <summary>        /// 获取当前地图文档所有图层集合        /// </summary>        /// <param name="pMap"></param>        /// <returns></returns>        public static List<ILayer> GetLayers(IMap pMap)        {            ILayer plyr = null;            List<ILayer> pLstLayers = null;            try            {                pLstLayers = new List<ILayer>();                for (int i = 0; i < pMap.LayerCount; i++)                {                    plyr = pMap.get_Layer(i);                    if (!pLstLayers.Contains(plyr))                    {                        pLstLayers.Add(plyr);                    }                }            }            catch (Exception ex)            { }            return pLstLayers;        }
2、设置ComboBox的SelectedIndexChanged事件

在写ComboBox的SelectedIndexChanged事件之前需要先定义一些全局变量

private IFeatureLayer pCurrentLyr = null;

private IEngineEditLayers pEngineEditLayers = null;

定义完后我们来写这个事件:

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)        {            string sLyrName = cmbSelLayer.SelectedItem.ToString();            pCurrentLyr = MapManager.GetLayerByName(pMap, sLyrName) as IFeatureLayer;            //设置编辑目标图层            pEngineEditLayers.SetTargetLayer(pCurrentLyr, 0);        }
3、通过单击ComboBox来获取各个图层名

同样的需要先定义各个变量:

        private IMap pMap = null;

        private IActiveView pActiveView = null;

        private List<ILayer> plstLayers = null;
单击ComboBox获取图层名:

        private void cmbSelLayer_Click(object sender, EventArgs e)        {            pMap = axMapControl1.Map;            pActiveView = pMap as IActiveView;            plstLayers = MapManager.GetLayers(pMap);            //List<ILayer> plstLyt = new List<ILayer>();            cmbSelLayer.Items.Clear();            for (int i = 0; i < plstLayers.Count; i++)            {                if (!cmbSelLayer.Items.Contains(plstLayers[i].Name))                {                    cmbSelLayer.Items.Add(plstLayers[i].Name);                }            }            if (cmbSelLayer.Items.Count != 0) cmbSelLayer.SelectedIndex = 0;        }

4、获取到图层名之后就可以点击“开始编辑”按钮开始编辑

当然依旧不要忘了定义变量,我这里就不列出来了,形式如上面两个一样。

其中ChangeButtonState()是自定义的控制各个按钮是否Enable的函数,未开始编辑之前为false,开始编辑之后为true。

        /// <summary>        /// 开始编辑        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void btnStartEdit_Click(object sender, EventArgs e)        {            try            {                if (plstLayers == null || plstLayers.Count == 0)                {                    MessageBox.Show("请加载编辑图层!", "提示",MessageBoxButtons.OK, MessageBoxIcon.Information);                    return;                }                pMap.ClearSelection();                pActiveView.Refresh();                //InitComboBox(plstLayers);                ChangeButtonState(true);                //如果编辑已经开始,则直接退出                if (pEngineEditor.EditState != esriEngineEditState.esriEngineStateNotEditing)                    return;                if (pCurrentLyr == null) return;                //获取当前编辑图层工作空间                IDataset pDataSet = pCurrentLyr.FeatureClass as IDataset;                IWorkspace pWs = pDataSet.Workspace;                //设置编辑模式,如果是ArcSDE采用版本模式                if (pWs.Type == esriWorkspaceType.esriRemoteDatabaseWorkspace)                {                    pEngineEditor.EditSessionMode = esriEngineEditSessionMode.esriEngineEditSessionModeVersioned;                }                else                {                    pEngineEditor.EditSessionMode = esriEngineEditSessionMode.esriEngineEditSessionModeNonVersioned;                }                //设置编辑任务                pEngineEditTask = pEngineEditor.GetTaskByUniqueName("ControlToolsEditing_CreateNewFeatureTask");                pEngineEditor.CurrentTask = pEngineEditTask;// 设置编辑任务                pEngineEditor.EnableUndoRedo(true); //是否可以进行撤销、恢复操作                pEngineEditor.StartEditing(pWs, pMap); //开始编辑操作            }            catch (Exception ex)            {            }        }

二、选择要素

开始编辑之后就可以选择要素了。在工程中新建一个SelectFeatureToolClass类。
1、引用
using ESRI.ArcGIS.SystemUI;using ESRI.ArcGIS.Carto;using ESRI.ArcGIS.Controls;using ESRI.ArcGIS.Geodatabase;using ESRI.ArcGIS.Geometry;using ESRI.ArcGIS.Display;
2、继承ICommand和ITool接口,定义全局变量
        private IMap m_Map = null;        private bool bEnable = true;        private IHookHelper m_hookHelper = null;        private IActiveView m_activeView = null;        private IEngineEditor m_EngineEditor = null;        private IEngineEditLayers m_EngineEditLayers = null;
3、ITool接口的成员实现:

        #region ITool 成员        public int Cursor        {            get { return -1; }        }        public bool Deactivate()        {            return true;        }        public bool OnContextMenu(int x, int y)        {            return false;        }        public void OnDblClick()        {        }        public void OnKeyDown(int keyCode, int shift)        {        }        public void OnKeyUp(int keyCode, int shift)        {        }        public void OnMouseDown(int button, int shift, int x, int y)        {            try            {                if (m_EngineEditor == null) return;                if (m_EngineEditor.EditState != esriEngineEditState.esriEngineStateEditing) return;                if (m_EngineEditLayers == null) return;                //获取目标图层                IFeatureLayer pFeatLyr = m_EngineEditLayers.TargetLayer;                IFeatureClass pFeatCls = pFeatLyr.FeatureClass;                //获取地图上的坐标点                IPoint pPt = m_activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);                IGeometry pGeometry = pPt as IGeometry;                double dLength = 0;                ITopologicalOperator pTopo = pGeometry as ITopologicalOperator;                //设置选择过滤条件                ISpatialFilter pSpatialFilter = new SpatialFilterClass();                //不同的图层类型设置不同的过滤条件                switch (pFeatCls.ShapeType)                {                    case esriGeometryType.esriGeometryPoint:                        //将像素距离转换为地图单位距离                        dLength = MapManager.ConvertPixelsToMapUnits(m_activeView, 8);                        pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;                        break;                    case esriGeometryType.esriGeometryPolygon:                        dLength = MapManager.ConvertPixelsToMapUnits(m_activeView, 4);                        pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;                        break;                    case esriGeometryType.esriGeometryPolyline:                        dLength = MapManager.ConvertPixelsToMapUnits(m_activeView, 4);                        pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelCrosses;                        break;                }                //根据过滤条件进行缓冲                IGeometry pBuffer = null;                pBuffer = pTopo.Buffer(dLength);                pGeometry = pBuffer.Envelope as IGeometry;                pSpatialFilter.Geometry = pGeometry;                pSpatialFilter.GeometryField = pFeatCls.ShapeFieldName;                IQueryFilter pQueryFilter = pSpatialFilter as IQueryFilter;                //根据过滤条件进行查询                IFeatureCursor pFeatCursor = pFeatCls.Search(pQueryFilter, false);                IFeature pFeature = pFeatCursor.NextFeature();                while (pFeature != null)                {                    //获取地图选择集                    m_Map.SelectFeature(pFeatLyr as ILayer, pFeature);                    pFeature = pFeatCursor.NextFeature();                }                m_activeView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, null);                System.Runtime.InteropServices.Marshal.ReleaseComObject(pFeatCursor);            }            catch (Exception ex)            {            }        }        public void OnMouseMove(int button, int shift, int x, int y)        {        }        public void OnMouseUp(int button, int shift, int x, int y)        {        }        public void Refresh(int hdc)        {        }        #endregion
其中OnMouseDown是鼠标按下时所发生的事件。

4、ICommand接口的成员实现:
        #region ICommand 成员        public int Bitmap        {            get { return -1; }        }        public string Caption        {            get { return "选择要素"; }        }        public string Category        {            get { return "编辑工具"; }        }        public bool Checked        {            get { return false; }        }        public bool Enabled        {            get { return bEnable; }        }        public int HelpContextID        {            get { return -1; }        }        public string HelpFile        {            get { return ""; }        }        public string Message        {            get { return "选择要素"; }        }        public string Name        {            get { return "SelectFeatureTool"; }        }        public void OnClick()        {            m_Map = m_hookHelper.FocusMap;            m_activeView = m_Map as IActiveView;            m_EngineEditor = MapManager.EngineEditor;            m_EngineEditLayers = MapManager.EngineEditor as IEngineEditLayers;            //EditVertexClass.ClearResource();        }        public void OnCreate(object Hook)        {            if (Hook == null) return;            try            {                m_hookHelper = new HookHelperClass();                m_hookHelper.Hook = Hook;                if (m_hookHelper.ActiveView == null)                    m_hookHelper = null;            }            catch            {                m_hookHelper = null;            }            if (m_hookHelper == null)                bEnable = false;            else                bEnable = true;        }        public string Tooltip        {            get { return "选择要素"; }        }        #endregion
需要注意的是,ICommand和ITool接口中的所有函数都得写上去实现,否则报错。

那么现在自定义的SelectFeatureToolClass类就写好了,接下来只要调用这个类就可以实现对图层要素的选择。

5、“选择要素”按钮的Click事件

        /// <summary>        /// 选择要素        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void btnSelectedEdit_Click(object sender, EventArgs e)        {            try            {                ////调用类库                //axMapControl1.CurrentTool = null;                //ControlsSelectFeaturesTool pTool = new ControlsSelectFeaturesToolClass();                //pTool.OnCreate(axMapControl1.Object);                //axMapControl1.CurrentTool = pTool as ITool;                                ICommand m_SelTool = new SelectFeatureToolClass();                m_SelTool.OnCreate(axMapControl1.Object);                m_SelTool.OnClick();                axMapControl1.CurrentTool = m_SelTool as ITool;                axMapControl1.MousePointer = esriControlsMousePointer.esriPointerArrow;            }            catch (Exception ex)            {            }        }
从上面的代码中可以看出,还有一个调用类库的方法。调用类库的方法其实也可以,但是和自定义函数的是有区别的。

用调用类库的方法进行选择要素无视对图层的选择,所有的图层上的要素都可以进行选择;自定义类方法进行选择要素是根据选择的图层进行选择,不是当前ComboBox中的当前图层不会进行选中。
当然,调用类库的方法也可以根据当前图来选择,不过我还没写出来,如果知道如何写的大佬们请务必告知,交流知识经验嘛。

关于其他例如移动要素啊删除要素啊之类的方法如同选择要素,就是自定义类,然后调用。当然这些都是在选择要素的基础上进行的,不先选择怎么移动和删除对不对。

如果有空的话我会再写其他有关空间编辑的操作,今天就先这样。



















原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 国美东西买贵啦怎么办 饥荒咕咕鸟死了怎么办 收到催天下信息怎么办 对门邻居有白事怎么办 顺丰理赔不合理怎么办 手机店抽奖被骗怎么办 手机店投票被骗怎么办 锤子手机进水了怎么办 锤子手机无法关机怎么办 坚果pro2卡顿怎么办 兴隆破产兴隆卡怎么办 电脑开机键失灵怎么办 网上买冰箱售后怎么办 物流公司损坏了怎么办 白色充电器线脏了怎么办 卷尺缩不回去怎么办 在昆山怎么办电瓶车牌 网购遇到质量问题怎么办 洗衣机外壳坏了怎么办 8元飞享套餐下线怎么办 改光纤后传真机怎么办 网上预约迟到了怎么办 国地税合并局长怎么办? 信用卡申请条件不足怎么办 深户落亲戚房产怎么办准迁证 从深圳迁出户口怎么办 快递未送达签收怎么办 床垫用水洗后怎么办 轿车空调不制冷怎么办 空调氟漏完了怎么办 一窗式比对异常怎么办 高铁票无座怎么办 公司把社保断交怎么办 电信宽带电视无信号怎么办 电信电视没信号怎么办 苹果键盘进水了怎么办 电信怎么办日流量包 济南华强坑人怎么办 超市提货券过期怎么办 深圳天虹怎么办会员卡 超市会员卡丢了怎么办