zoukankan      html  css  js  c++  java
  • 组件GIS 4 空间编辑

    TODO:属性表”属性修改“,属性表”字段计算器“,”非创建要素过程中”的撤销重做。

    4.1 纲要

    4.1.1 思维导图

    空间编辑

    4.1.2 接口、枚举

    • IEngineEditor,IEngineEditSketch,IEngineSketchOperation
    • IPoint,IPointCollection,IGeometry,IGeometryCollection

    4.1.3 效果动态图

    空间编辑效果

    4.2 编辑命令

    撤销重做包括“创建要素”过程中和非“创建要素”过程中,难度较大。

    4.2.1 开始编辑

    //1 获取目标图层
    cboEditingLyr.Items.Clear();
    List<string> targetEditingLyr = BasicClass.GetFeatureLayerNameList(axMapControl.Map);
    cboEditingLyr.Items.AddRange(targetEditingLyr.ToArray());
    cboEditingLyr.SelectedIndex = 0;
    //2 获取工作空间&开始编辑
    IDataset pSet = (IDataset)m_pFeaLyr.FeatureClass;
    IWorkspace pWs = pSet.Workspace;
    m_pEditor.EnableUndoRedo(true);//开启撤销重做
    m_pEditor.StartEditing(pWs, axMapControl.Map);
    

    4.2.2 保存编辑

    DialogResult isSave = MessageBox.Show("是否保存编辑?", "提示",
                                          MessageBoxButtons.YesNo, MessageBoxIcon.Question);
    IWorkspace pWs = m_pEditor.EditWorkspace;
    if (isSave == DialogResult.Yes)
    {
        m_pEditor.StopEditing(true);
        m_pEditor.StartEditing(pWs, axMapControl.Map);
        axMapControl.Refresh();
    }
    

    4.2.3 停止编辑

    DialogResult isSave = MessageBox.Show("是否保存编辑?", "提示",
                                          MessageBoxButtons.YesNo, MessageBoxIcon.Question);
    if (isSave == DialogResult.Yes)
        m_pEditor.StopEditing(true);
    else
        m_pEditor.StopEditing(false);
    

    4.2.4 撤销重做(创建要素过程中)

    找了草图工具创建要素过程中撤销重做的官方接口很久,尝试了IEngineEditSketch,IEngineSketchOperation,IOperationStack接口发现效果并不是我想要的,最后只能确定官方不提供,只能用C#的堆栈类实现。

    注:建议先看”创建要素“思路代码。

    撤销

    1. 初检:草图工具Geometry属性不为空;
    2. 入栈:草图工具最后一个点;备份点栈;
    3. 转为点串;
    4. 删除最后一个点(面要素是倒数第二个点);
    5. 复检:草图工具Geometry属性为空→关闭撤销许可。
    
    //1 初检
    if (!m_pSketch.Geometry.IsEmpty)
    {
        //2 入栈
        m_pPntStack.Push(m_pSketch.LastPoint);
        m_pPntStackCopy = m_pPntStack;//备份
        //3 删除
        IPointCollection pPntCol = (IPointCollection)m_pSketch.Geometry;
        if (m_pSketch.GeometryType == esriGeometryType.esriGeometryPolygon
            && pPntCol.PointCount > 1)
            pPntCol.RemovePoints(pPntCol.PointCount - 2, 1);
        else
            pPntCol.RemovePoints(pPntCol.PointCount - 1, 1);
        m_pSketch.Geometry = (IGeometry)pPntCol;
        //4 复检/更新许可
        if (m_pSketch.Geometry.IsEmpty)
            canUndo = false;
        canRedo = true;
    }
    //5 刷新
    m_pHookHelper.ActiveView.Refresh();
    

    重做

    1. 初检:栈内要素不为空;
    2. 出栈:获取一个点;
    3. 加点:草图工具添加一个点;
    4. 复检:点栈为空→从备份栈获取,关闭重做许可。
    
    //1 初检
    if (m_pPntStack.Count > 0)
    {
        //2 出栈
        IPoint pPnt = m_pPntStack.Pop();
        //3 复检
        if (m_pPntStack.Count == 0)
        {
            m_pPntStack = m_pPntStackCopy;
            canRedo = false;
        }
        //4 添加
        m_pSketch.AddPoint(pPnt, true);
        //5 许可
        canUndo = true;
    }
    //6 刷新
    m_pHookHelper.ActiveView.Refresh();
    

    快捷键设置

    给axMapControl.ContextMenu属性赋值一个右键菜单。

    4.3 要素编辑

    4.3.1 创建要素

    新建CreateFeatureTool类,实现ICommand和ITool接口,关键代码在ITool成员的OnMouseDown的响应事件中实现

    public void OnMouseDown(int button, int shift, int x, int y)
    {
        //转成地图坐标
        IPoint point = m_pHookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
        if (button == 1)
        {
            m_pSketch.AddPoint(point, true);//添加点
            m_pPntStack.Clear();//清空栈
            m_pPntStackCopy.Clear();//清空备份栈
            canUndo = true;//允许撤销
            isFinishedSketch = false;//创建要素过程中
        }
    }
    
    //完成草图
    public void OnDblClick()
    {
        m_pSketch.FinishSketch();
        isFinishedSketch = true;
    }
    

    4.3.2 移动要素

    使用组件库ICommand cmd = new ControlsEditingEditToolClass();

    4.3.3 删除要素

    使用组件库ICommand cmd = new ControlsEditingEditToolClass();

    4.4 结点编辑

    要理解”IHitTest.HitTest“参数

    image-20200630115035950

    bool isTrue = hitShape.HitTest(点击点, 搜索范围, 搜索类型, 反馈点, ref 反馈距离,
                         ref hitPartIndex, ref hitSegmentIndex, ref bRightSide);
    

    4.4.1 结点插入

    参考帮助文档”CustomVertexCommands“,”EditingVertexCommands“。

    public void OnMouseDown(int button, int shift, int x, int y)
    {
        //转成地图坐标
        IPoint clickedPt = m_pHookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
        if (button == 1)
        {
            #region 1 获取点击测试参数
                IHitTest hitShape = (IHitTest)m_pSketch.Geometry;
            IPoint hitPoint = new PointClass();
            double hitDistance = 0;
            int hitPartIndex = 0;
            int hitSegmentIndex = 0;
            bool bRightSide = false;
            esriGeometryHitPartType hitPartType = esriGeometryHitPartType.esriGeometryPartNone;
            double searchRadius = 50;
            #endregion
    
            //2 节点判断
            hitPartType = esriGeometryHitPartType.esriGeometryPartVertex;
            bool isTrue = hitShape.HitTest(clickedPt, searchRadius, hitPartType, hitPoint, ref hitDistance,
                                           ref hitPartIndex, ref hitSegmentIndex, ref bRightSide);
            if (isTrue) return; //已存在节点,不需要添加
            //3 点击测试
            hitPartType = esriGeometryHitPartType.esriGeometryPartBoundary;
            isTrue = hitShape.HitTest(clickedPt, searchRadius, hitPartType, hitPoint, ref hitDistance,
                                      ref hitPartIndex, ref hitSegmentIndex, ref bRightSide);
            //4 添加节点 
            if (isTrue)
            {
                //4.1 草图操作开始
                IEngineSketchOperation pSketchOp = new EngineSketchOperationClass();
                pSketchOp.Start(m_pEditor);
                pSketchOp.SetMenuString("Insert Vertex (Custom)");
                //4.2 获取点串
                IGeometryCollection pGeoCol = (IGeometryCollection)m_pSketch.Geometry;
                IPointCollection pPathOrRingPtCol = (IPointCollection)pGeoCol.get_Geometry(hitPartIndex);
                //4.3 插入节点
                object missing = Type.Missing;
                object hitSegmentIndexObject = hitSegmentIndex;
                object partIndexObject = hitPartIndex;
                pPathOrRingPtCol.AddPoint(hitPoint, ref missing, ref hitSegmentIndexObject);
                //4.4 移除旧的,添加新的
                pGeoCol.RemoveGeometries(hitPartIndex, 1);
                pGeoCol.AddGeometry((IGeometry)pPathOrRingPtCol, ref partIndexObject, ref missing);
                //4.5 草图操作完成
                esriEngineSketchOperationType opType =
                    esriEngineSketchOperationType.esriEngineSketchOperationVertexAdded;
                pSketchOp.Finish(null, opType, hitPoint);
            }
        }
    }
    

    4.4.2 结点删除

    public void OnMouseDown(int button, int shift, int x, int y)
    {
        //转成地图坐标
        IPoint clickedPt = m_pHookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
        if (button == 1)
        {
            #region 1 获取点击测试参数
                IHitTest hitShape = (IHitTest)m_pSketch.Geometry;
            IPoint hitPoint = new PointClass();
            double hitDistance = 0;
            int hitPartIndex = 0;
            int hitSegmentIndex = 0;
            bool bRightSide = false;
            esriGeometryHitPartType hitPartType = esriGeometryHitPartType.esriGeometryPartNone;
            double searchRadius = 50;
            #endregion
    
            //2 节点判断
            hitPartType = esriGeometryHitPartType.esriGeometryPartVertex;
            bool isTrue = hitShape.HitTest(clickedPt, searchRadius, hitPartType, hitPoint, ref hitDistance,
                                           ref hitPartIndex, ref hitSegmentIndex, ref bRightSide);
            //3 删除节点 
            if (isTrue)
            {
                //3.1 草图操作开始
                IEngineSketchOperation pSketchOp = new EngineSketchOperationClass();
                pSketchOp.Start(m_pEditor);
                pSketchOp.SetMenuString("Delete Vertex (Custom)");
                //3.2 获取点串
                IGeometryCollection pGeoCol = (IGeometryCollection)m_pSketch.Geometry;
                IPointCollection pPathOrRingPtCol = (IPointCollection)pGeoCol.get_Geometry(hitPartIndex);
                //3.3 删除节点
                object missing = Type.Missing;
                object partIndexObject = hitPartIndex;
                pPathOrRingPtCol.RemovePoints(hitSegmentIndex, 1);
                //4.4 移除旧的,添加新的
                pGeoCol.RemoveGeometries(hitPartIndex, 1);
                pGeoCol.AddGeometry((IGeometry)pPathOrRingPtCol, ref partIndexObject, ref missing);
                //4.5 草图操作完成
                esriEngineSketchOperationType opType =
                    esriEngineSketchOperationType.esriEngineSketchOperationVertexDeleted;
                pSketchOp.Finish(null, opType, hitPoint);
            }
        }
    }
    

    4.4.3 结点移动

    使用组件库ICommand cmd = new ControlsEditingEditToolClass();

    4.5 属性编辑

    注:这里的保存是保存在”工作空间“,还没有保存到数据库中,需要点击【保存编辑】才是真正的保存在数据库中

    4.5.1 对话框布局

    属性编辑对话框

    4.5.1 关键代码

    for (int i = 0; i < dgvAttributeEdit.RowCount; i++)
    {
        string sFieldName = (string)dgvAttributeEdit.Rows[i].Cells[0].Value;
        object objFieldValue = dgvAttributeEdit.Rows[i].Cells[1].Value;
        if (sFieldName != null && sFieldName != string.Empty
            && !sFieldName.ToUpper().Equals("OBJECTID") && objFieldValue != null)
        {
            int index = m_pFea.Fields.FindField(sFieldName);
            m_pFea.Value[index] = objFieldValue;
        }
    }
    m_pFea.Store();
    
  • 相关阅读:
    合理的嵌入式开发学习路线
    Nginx
    RARP
    强弱电共地
    ACDC
    各电脑进Bios方法
    Java中Integer.parseInt
    全排列
    Java实现LRU缓存方案?
    缓存有关的几个问题
  • 原文地址:https://www.cnblogs.com/liuwenzhen/p/13213041.html
Copyright © 2011-2022 走看看