基于C#的ArcEngine二次开发46:编辑内容回撤与炸开multipart feature

简介: 基于C#的ArcEngine二次开发46:编辑内容回撤与炸开multipart feature

绘制街道时,我们会对LRDL、VEGA、RESA、RESL和RESP中的要素进行操作,编辑完成后,改动的要素涉及多个图层,一旦出错,回撤功能将变得十分重要;同时,截取裁切LRDL面会产生许多复合要素(multipart feature),要求是不能产生复合要素。本文针对这两个问题,进行分析和探讨。

1 支持撤销操作

1.1 方法接口介绍

arcengine中使用StartOperation 和StopOperation,将编辑操作记录到ArcGIS引擎中


每一个开始结束对之间的操作会被存储在一个操作栈中,点击undo时,会以整个操作栈的形式,执行撤销操作


不能保存编辑或者停止编辑,否则会出错;


在StopOperation之后,不能再在同一函数或按钮中,对刚才操作栈进行修改,否则调试不会出错;运行会崩


1.1.1 StartOperation()

[C#]public void StartOperation ();

Description


StartOperation marks the beginning of an edit operation. To provide undo/redo capability programmatically all edits must be performed within an edit operation. (标记编辑操作的开始,提供了以编程方式记录编辑操作中执行的所有编辑)


Calling IEngineEditor::StopOperation completes an edit operation which is then added to the top of the operation stack. The operation stack is how ArcGIS Engine implements Undo and Redo. When using StartOperation, proper error handling, including the use of IEgineEditor::AbortOperation, is neccessary.(调用StopOperation完成编辑操作,然后将其添加到操作堆栈的顶部。操作堆栈是ArcGIS引擎如何实现撤消和重做的。使用StartOperation时,必须进行正确的错误处理,包括使用IEEngineEditor:AbortOperation)


Edit operations cannot be nested; calling StartOperation within another operation will raise an error.(不能嵌套编辑操作,在另一个操作中调用StartOperation将引发错误)


Remarks


This method fires the IEngineEditEvents::OnStartOperation event.


(该方法将触发OnStartOperation事件)


1.1.2 StopOperation


1. [C#]public void StopOperation (
2.     stringoperationName);


Description


StopOperation marks the end of an edit operation. Calling StopOperation creates an edit operation that is added to the top of the operation stack. The operation stack is how ArcGIS Engine implements Undo and Redo.(StopOperation标记编辑操作的结束,调用该方法将在操作栈的顶部创建一个编辑操作,这也是ArcGIS引擎实现撤销和重做的操作栈)


When using IEngineEditor::StartOperation proper handling of errors, including the use of IEngineEditor::AbortOperation, is neccessary.(使用StartOperation 时,必须进行正确的错误处理,包括使用IEEngineEditor:AbortOperation)


The string argument allows the operation to be identified on the operaton stack.(不能嵌套编辑操作,在另一个操作中调用StartOperation将引发错误)


Remarks


This method fires the IEngineEditEvents::OnBeforeStopOperation and IEngineEditEvents::OnStopOperation events.


该方法将触发OnBeforeStopOperation 和OnStopOperation 事件


1.2 代码实现

public void supportUndo()
{
    UID editorUID= new UIDClass();
    editorUID.Value = "esriEditor.Editor";
    IMxApplication mxApplication = new ArcMap.ThisApplication;
    IApplication application = mxApplication as IApplication;
    IEidtor pEditor = application.FindExtensionByCLSID(editorID) as IEidtor;
    IEditorLayers pEditorLayer = pEditor as IEditorLayers;
    if(pEditor.EditState != esriEditState.esriStateEditing)
    {
        MessageBox("先打开编辑器");
        return;
    }
    IActiveView pActiveView = ArcMap.Document.FocusMap as IActiveView;
    pEditor.StartOperation();
    //-------------------------------------------------------
    // 绘制街区,标记删除点房,道路GB修改等操作
    //-------------------------------------------------------
    pEditor.StopOperation("Edit Finshed");
}

2 炸开复合要素(explode multipart feature)


关于这个问题,网上大多是ArcEngine判断要素(feature)是否为multipart feature及分解(炸开)代码文章的复制版本,但是有一个问题,他的代码中有一个变量GeometryHelper未明确说明,无法验证代码可行与否,所幸找到如下一篇文章


explode multiPart 炸开多部件(复杂对象)又称为多部分: https://blog.csdn.net/gishys/article/details/55100655


较好的解决了我的问题:


其思路为先将multipart feature包含的各个Geometry取出来,以创建要素的方式将其添加到图层中;之后再删除原multipart feature

public void ExplodeMultipart(IFeatureClass ExFeature)
        {
            IFeatureCursor mFeatureCursor = ExFeature.Update(null, false);
            IFeature mFeature = mFeatureCursor.NextFeature();
            IWorkspace del_workspace = (ExFeature as IDataset).Workspace;
            IWorkspaceEdit del_workspaceedit = del_workspace as IWorkspaceEdit;
            if (del_workspaceedit.IsBeingEdited() == true)
                del_workspaceedit.StopEditing(true);
            del_workspaceedit.StartEditing(false);
            del_workspaceedit.StartEditOperation();
            while (mFeature != null)
            {
                IGeometryCollection mGeometryCol = mFeature.ShapeCopy as IGeometryCollection;
                int mGeoCount = mGeometryCol.GeometryCount;
                int idRemark = -1;
                if (mGeoCount > 1)
                {
                    idRemark = int.Parse(mFeature.get_Value(0).ToString());
                    for (int index = 0; index < mGeoCount; index++)
                    {
                        IFeature mNewFeature =
                            (mFeature.Class as IFeatureClass).CreateFeature();
                        IFeatureEdit mFeatureEdit = mFeature as IFeatureEdit;
                        mFeatureEdit.SplitAttributes(mNewFeature);
                        IGeometry mGeoNew = mGeometryCol.get_Geometry(index);
                        mGeoNew.SpatialReference = mFeature.Shape.SpatialReference;
                        IGeometryCollection mGCollection = new PolygonClass();
                        mGCollection.AddGeometry(mGeoNew);
                        mNewFeature.Shape = mGCollection as IGeometry;
                        mNewFeature.Store();
                    }
                }
                if (idRemark != -1)
                {
                    mFeatureCursor.DeleteFeature();
                    idRemark = -1;
                }
                mFeature = mFeatureCursor.NextFeature();
            }
            del_workspaceedit.StopEditOperation();
            del_workspaceedit.StopEditing(true);
        }

3 Multipart To Singlepart

该工具定义在ArcToolbox/DataManagementTools/Features/Multipart To Singlepart下

3.1 原理描述

创建包含通过分割多部件输入要素而生成的单部件要素的要素类

2020080810222461.png


3.2 使用方法

输入要素的属性将保留在输出要素类中。向输出要素类添加新字段 ORIG_FID,并设置为输入要素 ID。


多部件要素的各个部件在输出要素类中将成为独立的要素。已经是单部件的要素不会受到影响。


大多数输出要素的类型与输入要素的类型相同(输入面仍为面;输入线仍为线)。唯一的例外是当输入要素类型为多点时,输出要素类的类型将为点。


要使用单部件要素根据公用字段值重新构建多部件要素(例如 ORIG_FID),请使用融合工具。


多面体要素将被分为其构成的几何部件。每一部件可定义为包含 X、Y 和 Z 坐标的折点集合,请形式如下所示:


引用 3 个折点的单个三角形。

三角条带由共享同一条公用边的多个三角形定义。

三角扇由具有公用原点的多个三角形定义。

表示由 4 个或更多折点定义边界的共平面区域的圆环。


3.3 语法

MultipartToSinglepart(in_features, out_feature_class)

image.png

3.4 python代码示例

MultipartToSinglepart 示例 1(Python 窗口)

以下 Python 窗口脚本演示了如何在即时模式下使用 MultipartToSinglepart 函数。

import arcpy
arcpy.env.workspace = "C:/data"
arcpy.MultipartToSinglepart_management("landuse.shp","c:/output/output.gdb/landuse_singlepart")


MultipartToSinglepart 示例 2(独立脚本)

以下独立脚本是演示如何在脚本环境中应用 MultipartToSinglepart 函数的简单示例。

# Name: MultipartToSinglepart_Example2.py
# Description: Break all multipart features into singlepart features,
#              and report which features were separated.
# Import system modules
import arcpy
# Create variables for the input and output feature classes
inFeatureClass = "c:/data/gdb.gdb/vegetation"
outFeatureClass = "c:/data/gdb.gdb/vegetation_singlepart"
try:
    # Create list of all fields in inFeatureClass
    fieldNameList = [field.name for field in arcpy.ListFields(inFeatureClass)]
    # Add a field to the input this will be used as a unique identifier
    arcpy.AddField_management(inFeatureClass, "tmpUID", "double")
    # Determine what the name of the Object ID is 
    OIDFieldName = arcpy.Describe(inFeatureClass).OIDFieldName
    # Calculate the tmpUID to the OID
    arcpy.CalculateField_management(inFeatureClass, "tmpUID",
                                    "!" + OIDFieldName + "!", "PYTHON")
    # Run the tool to create a new fc with only singlepart features
    arcpy.MultipartToSinglepart_management(inFeatureClass, outFeatureClass)
    # Check if there is a different number of features in the output
    #   than there was in the input
    inCount = int(arcpy.GetCount_management(inFeatureClass).getOutput(0))
    outCount = int(arcpy.GetCount_management(outFeatureClass).getOutput(0))
    if inCount != outCount:
        # If there is a difference, print out the FID of the input 
        #   features which were multipart
        arcpy.Frequency_analysis(outFeatureClass,
                                 outFeatureClass + "_freq", "tmpUID")
        # Use a search cursor to go through the table, and print the tmpUID 
        print("Multipart features from {0}".format(inFeatureClass))
        for row in arcpy.da.SearchCursor(outFeatureClass + "_freq",
                                         ["tmpUID"], "FREQUENCY > 1"):
            print(int(row[0]))
    else:
        print("No multipart features were found")
except arcpy.ExecuteError:
    print(arcpy.GetMessages())
except Exception as err:
    print(err.args[0])

官方注解网址:https://pro.arcgis.com/zh-cn/pro-app/tool-reference/data-management/multipart-to-singlepart.htm


相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
相关文章
|
7月前
|
C# Windows
C#通过代码实现快捷键编辑
C#通过代码实现快捷键编辑
|
Web App开发 存储 C#
C# 10分钟入门基于WebOffice实现在线编辑文档,实时保存到服务器(所有office,兼容WPS)
C# 10分钟入门基于WebOffice实现在线编辑文档,实时保存到服务器(所有office,兼容WPS)
|
7月前
|
C#
[C#] 如何在子线程中显示编辑控件内容
[C#] 如何在子线程中显示编辑控件内容
58 0
基于C#的ArcEngine二次开发56:双击属性表跳转目标要素并闪烁
基于C#的ArcEngine二次开发56:双击属性表跳转目标要素并闪烁
基于C#的ArcEngine二次开发56:双击属性表跳转目标要素并闪烁
基于C#的ArcEngine二次开发54:IStatusBar状态栏接口的使用
基于C#的ArcEngine二次开发54:IStatusBar状态栏接口的使用
基于C#的ArcEngine二次开发54:IStatusBar状态栏接口的使用
|
NoSQL 数据处理 C#
基于C#的ArcEngine二次开发52:GDB数据处理过程中与Name相关的操作
基于C#的ArcEngine二次开发52:GDB数据处理过程中与Name相关的操作
基于C#的ArcEngine二次开发52:GDB数据处理过程中与Name相关的操作
基于C#的ArcEngine二次开发51:获取图层字段唯一值列表(Get Unique Values)
基于C#的ArcEngine二次开发51:获取图层字段唯一值列表(Get Unique Values)
|
算法 C#
基于C#的ArcEngine二次开发50:生成面空洞连接线
基于C#的ArcEngine二次开发50:生成面空洞连接线
基于C#的ArcEngine二次开发50:生成面空洞连接线
|
存储 NoSQL Unix
基于C#的ArcEngine二次开发50:MDB创建新要素类及“无当前记录”异常处理
基于C#的ArcEngine二次开发50:MDB创建新要素类及“无当前记录”异常处理
基于C#的ArcEngine二次开发50:MDB创建新要素类及“无当前记录”异常处理