ArcMap的Editor工具,实现要素拖动、编
更新时间:2023-11-07 04:34:01 阅读量: 教育文库 文档下载
ArcMap的Editor工具,实现要素拖动、编辑。
本来根本没有写这个工具的意思,自己一直用的Ae自带的工具。虽然可控制力弱了一些,但终究还是凑或能用。一天,问到一个同学,想请教一下,居然以百般理由回绝。算了,秉承毛老人家的口号:自力更生,丰衣足食!好了,闲话少说,各位看官,咱步入正题了。
首先,说一下,所有的要素的更新、插入、删除最好放在编辑的Session 里面,即以一对StartEditing和StopEditing包裹。
一开始我的疑问在于,为什么我用IWorkspaceEdit的StartEditing方法后,怎么鼠标不会变成AcrMap里面Editor的开始编辑那样呢,为什么不能选中要素,为什么不能双击后编辑要素?原来,选中要素和使要素处于编辑状态还是要自己写的(经高人指点,呵呵)。
先介绍一下程序中用到的变量:
Code
那我们就按照逻辑顺序来一一展示这个到底是怎么做的。首先是,开始和结束编辑的代码:
///
///
if (m_SelectedLayer == null) return;
IFeatureLayer featureLayer = m_SelectedLayer as IFeatureLayer; if (featureLayer == null) return;
IFeatureClass featureClass = featureLayer.FeatureClass; if (featureClass == null) return;
IDataset dataset = featureClass as IDataset;
IWorkspaceEdit workspaceEdit = dataset.Workspace as IWorkspaceEdit; try {
workspaceEdit.StartEditing(bWithUndoRedo); m_IsEdited = true; } catch {
return; } }
当然你可以直接传进来IWorkspace,这个可根据你具体的需求,我这里用当前图层获取工作空间。
///
///
public void StopEditing(bool bSave) {
if (m_IsEdited) {
m_IsEdited = false;
if (m_SelectedLayer == null) return;
IFeatureLayer featureLayer = m_SelectedLayer as IFeatureLayer; if (featureLayer == null) return;
IFeatureClass featureClass = featureLayer.FeatureClass; if (featureClass == null) return;
IDataset dataset = featureClass as IDataset;
IWorkspaceEdit workspaceEdit = dataset.Workspace as IWorkspaceEdit; if (workspaceEdit.IsBeingEdited()) {
try {
workspaceEdit.StopEditing(bSave); } catch {
workspaceEdit.AbortEditOperation(); return; } } } }
开始编辑已经好了,然后就是鼠标点击要素时候,让其处于选中状态,我这里为了方便控制,我分成了两个函数写,给为看官也可以合并成一个:
public void GetFeatureOnMouseDown(int x, int y) {
m_SelectedFeature.Clear(); try {
if (m_SelectedLayer == null) return;
IFeatureLayer featureLayer = m_SelectedLayer as IFeatureLayer; if (featureLayer == null) return;
IFeatureClass featureClass = featureLayer.FeatureClass; if (featureClass == null) return;
IPoint point = m_MapControl.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
IGeometry geometry = point as IGeometry;
double length = ConvertPixelsToMapUnits(4);
ITopologicalOperator pTopo = geometry as ITopologicalOperator; IGeometry buffer = pTopo.Buffer(length); geometry = buffer.Envelope as IGeometry;
ISpatialFilter spatialFilter = new SpatialFilterClass(); spatialFilter.Geometry = geometry; switch (featureClass.ShapeType) {
case esriGeometryType.esriGeometryPoint:
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains; break;
case esriGeometryType.esriGeometryPolygon:
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; break;
case esriGeometryType.esriGeometryPolyline:
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelCrosses; break; }
spatialFilter.GeometryField = featureClass.ShapeFieldName; IQueryFilter filter = spatialFilter as IQueryFilter;
IFeatureCursor cursor = featureClass.Search(filter, false); IFeature pfeature = cursor.NextFeature(); while (pfeature != null) {
m_SelectedFeature.Add(pfeature); pfeature = cursor.NextFeature(); } } catch {
return; } }
///
/// 根据鼠标点击位置使击中要素处于高亮显示状态 ///
///
{ try {
if (m_SelectedLayer == null) return; m_MapControl.Map.ClearSelection();
m_MapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, null);
foreach (IFeature feature in m_SelectedFeature.ToArray()) {
m_MapControl.Map.SelectFeature(m_SelectedLayer, feature); }
m_MapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, null); } catch { return; } }
相信大家对第一个函数并不陌生吧?对的,就是用的空间查询,把点击中的要素放进容器,再用第二个函数进行高亮显示。这个地方注意,如果数据量比较多,强烈推荐用PartialRefresh 而不要用Refresh,参数的含义请参考帮助。
这个只是开始编辑后,可以用鼠标点击选中要素,使其处于高亮状态,然而,ArcMap里面双击要素怎么出现节点用以编辑呢?这个是要自己绘制到MapControl上面去的:
///
/// 在要素上面绘制一个可拖拽的符号 ///
///
public void DrawEditSymbol(IGeometry geometry, IDisplay display) {
IEngineEditProperties engineProperty = new EngineEditorClass();
ISymbol pointSymbol = engineProperty.SketchVertexSymbol as ISymbol; ISymbol sketchSymbol = engineProperty.SketchSymbol as ISymbol;
ITopologicalOperator pTopo = geometry as ITopologicalOperator;
sketchSymbol.SetupDC(display.hDC, display.DisplayTransformation); sketchSymbol.Draw(pTopo.Boundary);
IPointCollection pointCol = geometry as IPointCollection; for (int i = 0; i < pointCol.PointCount; i++) {
IPoint point = pointCol.get_Point(i);
pointSymbol.SetupDC(display.hDC, display.DisplayTransformation); pointSymbol.Draw(point);
pointSymbol.ResetDC(); }
ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(sketchSymbol); ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(pointSymbol); ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(engineProperty); }
注意,这个函数是在MapControl的AfterDraw里面调用的,IDisplay参数,是AfterDraw事件的参数,我这里就没有画出来,类似ArcMap里面还有一个红色的节点,这里全是绿色的,因为红色对我的用处不大,也就没有必要了,当然各位看官可以自行修改,还有就是绘制符号的时候一定要记得释放内存哦~
现在,编辑状态做好了,但是现在只是雏形,因为它还没有响应任何鼠标事件,当鼠标悬停在绿色的节点上时并不会让你可以拖拽,所以我们还要做点工作。
那现在就开始如果鼠标悬停在绿色节点上时的代码吧:
public void SnapVertex(int x,int y,IGeometry snapContainer,ref bool vertexSnaped,ref bool contained) {
IPoint point = m_MapControl.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
IPoint pHitPoint = null; double hitDist = -1, tol = -1;
int vertexIndex = -1, partIndex = -1; bool vertex = false;
tol = ConvertPixelsToMapUnits(4);
IHitTest pHitTest = snapContainer as IHitTest;
bool bHit=pHitTest.HitTest(point, tol, esriGeometryHitPartType.esriGeometryPartVertex, pHitPoint, ref hitDist, ref partIndex, ref vertexIndex, ref vertex); vertexSnaped = false; contained = false; if (bHit) {
m_MapControl.MousePointer = esriControlsMousePointer.esriPointerCrosshair; vertexSnaped = true; return; } else {
IRelationalOperator pRelOperator=null; ITopologicalOperator pTopo = null; IGeometry buffer = null; IPolygon polygon = null;
if (m_SelectedLayer == null) return;
IFeatureLayer featLayer = m_SelectedLayer as IFeatureLayer; IDataset dataset = featLayer.FeatureClass as IDataset;
IWorkspaceEdit workspaceEdit = dataset.Workspace as IWorkspaceEdit; bool bHasUndos = false;
workspaceEdit.HasUndos(ref bHasUndos); if(bHasUndos) {
workspaceEdit.UndoEditOperation(); }
ClearSelection(); }
public void RedoEdit() {
if (m_SelectedLayer == null) return;
IFeatureLayer featLayer = m_SelectedLayer as IFeatureLayer; IDataset dataset = featLayer.FeatureClass as IDataset;
IWorkspaceEdit workspaceEdit = dataset.Workspace as IWorkspaceEdit; bool bHasUndos = false;
workspaceEdit.HasRedos(ref bHasUndos); if (bHasUndos) {
workspaceEdit.RedoEditOperation(); }
ClearSelection(); }
呵呵 这个也是很简单,对吧?这里需要给出几个上述函数中用到的辅助函数,这里就不一一阐明了,请各位看官自行分析:
private double ConvertPixelsToMapUnits(double pixelUnits) {
int pixelExtent = m_MapControl.ActiveView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().right- m_MapControl.ActiveView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().left;
double realWorldDisplayExtent = m_MapControl.ActiveView.ScreenDisplay.DisplayTransformation.VisibleBounds.Width;
double sizeOfOnePixel = realWorldDisplayExtent / pixelExtent;
return pixelUnits * sizeOfOnePixel; }
private bool TestGeometryHit(double tol,IPoint pPoint,IGeometry geometry,ref IPoint pHitPoint,
ref double hitDist, ref int partIndex, ref int vertexOffset,
ref int vertexIndex, ref bool vertexHit) {
IHitTest pHitTest = geometry as IHitTest; pHitPoint = new PointClass(); bool last = true; bool res = false;
if (pHitTest.HitTest(pPoint, tol, esriGeometryHitPartType.esriGeometryPartVertex, pHitPoint, ref hitDist, ref partIndex, ref vertexIndex, ref last)) {
vertexHit = true; res = true; } else {
if (pHitTest.HitTest(pPoint, tol, esriGeometryHitPartType.esriGeometryPartBoundary, pHitPoint, ref hitDist, ref partIndex, ref vertexIndex, ref last)) {
vertexHit = false; res = true; } }
if(partIndex>0) {
IGeometryCollection pGeoColl = geometry as IGeometryCollection; vertexOffset = 0;
for (int i = 0; i < partIndex;i=2*i+1) {
IPointCollection pointColl = pGeoColl.get_Geometry(i) as IPointCollection; vertexOffset = vertexOffset + pointColl.PointCount; } }
return res; }
///
/// 清除要素选择状态,恢复常态 ///
public void ClearSelection() {
m_MapControl.Map.ClearSelection();
m_MapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, m_SelectedLayer, null); }
各位看官,由于要素的移动、要素的创建和要素编辑在代码逻辑上差不多,所以我就不做过多阐述了,都是在处理鼠标的事件,需要做判断。其实,可能有看官已经了解,在AE的帮助里面就有类似的代码,是的,我参考了这部分代码,并对ESRI的开发和工作人员表示感谢。
最后,谢谢AE开发群一叶知秋老大哥的帮助,总是在繁忙之中耐心的指导,再次表示感谢。 希望大家能够有所启发,谢谢大家的支持!
示例源码下载地址 http://download.csdn.net/source/947550
正在阅读:
沪科版七年级数学上《第二章整式加减》单元测试(有答案)06-17
机器人技术概论开卷考试10-18
旋挖桩工程施工安全技术交底 - 图文06-21
2015-2016学年度广州版小学五年级下册英语期末试题(含听力材料04-14
浅析县疾控中心生存发展面临的主要困难05-25
浅谈地质勘探中岩矿芯的采取06-10
治水从小事做起作文800字06-30
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 拖动
- 要素
- 实现
- 工具
- ArcMap
- Editor
- 沥青路面改造方案设计
- 六年级语文上册第七单元小英雄的故事达标检测卷(A卷)长春版
- 中学生学科素养培养研究 结题报告
- 滇重楼标准化种植 - 图文
- 2014《MATLAB及应用》实验报告4
- 分数乘法(二)练习题及答案
- 新浙教版七年级上册科学第三单元知识点总结提纲
- 人教版五年级上册应用题100道A
- 路堤与横向结构物过渡段工艺性试验施工方案--杨停版本2
- 第十四章 整式的乘除与因式分解单元检测(附答案)精华版
- 武昌区2017—2018学年度上学期期中考试八年级数学试卷(含答案)
- 2016年执业医师操作第二站临床实践技能相关问题
- 2气象统方法 复习思考题
- 平原地质条件
- 六年级语文考试题
- (精品推荐)新九年级物理上册 12.3研究物质的比热容(第2课时 热量计算及比热容的应用)练习(新版)粤教
- Tensile behavior of PVC-coated woven membrane materials under uni- and bi-axial loads
- 2018-2019年江苏省高邮市三垛镇中心小学一年级上册数学模拟月考无答案
- iPhone6广告词:比逼格更有逼格
- 正面管教查理