ArcGIS Engine10.0轻松入门级教程(4)——基本功能开发

1地图编辑功能

  地图编辑功能涉及到比较复杂的地图与鼠标的交互以及事件的响应,ArcGIS提供了强大的地图编辑的相关功能。本节我们将尝试实现一些简单的地图编辑功能,包括点、线、面要素形状的创建和移动。通过本节希望你能掌握ArcEngine实现地图编辑的机制以及常用的地图编辑的接口。

    新建一个C#.Net项目,项目名称为MapEdit,添加MapControlLicenceControl、四个Button、一个ComboBox、一个Label等控件。如下图:

     ArcEngine中的地图编辑使用IWorkspaceEdit接口来进行编辑状态的管理,在需要对指定的工作空间进行编辑时,首先使用IWorkspaceEdit获取该工作空间的数据,然后使用StartEditing方法开始编辑状态,StartEditOperation方法打开具体编辑的操作,编辑完成后,使用StopEditOperation方法关闭编辑操作,使用StopEditing方法关闭编辑状态,完成编辑。

    在本例中,我们实现了新的点线面要素的创建和移动的功能,涉及到了比较复杂的鼠标与地图间的交互,这个功能的实现中,IDisplayFeedback是一个十分关键的接口,它具有涉及创建要素,移动要素、编辑节点等31个实现类,能够实现鼠标与地图交互中的事件的追踪,返回新的几何对象。

   创建项目后注意把ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.EngineOrDesktop);这句代码加入到Program.cs文件中。   

   using ESRI.ArcGIS.Carto;
   using ESRI.ArcGIS.Controls;

   using ESRI.ArcGIS.Geometry;
   using ESRI.ArcGIS.Geodatabase;
   using ESRI.ArcGIS.Display;
   定义如下成员变量。

        //操作类型
        string strOperator = "";
        //当前地图视图
        IActiveView m_activeView = null;
        //当前操作图层
        IFeatureLayer m_FeatureLayer = null;
        //当前操作实体
        IFeature m_Feature = null;
        //当前点移动反馈对象
        IMovePointFeedback m_MovePointFeedback = new MovePointFeedbackClass();
        //当前线移动反馈对象
        IMoveLineFeedback m_MoveLineFeedback = new MoveLineFeedbackClass();
        //当前面移动反馈对象
        IMovePolygonFeedback m_MovePolygonFeedback = new MovePolygonFeedbackClass();

     加载地图文档的函数代码:

      private void button1_Click(object sender, EventArgs e)
        {
            //加载地图文档
            loadMapDocument();
            //将图层名填加到下拉列表框
            for (int i = 0; i < this.axMapControl1.LayerCount; i++)
            {
                ILayer layer = this.axMapControl1.get_Layer(i);
                this.comboBox1.Items.Add(layer.Name);
            }           
        }

        //加载地图文档
        private void loadMapDocument()
        {
            System.Windows.Forms.OpenFileDialog openFileDialog;
            openFileDialog = new OpenFileDialog();
            openFileDialog.Title = "打开地图文档";
            openFileDialog.Filter = "map documents(*.mxd)|*.mxd";
            openFileDialog.ShowDialog();
            string filePath = openFileDialog.FileName;
            if (axMapControl1.CheckMxFile(filePath))
            {
                axMapControl1.MousePointer = esriControlsMousePointer.esriPointerHourglass;
                axMapControl1.LoadMxFile(filePath, 0, Type.Missing);
                axMapControl1.MousePointer = esriControlsMousePointer.esriPointerDefault;
            }
            else
            {
                MessageBox.Show(filePath + "不是有效的地图文档");
            }
        }

     combobox1添加selectedchange事件。

    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.comboBox1.Text != "")
            {
                for (int i = 0; i < this.axMapControl1.LayerCount; i++)
                {
                    ILayer layer = this.axMapControl1.get_Layer(i);
                    if (layer.Name == this.comboBox1.Text.ToString())
                    {
                        m_FeatureLayer = layer as IFeatureLayer;
                        m_Feature = m_FeatureLayer.FeatureClass.GetFeature(0);

                        if (m_Feature != null)
                        {
                            this.axMapControl1.Map.ClearSelection();
                            this.axMapControl1.Map.SelectFeature(m_FeatureLayer, m_Feature);
                            this.axMapControl1.Refresh();
                        }
                        m_activeView = this.axMapControl1.ActiveView;
                        return;
                    }
                }
            }
        }

           移动要素按钮添加事件:

        private void button2_Click(object sender, EventArgs e)
        {
            strOperator = "move";
            m_MovePointFeedback = new MovePointFeedbackClass();
            m_MoveLineFeedback = new MoveLineFeedbackClass();
            m_MovePolygonFeedback = new MovePolygonFeedbackClass();
        }

    下面添加鼠标与地图的交互事件,包括移动要素时鼠标的PanMouseDown事件、MouseMove事件和MouseUp事件。代码如下:

创建要素时首先在MouseDown事件中获取鼠标点击的点位,若图层为点图层,则直接创建要素,若为线图层或面图层,则作为第一个节点,以后每次点击都会添加一个节点,直到双击鼠标完成要素的创建。创建要素时的MouseDown事件在这里定义为CreateMouseDown。代码如下:

     private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
        {
            IPoint point = new PointClass();
            IFeatureClass featureClass = null;
            if (m_Feature == null) return;
            switch (strOperator)
            {
                case "move":
                    //将当前鼠标位置的点转换为地图上的坐标
                    point = m_activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);
                    if (m_Feature.Shape.GeometryType == esriGeometryType.esriGeometryPoint)
                    {
                        //设置显示对象,并启动移动
                        m_MovePointFeedback.Display = m_activeView.ScreenDisplay;
                        m_MovePointFeedback.Start(m_Feature.Shape as IPoint, point);
                    }
                    else if (m_Feature.Shape.GeometryType == esriGeometryType.esriGeometryPolyline)
                    {
                        //设置显示对象,并启动移动
                        m_MoveLineFeedback.Display = m_activeView.ScreenDisplay;
                        m_MoveLineFeedback.Start(m_Feature.Shape as IPolyline, point);
                    }
                    else if (m_Feature.Shape.GeometryType == esriGeometryType.esriGeometryPolygon)
                    {
                        //设置显示对象,并启动移动
                        m_MovePolygonFeedback.Display = m_activeView.ScreenDisplay;
                        m_MovePolygonFeedback.Start(m_Feature.Shape as IPolygon, point);
                    }
                    break;
            }
        }

        private void axMapControl1_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent e)
        {
            IPoint point = new PointClass();
            switch (strOperator)
            {
                case "move":
                    if (m_Feature.Shape.GeometryType == esriGeometryType.esriGeometryPoint)
                    {
                        if (m_MovePointFeedback != null)
                        {
                            //将当前鼠标位置的点转换为地图上的坐标
                            point = m_activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);
                            //移动对象到当前鼠标位置
                            m_MovePointFeedback.MoveTo(point);
                        }
                    }
                    else if (m_Feature.Shape.GeometryType == esriGeometryType.esriGeometryPolyline)
                    {
                        if (m_MoveLineFeedback != null)
                        {
                            //将当前鼠标位置的点转换为地图上的坐标
                            point = m_activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);
                            //移动对象到当前鼠标位置
                            m_MoveLineFeedback.MoveTo(point);
                        }
                    }
                    else if (m_Feature.Shape.GeometryType == esriGeometryType.esriGeometryPolygon)
                    {
                        if (m_MovePolygonFeedback != null)
                        {
                            //将当前鼠标位置的点转换为地图上的坐标
                            point = m_activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);
                            //移动对象到当前鼠标位置
                            m_MovePolygonFeedback.MoveTo(point);
                        }
                    }
                    break;
            }
        }

        private void axMapControl1_OnMouseUp(object sender, IMapControlEvents2_OnMouseUpEvent e)
        {
            if (m_Feature == null) return;
            IGeometry resultGeometry = null;
            switch (strOperator)
            {
                case "move":
                    if (m_Feature.Shape.GeometryType == esriGeometryType.esriGeometryPoint)
                    {
                        //停止移动
                        resultGeometry = m_MovePointFeedback.Stop() as IGeometry;
                        m_Feature.Shape = resultGeometry;
                    }
                    else if (m_Feature.Shape.GeometryType == esriGeometryType.esriGeometryPolyline)
                    {
                        //停止移动
                        resultGeometry = m_MoveLineFeedback.Stop() as IGeometry;
                        m_Feature.Shape = resultGeometry;
                    }
                    else if (m_Feature.Shape.GeometryType == esriGeometryType.esriGeometryPolygon)
                    {
                        //停止移动
                        resultGeometry = m_MovePolygonFeedback.Stop() as IGeometry;
                        m_Feature.Shape = resultGeometry;
                    }
                    IWorkspaceEdit workspaceEdit;
                    IWorkspace workspace;
                    IDataset dataset = m_FeatureLayer.FeatureClass as IDataset;
                    workspace = dataset.Workspace;
                    workspaceEdit = workspace as IWorkspaceEdit;
                    //开始编辑
                    workspaceEdit.StartEditing(true);
                    workspaceEdit.StartEditOperation();
                    //保存实体
                    m_Feature.Store();
                    //结束编辑
                    workspaceEdit.StopEditOperation();
                    workspaceEdit.StopEditing(true);
                    m_MovePointFeedback = null;
                    m_MoveLineFeedback = null;
                    m_MovePolygonFeedback = null;
                    break;
            }
            m_activeView.Refresh();
            this.axMapControl1.Map.ClearSelection();
        }

     删除节点按钮事件的代码如下:

     private void button3_Click(object sender, EventArgs e)
        {
            IPointCollection pointCollection;
            if (m_Feature.Shape.GeometryType == esriGeometryType.esriGeometryPolyline)
            {
                pointCollection = new PolylineClass();
                IPolyline polyline = m_Feature.Shape as IPolyline;

                pointCollection = polyline as IPointCollection;
                //如果点个数少于两个无法构成线
                if (pointCollection.PointCount > 2)
                {
                    //移除指定的节点
                    pointCollection.RemovePoints(pointCollection.PointCount - 1, 1);
                }
            }
            else if (m_Feature.Shape.GeometryType == esriGeometryType.esriGeometryPolygon)
            {
                pointCollection = new PolygonClass();
                IPolygon polygon = m_Feature.Shape as IPolygon;
                pointCollection = polygon as IPointCollection;
                //如果点个数少于三个无法构成面
                if (pointCollection.PointCount > 3)
                {
                    //移除指定的节点
                    pointCollection.RemovePoints(pointCollection.PointCount - 1, 1);
                }
            }
            IWorkspaceEdit workspaceEdit;
            IWorkspace workspace;
            IDataset dataset = m_FeatureLayer.FeatureClass as IDataset;
            workspace = dataset.Workspace;
            workspaceEdit = workspace as IWorkspaceEdit;
            //开始编辑
            workspaceEdit.StartEditing(true);
            workspaceEdit.StartEditOperation();
            //保存数据
            m_Feature.Store();
            //结束编辑
            workspaceEdit.StopEditOperation();
            workspaceEdit.StopEditing(true);
            m_activeView.Refresh();
        }

     双击“增加节点”添加如下代码:

        private void button4_Click(object sender, EventArgs e)
        {
            IPointCollection pointCollection;
            IPoint point = new PointClass();
            IPoint fromPoint = new PointClass();
            IPoint toPoint = new PointClass();
            if (m_Feature.Shape.GeometryType == esriGeometryType.esriGeometryPolyline)
            {
                pointCollection = new PolylineClass();
                IPolyline polyline = m_Feature.Shape as IPolyline;

                object missing1 = Type.Missing;
                object missing2 = Type.Missing;
                pointCollection = polyline as IPointCollection;
                //获取线对象的最后两个点
                fromPoint = pointCollection.get_Point(pointCollection.PointCount - 2);
                toPoint = pointCollection.get_Point(pointCollection.PointCount - 1);
                //根据线最后两个点,创建一个新点
                point.PutCoords((fromPoint.X + toPoint.X) / 2, (fromPoint.Y + toPoint.Y) / 2 + 50);
                //将新点添加到线对象的点集合中
                pointCollection.AddPoint(point, ref missing1, ref missing2);

            }
            else if (m_Feature.Shape.GeometryType == esriGeometryType.esriGeometryPolygon)
            {
                pointCollection = new PolygonClass();
                IPolygon polygon = m_Feature.Shape as IPolygon;

                object missing1 = Type.Missing;
                object missing2 = Type.Missing;
                pointCollection = polygon as IPointCollection;
                //获取面对象点集最后两个点
                fromPoint = pointCollection.get_Point(pointCollection.PointCount - 2);
                toPoint = pointCollection.get_Point(pointCollection.PointCount - 1);
                //根据线最后两个点,创建一个新点
                point.PutCoords((fromPoint.X + toPoint.X) / 2, (fromPoint.Y + toPoint.Y) / 2 + 50);
                //将新点添加到线对象的点集合中
                pointCollection.AddPoint(point, ref missing1, ref missing2);
            }
            IWorkspaceEdit workspaceEdit;
            IWorkspace workspace;
            IDataset dataset = m_FeatureLayer.FeatureClass as IDataset;
            workspace = dataset.Workspace;
            workspaceEdit = workspace as IWorkspaceEdit;
            //开始编辑
            workspaceEdit.StartEditing(true);
            workspaceEdit.StartEditOperation();
            //保存数据
            m_Feature.Store();
            //结束编辑
            workspaceEdit.StopEditOperation();
            workspaceEdit.StopEditing(true);
            m_activeView.Refresh();
        }

     至此,我们完成了代码的编写,效果如图所示。

    地图编辑的GIS中比较复杂和困难的环节,涉及到的对象和接口非常多,上面实例只是实现了最基础的编辑的活动,如果读者对二次开发感兴趣,可以自己试着阅读GIS二次开发相关书籍,了解与编辑相关的接口和方法,自己实现。

2地理变换

      以下演示了如何改变一个图层的空间参考。运行效果如下图:

    先新建一个MapControl Application模板,添加菜单按钮,事件代码为:

     private void 空间参考ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Transform attributeQueryForm = new Transform(this.axMapControl1);
            attributeQueryForm.Show();
        }

     然后见一个窗体,命名为Transform,控件布局见上图。添加变量:

        //地图数据
        private AxMapControl mMapControl;
        //选中图层
        private IFeatureLayer mFeatureLayer;

        构造函数修改为:

       public Transform(AxMapControl mapControl)
        {
            InitializeComponent();
            this.mMapControl = mapControl;
        }

       Load事件为:

     

private void Transform_Load(object sender, EventArgs e)
        {
            //MapControl中没有图层时返回
            if (this.mMapControl.LayerCount <= 0)
                return;

            //获取MapControl中的全部图层名称,并加入ComboBox
            //图层
            ILayer pLayer;
            //图层名称
            string strLayerName;
            for (int i = 0; i < this.mMapControl.LayerCount; i++)
            {
                pLayer = this.mMapControl.get_Layer(i);
                strLayerName = pLayer.Name;
                //图层名称加入cboLayer
                this.comboBox1.Items.Add(strLayerName);
            }
            //默认显示第一个选项
            this.comboBox1.SelectedIndex = 0;
        }

      comboBox1_SelectedIndexChanged事件为:

      private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            //获取cboLayer中选中的图层
            mFeatureLayer = mMapControl.get_Layer(comboBox1.SelectedIndex) as IFeatureLayer;
        }

         添加改变图层的空间参考的函数:

        /// <summary>
        /// 改变图层的空间参考
        /// </summary>
        /// <param name="pFeatureLayer">图层</param>
        /// <param name="pGeoType">空间参考类型</param>
        private void ChangeLayerRef(IFeatureLayer pFeatureLayer, int gcsType)
        {
            try
            {
                IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass;
                //QI到IGeoDataset
                IGeoDataset pGeoDataset = pFeatureClass as IGeoDataset;
                //QI到IGeoDatasetSchemaEdit
                IGeoDatasetSchemaEdit pGeoDatasetSchemaEdit = pGeoDataset as IGeoDatasetSchemaEdit;
                if (pGeoDatasetSchemaEdit.CanAlterSpatialReference == true)
                {
                    //创建SpatialReferenceEnvironmentClass对象
                    ISpatialReferenceFactory2 pSpaRefFactory = new SpatialReferenceEnvironmentClass();
                    //创建地理坐标系对象
                    IGeographicCoordinateSystem pNewGeoSys = pSpaRefFactory.CreateGeographicCoordinateSystem(gcsType);//4214代表Beijing1954
                    pGeoDatasetSchemaEdit.AlterSpatialReference(pNewGeoSys);
                }
            }
            catch (Exception Err)
            {
                MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        在转换坐标按钮下添加事件:

        private void button1_Click(object sender, EventArgs e)
        {
            ChangeLayerRef(mFeatureLayer, 4214);
            MessageBox.Show("转换成功!");
        }

        运行就能成功了! 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
arcgis开发教程,ao开发教程,arcobjects开发教程,arcgis objects开发教程,arcgis桌面开发教程,AE开发教程Arcgis Engine开发教程 1.3. GeoDataBase 34 1.3.1. 如何加载Shape文件 34 1.3.2. 如何在ArcMap中加入Text和dBASE文件 35 1.3.3. 如何连接GeoDataBase文件 37 1.3.4. 如何连接Coverage文件 39 1.3.5. 如何连接栅格文件 41 1.3.6. 如何创建Shape文件 42 1.3.7. 如何创建DBF文件 45 1.3.8. 如何创建GeoDataBase文件 47 1.3.9. 如何创建Coverage文件 48 1.3.10. 如何建立文件连接(Join / Link) 50 1.3.11. 如何浏览纪录(属性查询) 52 1.3.12. 如何编辑记录 53 1.3.13. 如何增加记录 54 1.3.14. 如何删除记录 56 1.3.15. 如何纪录排序(ITableSort) 58 1.3.16. 如何添加字段 59 1.3.17. 如何删除字段 61 1.3.18. 如何进行空间查询 62 1.3.19. 如何进行高级空间查询(两个层之间的空间查询) 64 1.3.20. 如何进行层与层之间的逻辑运算 65 1.3.21. 如何将shape文件转化成GeoDataBase(各种文件格式的转换) 67 1.3.22. 如何将Map中显示的图形转化成栅格文件 70 1.3.23. 如何打开选中的层或独立表的属性窗口 71 1.3.24. 如何拷贝属性表中的一行 73 1.3.25. 如何为当前层或独立表创建一个Summary表 75 1.3.26. 如何利用用户定义的规则创建定制的排序 78 1.3.27. 如何实现ArcMap上进行属性查询(Identify) 84 1.3.28. 如何设置和修改层的数据源 87 1.4. Display 88 1.4.1. 如何实现ArcMap中放大缩小地图 88 1.4.2. 如何实现ArcMap中移动地图 90 1.4.3. 如何实现ArcMap上画Polygon 92 1.4.4. 如何实现ArcMap上进行测量 94 1.4.5. 如何实现ArcMap上选取中记录 100 1.4.6. 如何实现ArcMap中进行动作的撤销和重做 101 1.4.7. 如何画Polygon Buffers 102 1.5. 图元编辑 104 1.5.1. 如何得到图形的基本属性 104 1.5.2. 如何将选中的点集转换成Polygon 105 1.5.3. 如何将Multipoint转换成Points 109 1.5.4. 如何通过Polygon中的多个Ring创建多个Polygon 111 1.5.5. 如何从Polyline创建Polygon 113 1.5.6. 如何从Polygon创建Polyline 115 1.5.7. 如何将Polygon/PolyCurve一般化(Generalize) 117 1.5.8. 如何获得Polygon的中点 119 1.5.9. 如何判断图形间的逻辑运算 121 1.5.10. 如何进行图形间的逻辑运算 124 1.5.11. 如何创建Envelope的Boundary 127 1.5.12. 如何通过鼠标移动图形 130 1.5.13. 如何为一个图形添加一个顶点 133 1.5.14. 如何删除一个图形上的一个顶点 136 1.5.15. 如何移动一个图形上的一个顶点 138 1.6. Element 141 1.6.1. 如何创建MarkerElement 141 1.6.2. 如何创建TextElement 142 1.6.3. 如何创建Balloon Callout 144 1.6.4. 如何创建PolygonElement 145 1.6.5. 如何选中一个Element 146 1.6.6. 如何移动Element 147 1.6.7. 如何排列Element 151 1.6.8. 如何通过名字查询Element 153 1.6.9. 如何拷贝Element 155 1.6.10. 如何沿着折线路径显示Text 158 1.7. Symbol和Renderer 159 1.7.1. 如何为一个层设置Simple Renderer 159 1.7.2. 如何为一个层设置UniqueValue Renderer 161 1.7.3. 如何为一个层设置ClassBreaks Renderer 165 1.7.4. 如何为一个层设置ProportionalSymbol Renderer 168 1.7.5. 如何为一个层设置Chart Renderer 170 1.7.6. 如何为一个层设置DotDensity Renderer 173 1.8. Layout和打印 175 1.8.1. 如何在Page Layout上添加Text 175 1.8.2. 如何在Page Layout上添加Legend 176 1.8.3. 如何在Page Layout上添加North Arrow 179 1.8.4. 如何在Page Layout上添加Scale bar 180 1.8.5. 如何在Page Layout上添加Scale Text 182 1.8.6. 如何在Page Layout上添加Picture 184 1.8.7. 如何创建、删除地图网格(Map Grid) 185 1.8.8. 如何设置Layout中MapFrame的外观风格属性 187 1.8.9. 何设置Layout中Page的边框(Border)和背景(Background) 189 1.8.10. 如何设置打印纸张的大小和方向 192 1.9. 坐标系统 193 1.9.1. 如何在ArcMap中设置地理坐标系和投影坐标系 193 1.9.2. 如何修改层的坐标系统 194 1.9.3. 如何把Polygon的顶点从经纬度坐标转换到平面直角坐标 196 1.10. ArcGis相关文件 198 1.10.1. 如何夹载grf文件 198 1.10.2. 如何新建指向Shape文件的lyr文件 199 1.10.3. 如何新建指向GeoDataBase文件的lyr文件 200 1.10.4. 如何加载mxd文件 202 1.10.5. 如何加载Apr文件(ArcView32) 203 1.10.6. 如何加载lyr文件 204 1.10.7. lyr文件的属性的设置 205 1.11. 其他 208 1.11.1. 如何创建简单的Column Chart 208 1.11.2. 如何将数据输出到Excel 209 1.11.3. 如何把Labels转换为Annotation 211 1.11.4. 如何把Annotation转换为Polygon Features 215 1.11.5. 如何设置Featurelayer的Label 218 1.11.6. 如何设置图层显示的透明度 220 1.11.7. 如何过滤层中要显示的Features 220 1.11.8. 如何在MapControl中新建一个Document并且保存 221
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暮紫月升

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值