liutingxiang的个人博客分享 http://blog.sciencenet.cn/u/liutingxiang

博文

ArcGIS Engine二次开发学习(12)缓冲区分析

已有 8980 次阅读 2018-5-28 15:43 |个人分类:地理信息系统二次开发|系统分类:教学心得

 本功能采用自定义菜单的方法,继承basecommand,具体步骤见教材。


0:新建项目GpBufferLayer,自定义生成一个菜单,命名为BufferSelectedLayerCmd.cs。在自定义菜单的代码中,修改onclick()事件的代码。

public override void OnClick()
    {
      if (null == m_hookHelper)
        return;

      if (m_hookHelper.FocusMap.LayerCount > 0)
      {
        BufferDlg bufferDlg = new BufferDlg(m_hookHelper);
        bufferDlg.Show();
      }
    }


其中,BufferDlg是需要新建的一个窗体BufferDlg.cs,也就是缓冲区分析的界面。




1、新建 form 窗体。

添加 2 个 groupbox 控件,3 个 textbox 控件,2 个 combobox 控件,3 个button 控件,3 个 label 控件。

控件名称以及 text 属性需要修改,在下面的表里面。


Combobox 控件 cboUnits 的 Item 属性添加的内容为(可以自定义修改,此处为单位)

Unknown

Inches

Points

Feet

Yards

Miles

NauticalMiles

Millimeters

Centimeters

Decimeters

Meters

Kilometers

DecimalDegrees




2、窗体的代码如下:

(1)添加命名空间的引用

using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geoprocessor;
using ESRI.ArcGIS.Geoprocessing;
using ESRI.ArcGIS.AnalysisTools;


(2)添加定义的变量

[DllImport("user32.dll")]
private static extern int PostMessage(IntPtr wnd,
                                                uint Msg,
                                                IntPtr wParam,
                                                IntPtr lParam);
private IMapControl4 MapControl;
private IHookHelper m_hookHelper = null;
private const uint WM_VSCROLL = 0x0115;
private const uint SB_BOTTOM = 7;


(3)为窗口的入口函数添加参数,使缓冲区分析能够获得主窗口的参数(从主窗口传递变量进来,用的是hookHelper)。

public 缓冲区分析(IHookHelper hookHelper)
{
    InitializeComponent();
    m_hookHelper = hookHelper;
    MapControl = m_hookHelper as IMapControl4;
}


(4)窗体的load事件中添加代码,使窗体得到当前地图中的图层列表,从而可以选择一个图层进行缓冲区分析。

private void 缓冲区分析_Load(object sender, EventArgs e)
{
    if (null == m_hookHelper || null == m_hookHelper.Hook || 0 == m_hookHelper.FocusMap.LayerCount)
        return;
    //加载地图中所有要素到combo
    IEnumLayer layers = GetLayers();
    layers.Reset();
    ILayer layer = null;
    while ((layer = layers.Next()) != null)
    {
        cboLayers.Items.Add(layer.Name);
    }
    //默认选择第一个图层
    if (cboLayers.Items.Count > 0)
        cboLayers.SelectedIndex = 0;
    string tempDir = System.IO.Path.GetTempPath(); 
    txtOutputPath.Text = System.IO.Path.Combine(tempDir, ((string)cboLayers.SelectedItem + "_buffer.shp")); 
    //设置默认的缓冲单位 
    int units = Convert.ToInt32(m_hookHelper.FocusMap.MapUnits); 
    cboUnits.SelectedIndex = units;
}


(5)在存放位置的按钮中弹出保存文件的窗口:

private void btnOutputLayer_Click(object sender, EventArgs e)
{
    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)cboLayers.SelectedItem + "_buffer.shp";

    DialogResult dr = saveDlg.ShowDialog();
    if (dr == DialogResult.OK)
        txtOutputPath.Text = saveDlg.FileName;
}

(6)添加缓冲区分析这个按钮的代码,也是这个功能的核心代码:

private void btnBuffer_Click(object sender, EventArgs e)
{
    double bufferDistance;
    //将输入距离的字符型转换为double类型
    double.TryParse(txtBufferDistance.Text, out bufferDistance);
    if (0.0 == bufferDistance)
    {
        MessageBox.Show("缓冲距离有错误!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        return;
    }
    //判断输出路径是否合法
    if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(txtOutputPath.Text)) ||
      ".shp" != System.IO.Path.GetExtension(txtOutputPath.Text))
    {
        MessageBox.Show("输出路径有问题!","提示",MessageBoxButtons.OK, MessageBoxIcon.Warning);

        return;
    }
    //判断图层个数
    if (m_hookHelper.FocusMap.LayerCount == 0)
        return;

    //从地图中获取图层
    IFeatureLayer layer = GetFeatureLayer((string)cboLayers.SelectedItem);
    if (null == layer)
    {
        txtMessages.Text += "Layer " + (string)cboLayers.SelectedItem + "找不到!\r\n";
        return;
    }

    //文本框拖到底部
    ScrollToBottom();
    //消息框中添加消息
    txtMessages.Text += "缓冲图层: " + layer.Name + "\r\n";

    txtMessages.Text += "\r\n正在获取地学处理器,请稍等...\r\n";
    txtMessages.Text += DateTime.Now.ToString() + "\r\n";
    txtMessages.Update();
    //获得地学处理器的一个实例
    Geoprocessor gp = new Geoprocessor();
    gp.OverwriteOutput = true;
    txtMessages.Text += "开始进行缓冲区分析...\r\n";
    txtMessages.Update();

    //创建缓冲区工具的一个实例
    ESRI.ArcGIS.AnalysisTools.Buffer buffer = new ESRI.ArcGIS.AnalysisTools.Buffer(layer, txtOutputPath.Text, Convert.ToString(bufferDistance) + " " + (string)cboUnits.SelectedItem);

    //执行缓冲区分析
    IGeoProcessorResult results = (IGeoProcessorResult)gp.Execute(buffer, null);
    if (results.Status != esriJobStatus.esriJobSucceeded)
    {
        txtMessages.Text += "图层缓冲失败: " + layer.Name + "\r\n";
    }
    txtMessages.Text += ReturnMessages(gp);
    //scroll the textbox to the bottom
    ScrollToBottom();

    txtMessages.Text += "\r\n完成.\r\n";
    txtMessages.Text += "-----------------------------------------------------------------------------------------\r\n";
    //scroll the textbox to the bottom
    ScrollToBottom();
    
}


(7)添加(6)中需要调用的几个方法,添加取消按钮的代码:

private string ReturnMessages(Geoprocessor gp)
{
  StringBuilder sb = new StringBuilder();
  if (gp.MessageCount > 0)
  {
    for (int Count = 0; Count <= gp.MessageCount - 1; Count++)
    {
      System.Diagnostics.Trace.WriteLine(gp.GetMessage(Count));
      sb.AppendFormat("{0}\n", gp.GetMessage(Count));
    }
  }
  return sb.ToString();
}

private IFeatureLayer GetFeatureLayer(string layerName)
{
  //get the layers from the maps
  IEnumLayer layers = GetLayers();
  layers.Reset();
 
  ILayer layer = null;
  while ((layer = layers.Next()) != null)
  {
    if (layer.Name == layerName)
      return layer as IFeatureLayer;
  }

  return null;
}

private IEnumLayer GetLayers()
{
  UID uid = new UIDClass();
  uid.Value = "{40A9E885-5533-11d0-98BE-00805F7CED21}";
  IEnumLayer layers = m_hookHelper.FocusMap.get_Layers(uid, true);
  
  return layers;
}

private void ScrollToBottom()
{
  PostMessage((IntPtr)txtMessages.Handle, WM_VSCROLL, (IntPtr)SB_BOTTOM, (IntPtr)IntPtr.Zero);
}
private void btnCancel_Click(object sender, EventArgs e)
{
   this.Close();
}

3、调用缓冲区分析工具。


(1)生成,重新生成解决方案

(2)在debug中有一个dll。

(3)在需要使用这个工具的项目中添加引用,然后在命名空间的引用代码部分添加using GpBufferLayer;

别忘了还需要添加

using ESRI.ArcGIS.Geoprocessor;

using ESRI.ArcGIS.Geoprocessing;

(4)在toolbarcontrol中添加这个工具的调用方式:

axToolbarControl1.AddItem(new BufferSelectedLayerCmd(), -1, -1, false, 0, esriCommandStyles.esriCommandStyleIconAndText);


最终结果如图:




https://blog.sciencenet.cn/blog-3373120-1116133.html

上一篇:ArcGIS Engine二次开发学习(11)根据空间关系查询
下一篇:ArcGIS Engine二次开发学习(13)利用gp进行其他空间分析
收藏 IP: 124.234.141.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-4-27 03:11

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部