组件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();
原文地址:https://www.cnblogs.com/liuwenzhen/p/13213041.html