ArcGIS Editor工具,实现要素拖动、编辑

您所在的位置:网站首页 arcgis编辑工具在哪 ArcGIS Editor工具,实现要素拖动、编辑

ArcGIS Editor工具,实现要素拖动、编辑

2023-03-21 22:45| 来源: 网络整理| 查看: 265

ArcGIS Editor工具,实现要素拖动、编辑

本来根本没有写这个工具的意思,自己一直用的Ae自带的工 具。虽然可控制力弱了一些,但终究还是凑或能用。首先,说一下,所有的要素的更新、插入、删除最好放在编辑的Session 里面,即以一对StartEditing和StopEditing包裹。     一开始我的疑问在于,为什么我用IWorkspaceEdit的StartEditing方法后,怎么鼠标不会变成AcrMap里面Editor的开始编 辑那样呢,为什么不能选中要素,为什么不能双击后编辑要素?原来,选中要素和使要素处于编辑状态还是要自己写的(经高人指点,呵呵)。     先介绍一下程序中用到的变量: 复制内容到剪贴板 代码: private AxMapControl m_MapControl;//从外部传进来的MapControl控件 private ILayer m_SelectedLayer;//当前正在编辑的图层 private bool m_IsEdited = false;//当前是否处于编辑状态 private bool m_IsInUse = false;//这个其实我这里没有用到,这个实在创建新要素时用到的 private List m_SelectedFeature;//这个存储鼠标点击下,击中的要素 private IPoint m_CurrentMousePosition;//这个好像也没用到,记录当前鼠标的位置 private IDisplayFeedback m_FeedBack;//这个就是当前屏幕(鼠标动作)的反馈信息 那我们就按照逻辑顺序来一一展示这个到底是怎么做的。首先是,开始和结束编辑的代码: 复制内容到剪贴板 代码:

/// /// 开始编辑 /// /// public void StartEditing(bool bWithUndoRedo) { 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; } } /// /// 根据鼠标点击位置使击中要素处于高亮显示状态 /// /// /// public void SelectOnMouseDown() {    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;          switch (snapContainer.GeometryType)          {                case esriGeometryType.esriGeometryPolyline:                      pTopo = snapContainer as ITopologicalOperator;                      buffer=pTopo.Buffer(3);                      polygon = buffer as IPolygon;                      pRelOperator=polygon as IRelationalOperator;                      break;                case esriGeometryType.esriGeometryPolygon:                      polygon = snapContainer as IPolygon;                      pRelOperator=polygon as IRelationalOperator;                      break;                case esriGeometryType.esriGeometryPoint:                      pTopo = snapContainer as ITopologicalOperator;                      buffer = pTopo.Buffer(3);                      polygon = buffer as IPolygon;                      pRelOperator = polygon as IRelationalOperator;                      break;                default:                      break;          }          if (pRelOperator == null) return;          if (pRelOperator.Contains(point))          {                m_MapControl.MousePointer = esriControlsMousePointer.esriPointerSizeAll;                contained = true;          }          else m_MapControl.MousePointer = esriControlsMousePointer.esriPointerArrow;          return;    } }

这里就是根据鼠标悬停的位置,来改变鼠标样式,抱歉的很,我没有从AE里面找到和ArcMap一 样的鼠标样式,只要用一些简单的替代了,当然你可以自己定义,也可以打电话、发Email质问ESRI客服,如果你知道了,一定要告诉我,否则我诅咒你找 不到女朋友!这个函数里面,我需要判断,鼠标是悬停在要素的节点上,还是悬停在要素内部了,这个对于后面处理是拽节点还是移动要素有很大的帮助。

这个根据鼠标悬停位置改变鼠标样式,还远远不够滴,当你悬停到绿色节点上时,按下鼠标时,就意味这拖 拽开始,当鼠标左键按下并移动时,要出现像橡皮筋一样的连接线,当左键弹起时,就意味着拖拽结束,如果再按下左键,就意味着要素的编辑结束。这个怎么做到 呢,请看下面的代码: public bool EditFeature(int x,int y,IGeometry geometry) {     GetFeatureOnMouseDown(x, y);     SelectOnMouseDown();     if(m_SelectedFeature.Count0)    {          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的开发和工作人员表示感谢。      希望大家能够有所启发,谢谢大家的支持!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3