AE+C# 缓冲区的实现(GeoProcessor的用法)

7 篇文章 0 订阅
4 篇文章 0 订阅

最近在做一个地理信息系统,需要实现缓冲区分析的功能。在网上、参考书上参考别人的代码。发现了一个大bug,一直解决不了,遂奋战至凌晨三点半。终于解决啦~

先搭建窗体:
在这里插入图片描述
选择图层 :comboBox1
缓冲距离 :textBox1
输出路径 :textBox2
确认:button1
取消:button2

(一)变量以及构造函数的的定义

        //变量的定义
        private IActiveView pActiveView;
        private AxMapControl mapControl;

        public Buffer()
        {
            InitializeComponent();
        }

        //构建含参构造函数,将主窗体的AxMapControl传进来
        public Buffer(AxMapControl mainMapControl):this()
        {
            mapControl = mainMapControl;
            pActiveView = mainMapControl.ActiveView;
        }
        
        //窗体加载
        private void Buffer_Load(object sender, EventArgs e)
        {
            if (mapControl == null || pActiveView.FocusMap.LayerCount == 0)
            {
                return;
            }
            
            IEnumLayer layers = pActiveView.FocusMap.get_Layers();
            layers.Reset();
            ILayer layer = layers.Next();
            
            while (layer != null)
            {
                comboBox1.Items.Add(layer.Name);
                layer = layers.Next();
            }
        }
        
        //设置输出路径
        private void textBox2_MouseDown(object sender, MouseEventArgs e)
        {
            //set the output layer
            SaveFileDialog saveDlg = new SaveFileDialog();
            saveDlg.CheckPathExists = true;
            saveDlg.Filter = "Shapefile (*.shp)|*.shp";
            saveDlg.OverwritePrompt = true;
            saveDlg.Title = "Output Layer";
            saveDlg.RestoreDirectory = true;
            saveDlg.FileName = (string)comboBox1.SelectedItem + "_buffer.shp";

            DialogResult dr = saveDlg.ShowDialog();
            if (dr == DialogResult.OK)
                textBox2.Text = saveDlg.FileName;
        }
        
        //取消
        private void button2_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        
        //获取图层源路径
        public static string getLayerPath(ILayer pLayer)
        {
            IDatasetName pDatasetName = (pLayer as IDataLayer2).DataSourceName as IDatasetName;
            IWorkspaceName pWorkspaceName = pDatasetName.WorkspaceName;
            return pWorkspaceName.PathName + "\\" + pLayer.Name + ".shp";
        }
        
        //确认
        private void button1_Click(object sender, EventArgs e)
        {

            double bufferDistance = Convert.ToDouble(textBox1.Text.Trim());

            if (bufferDistance == 0.0)
            {
                MessageBox.Show("缓冲区距离有误!");
                return;
            }

            if (comboBox1.Text == string.Empty)
            {
                MessageBox.Show("输入图层不能为空!");
                return;
            }

            if (textBox2.Text == string.Empty)
            {
                MessageBox.Show("输出路径不能为空!");
                return;
            }
            int index = comboBox1.SelectedIndex;
            string name = getLayerPath(pActiveView.FocusMap.get_Layer(index));
            string outPath = textBox2.Text;

            //Geoprocessor对象的定义
            ESRI.ArcGIS.Geoprocessor.Geoprocessor pGp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor();
            //以下两种情况下会报错。
            //GeoProcessor pGp = new GeoProcessor();
            //IGeoProcessor2 pGp = new GeoProcessorClass();
            pGp.OverwriteOutput = true; //允许运算结果覆盖现有文件,可无
            ESRI.ArcGIS.AnalysisTools.Buffer pBuffer = new ESRI.ArcGIS.AnalysisTools.Buffer();

            //获取缓冲区分析图层
            ILayer pLayer = pActiveView.FocusMap.get_Layer(index);
            IFeatureLayer featLayer = pLayer as IFeatureLayer;
            //IFeatureCursor cursor = featLayer.Search(null, false);
            //IFeature feaClass = cursor.NextFeature();

            pBuffer.in_features = featLayer;
            pBuffer.out_feature_class = outPath; //输出路径
            pBuffer.buffer_distance_or_field = bufferDistance; //缓冲区参数
            pBuffer.dissolve_option = "NONE"; //融合缓冲区重叠交叉部分,如果不融合填"ALL"
            pGp.Execute(pBuffer, null); //执行

            string pFolder = System.IO.Path.GetDirectoryName(outPath); //得到字符串中文件夹位置
            string pFileName = System.IO.Path.GetFileName(outPath); //得到字符串中文件名字
            mapControl.AddShapeFile(pFolder, pFileName); //往地图控件里添加文件
            mapControl.ActiveView.Refresh(); //激活窗口刷新
            this.Close();
        }

对于我上面提到的bug,就是在我在执行GeoProcessor.Excute()方法时,一直弹出以下错误:
在这里插入图片描述
昨天遇到这个问题,当时差点崩溃,因为查了一天资料,别人的用法都是这样。差点想重装VS。突然灵机一动,去对象浏览器里看了一下:

解决方法:
定义Geoprocessor对象时,要用:

ESRI.ArcGIS.Geoprocessor.Geoprocessor pGp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor();

而不能直接用:

GeoProcessor pGp = new GeoProcessor();

补充:
在写这篇博客时,我又想到:是不是我加的引用不对?我昨天其实已经加了GeoProcessor的引用,后来发现没用到,就注释掉了,但是我发现:将GeoProcessor改成小写p的Geoprocessor,就不用那么麻烦了。

using ESRI.ArcGIS.Geoprocessor;
Geoprocessor GP = new Geoprocessor();

emmmm…一定要细心!

2021/4/12 更新:评论很多人要主窗体代码,更新一下。
ps.这个项目太久远了,当时很多技术和意识都不太成熟,用了很多公共变量,暂时没时间完善了,(先活过毕设),大家凑活看吧。

//主窗体界面的公共变量
        IExtractionOp extractOp = null;//提取分析对象
        IGeoDataset maskRaster = null;//掩膜数据集
        IGeoDataset inGeodataset = null;//输入数据集
        IGeoDataset outGeodataset = null;//输出数据集
        IFeatureLayer pTocFeatureLayer;//当前所选矢量图层
        IEngineEditor pEngineEditor = new EngineEditorClass();//启动或停止编辑
        IEngineEditTask pEngineEditTask = null;
        IEngineEditLayers pEngineEditLayers = null;
        IActiveView pActiveView = null;
        IRasterLayer pOutRasLayer;//输出栅格
        IRasterLayer pRasterLayer;//所选栅格
        IRaster raster;
        Color Color;
        ILayer pLayer = null;//被选中的图层
        private frmMapTips frmMapTips = null;//MapTips
        string filepath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;//获取应用程序的目录
        private ISelectionEnvironment selectionEnvironment;//定义接口对象来设置选择环境
        private IMap pMap = null;
        private string sMxdPath = Application.StartupPath;
        int flag = 0;//标志是否点击了“添加图名”
        int ind;//当前所选图层的序号

接下来是主窗体界面的无参构造函数

        public MainForm()
        {
            InitializeComponent();
            InitObject();
            //窗体初始化时新建接口对象,对象具有默认的选项设置值
            selectionEnvironment = new SelectionEnvironmentClass();
        }
        
        private void InitObject()
        {
            try
            {
                //ChangeButtonState(false);

                pEngineEditor = new EngineEditorClass();//实例化IEngineEditor接口类型的对象,表示启动或者停止编辑
                OperateMap.EngineEditor = pEngineEditor;//将该对象的值传到MapManager类中的同接口类型的变量
                pEngineEditTask = pEngineEditor as IEngineEditTask;//接口转换,将IEngineEditor接口转换为IEngineEditTask接口,设置编辑任务
                pEngineEditLayers = pEngineEditor as IEngineEditLayers;//接口转换,将IEngineEditor接口转换为IEngineEditLayers接口,设置编辑图层
                sMxdPath = OperateMap.getPath(sMxdPath) + "\\data\\edit.mxd"; ;//获取Mxd文件的路径
                if (mainMapControl.CheckMxFile(sMxdPath))
                {
                    mainMapControl.LoadMxFile(sMxdPath);
                }
                pMap = mainMapControl.Map;
                pActiveView = mainMapControl.Map as IActiveView;//刷新视图
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

调用时的代码:

        private void 缓冲区分析ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Buffer bf = new Buffer(mainMapControl);
            bf.Show();
        }

=====================2023/12/29更新=
这个项目太久远啦,而且我现在由于硕士转专业了,电脑也没有ArcGIS环境了。评论很多细节我回答不上来,把代码和运行视频放上来帮助大家学习。数据因为我们老师说不能外传,所以抱歉啦!

链接:https://pan.baidu.com/s/1xefFX4ruj5mI819illszhQ
提取码:dxe1

评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值