环境:Windows10专业版 + ArcGIS10.2 + ArcEngine10.2 + Visual Studio 2019
因每个人电脑版本和软件版本不同,运行的结果可能不同
系列文章:
目录
一、系统功能简介
1、鹰眼、空间书签、数据列表显示、创建 shapefile 文件与编辑要素;
2、文件(新建地图文档、打开地图文档、保存、另存为、添加数据(添加.shp、添加.lyr、添加栅格数据、退出));
3、栅格数据处理功能(获取栅格目录、创建栅格数据集、添加栅格数据、格式转换、影像镶嵌、栅格数据计算器(由用户定义计算表达式));
4、空间分析功能,包括据缓冲区分析、叠加分析、裁剪分析(要求采用对话框方式实现,通过对话框选择数据对象与相应的设置);
5、几何对象的绘制(点绘制、线绘制、面绘制)并保存到指定图层;
6、视图切换(页面视图、数据视图)且实现两者的数据联动;
7、制图(插入标题、插入指北针、插入比例尺、插入图例、文字编辑);
二、界面介绍
1.文件
(1)添加数据 ①添加.shp ②添加.lyr ③添加栅格数据 ④添加栅格数据集(2)新建地图文档(3)打开地图文档(4)保存(5)另存为(6)地图输出(7)打印(8)退出
2.创建书签
3.空间数据
(1)访问图层数据(2)格式转换
4.地图表现
(1)简单渲染图层(2)获取渲染器信息(3)显示地图(4)显示页面布局
5.数据操作
(1)创建shapefile(2)添加要素(3)创建要素①创建点②创建线③创建多边形
6.GIS分析
(1)空间分析(2)缓冲区分析(3)要素统计(4)叠加分析
7.栅格数据处理
(1)创建栅格数据集(2)格式转换(3)影像镶嵌(4)栅格数据计算器
8.地图制图
(1)插入标题(2)插入指北针(3)插入比例尺(4)插入图例
三、功能实现
3.1 鹰眼功能
3.1.1 实现思想
(1)在布局窗体控件时,需要两个MapcControl控件,一个作为主视图,一个作为鹰眼视图。
(2)在主视图和鹰眼视图两个控件中显示的数据许保持一致。
(3)在主视图中当前显示的地图范围,需要用一个红色矩形框在鹰眼视图中标绘出来。当主视图显示的地图范围发生变化时,红色矩形框的位置也要发生相应变化。
(4)当用户用鼠标在鹰眼视图中移动或改变红色矩形框的位置或大小时,主视图的地图范围也要发生相应变化。
3.1.2 实现的主体代码及注释
using System;
using System.Data;
using System.Windows.Forms;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.Output;
using Microsoft.VisualBasic;
private void axMapControl1_OnMapReplaced(object sender, IMapControlEvents2_OnMapReplacedEvent e)
{
IMap pMap;
pMap = axMapControl1.Map;
for (int i = 0; i < pMap.LayerCount; i++)
{
axMapControl2.Map.AddLayer(pMap.get_Layer(i));
}
//使鹰眼视图中显示加载地图的全图
axMapControl2.Extent = axMapControl2.FullExtent;
copyToPageLayout();
}
private void axMapControl2_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
{
if (e.button == 1)//探测鼠标左键
{
IPoint pPt = new PointClass();
pPt.X = e.mapX;
pPt.Y = e.mapY;
IEnvelope pEnvelope = axMapControl1.Extent as IEnvelope;
pEnvelope.CenterAt(pPt);
axMapControl1.Extent = pEnvelope;
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);
}
else if (e.button == 2)//鼠标右键按下
{
IEnvelope pEnvelope = axMapControl2.TrackRectangle();
axMapControl1.Extent = pEnvelope;
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);
}
}
private void axMapControl2_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent e)
{
if (e.button != 1)
{
return;
}
IPoint pPt = new PointClass();
pPt.X = e.mapX;
pPt.Y = e.mapY;
axMapControl1.CenterAt(pPt);
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
}
private void axMapControl1_OnExtentUpdated(object sender, IMapControlEvents2_OnExtentUpdatedEvent e)
{
//绘制鹰眼图中红色矩形框的代码
IGraphicsContainer pGraphicsContainer = axMapControl2.Map as IGraphicsContainer;
IActiveView pAv = pGraphicsContainer as IActiveView;
//在绘制前,清除axMapControl2中的任何图形元素
pGraphicsContainer.DeleteAllElements();
IRectangleElement pRecElement = new RectangleElementClass();
IElement pEle = pRecElement as IElement;
IEnvelope pEnv;
pEnv = e.newEnvelope as IEnvelope;
pEle.Geometry = pEnv;
//设置颜色
IRgbColor pColor = new RgbColorClass();
pColor.Red = 200;
pColor.Green = 0;
pColor.Blue = 0;
pColor.Transparency = 255;
//产生一个线符号对象
ILineSymbol pLineSymbol = new SimpleLineSymbolClass();
pLineSymbol.Width = 2;
pLineSymbol.Color = pColor;
//设置填充符号属性
IFillSymbol pFillSymbol = new SimpleFillSymbolClass();
//设置透明颜色
pColor.Transparency = 0;
pFillSymbol.Color = pColor;
pFillSymbol.Outline = pLineSymbol;
IFillShapeElement pFillShapeElement = pRecElement as IFillShapeElement;
pFillShapeElement.Symbol = pFillSymbol;
pGraphicsContainer.AddElement(pEle, 0);
axMapControl2.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
}
3.2 空间书签
3.2.1 实现思想
(1)在主窗体添加“创建书签”的控件和添加用来保存已创建的书签名的组合框控件,并添加相应引用(Geometry)。
(2)在主窗体类中添加“创建书签”的函数CreateBookmark(string sBookmarkName),在函数中,通过IAOBookmark接口创建一个变量,用于保存当前地图的范围;通过IMapBookmarks接口访问当前地图,并向地图中加入新建书签;最后将书签名加入组合框中。
(3)添加“书签名称设置”窗体,添加设置“书签名称”的“文本框”控件和“确定”按钮控件,在此窗体中创建一个用于保存主窗体的对象,并在“确定”按钮的“点击”事件响应函数中调用CreateBookmark函数创建书签。
(4)为主窗体“创建书签”按钮生成“点击”事件响应函数,用于运行"书签名称设置"功能。
3.2.2 实现的主体代码及注释
using System;
using System.Windows.Forms;
namespace GISAE
{
public partial class AdmitBookmarkName : Form
{
//用于保存主窗体对象
public MainForm m_frmMain;
//用于传入主窗体对象
public AdmitBookmarkName(MainForm frm)
{
InitializeComponent();
if (frm != null)
{
m_frmMain = frm;
}
}
//"确定"按钮的"点击"事件鼠标响应函数
private void btnAdmit_Click(object sender, EventArgs e)
{
if (m_frmMain != null || tbBookmarkName.Text == "")
{
m_frmMain.CreateBookmark(tbBookmarkName.Text);
}
this.Close();
}
}
}
//创建书签
public void CreateBookmark(string sBookmarkName)
{
//通过IAOBookmark接口创建一个变量,其类型为AOIBookmark,用于保存当前地图的范围
IAOIBookmark aoiBookmark = new AOIBookmarkClass();
if (aoiBookmark != null)
{
aoiBookmark.Location = axMapControl1.ActiveView.Extent;
aoiBookmark.Name = sBookmarkName;
}
//通过IMapBookmarks接口访问当前地图,并向地图中加入新建书签
IMapBookmarks bookmarks = axMapControl1.Map as IMapBookmarks;
if (bookmarks != null)
{
bookmarks.AddBookmark(aoiBookmark);
}
// 将新建书签名名加入组合框中,用于之后调用对应书签
cbBookmarkList.Items.Add(aoiBookmark.Name);
}
// "创建书签"按钮的"点击"事件响应函数,用于运行"书签名称设置"按钮
private void miCreateBookmark_Click(object sender, EventArgs e)
{
AdmitBookmarkName frmABN = new AdmitBookmarkName(this);
frmABN.Show();
}
3.3 数据列表显示
3.3.1 实现思想
(1)在主窗体添加“访问图层数据”的控件。
(2)添加“数据展示台”窗体,在此窗体添加用来显示表名的“文本框”控件和用来显示表格的“数据网格视图”。
(3)添加“数据操作”类,并添加相应引用(Carto,Geometry,Geodatabase,DataSourceFile),在此窗体中创建一个保存当前地图的对象。
(4)在“数据操作”类中添加“获取地图图层”功能,添加GetLayerByName(string sLayerName)函数得到指定的图层对象,添加GetDataTableByLayer()函数处理图层对象得到的DataTable对象。
(5)为“访问图层数据”控件生成“点击”事件响应函数,调用“数据操作”工具得到DataTable对象,然后调用“数据展示”工具传入DataTable对象,实现创建地理数据列表功能。
3.3.2 实现的主体代码及注释
// 通过指定的图层名获取对应图层对象
public ILayer GetLayerByName(String sLayerName)
{
//判断图层名或地图对象是否为空,若为空,函数返回空
if (sLayerName == "" || m_map == null)
{
return null;
}
//对地图对象中的所有图层进行遍历,若某一图层中的名称与指定图层名相同,则返回该图层
for (int i = 0; i < m_map.LayerCount; i++)
{
if (m_map.get_Layer(i).Name == sLayerName)
{
return m_map.get_Layer(i);
}
}
//若地图对象中的所有图层名均与指定图层名不匹配,函数返回空
return null;
}
public DataTable GetContinentsNames()
{
//获取"Continents"图层,利用IFeatureLayer接口访问,并判断是否成功,若失败,则函数返回空
ILayer layer = GetLayerByName("Continents");
IFeatureLayer featureLayer = layer as IFeatureLayer;
if (featureLayer == null)
{
return null;
}
//调用IFeatureLayer接口的Search方法,获取要素指针(IFeatureCursor)接口对象,
//用于在之后遍历图层中的全部要去,并判断是否成功获取第一个要素,若失败,函数返回空
IFeature feature;
IFeatureCursor featureCursor = featureLayer.Search(null, false);
feature = featureCursor.NextFeature();
if (feature == null)
{
return null;
}
//更新,展示所有字段的信息
public DataTable GetContinentsNames(string layerName)
{
// 获取指定名称的图层
ILayer layer = GetLayerByName(layerName);
if (layer == null)
{
return null;
}
// 判断是否为要素图层
IFeatureLayer featureLayer = layer as IFeatureLayer;
if (featureLayer == null)
{
return null;
}
// 获取图层属性表
ITable table = featureLayer as ITable;
if (table == null)
{
return null;
}
// 创建 DataTable
DataTable dataTable = new DataTable(layerName);
// 添加列
for (int i = 0; i < table.Fields.FieldCount; i++)
{
DataColumn dataColumn = new DataColumn();
IField field = table.Fields.get_Field(i);
dataColumn.ColumnName = field.Name;
dataColumn.DataType = Type.GetType("System.Object");
dataTable.Columns.Add(dataColumn);
}
// 添加数据行
ICursor cursor = table.Search(null, false);
IRow row = cursor.NextRow();
while (row != null)
{
DataRow dataRow = dataTable.NewRow();
for (int i = 0; i < table.Fields.FieldCount; i++)
{
IField field = table.Fields.get_Field(i);
dataRow[i] = row.get_Value(i);
}
dataTable.Rows.Add(dataRow);
row = cursor.NextRow();
}
//返回设置好的数据表
return dataTable;
}
//新建DataTable类型对象,用于函数返回
DataTable dataTable = new DataTable();
//新建DataColumn类型对象,分别保存各个洲的序号和名称
DataColumn dataColumn = new DataColumn();
dataColumn.ColumnName = "序号";
dataColumn.DataType = System.Type.GetType("System.Int32");
//设置完之后,加入DataTable的列集合(Columns)中
dataTable.Columns.Add(dataColumn);
dataColumn = new DataColumn();
dataColumn.ColumnName = "名称";
dataColumn.DataType = System.Type.GetType("System.String");
dataTable.Columns.Add(dataColumn);
//对图层中的要素进行遍历,每获取一个要素,就关联DataTable的下一个DataRow
//将要素在序号和名称字段上的值赋给DataRow的对应列中。在"Continents"图层
//属性表中,序号信息在第0个字段中,名称信息在第2个字段中,相关内容可以
//通过ArcMap对地图文档进行查看
DataRow dataRow;
while (feature != null)
{
dataRow = dataTable.NewRow();
dataRow[0] = feature.get_Value(0);
dataRow[1] = feature.get_Value(2);
dataTable.Rows.Add(dataRow);
feature = featureCursor.NextFeature();
}
//返回设置好的数据表
return dataTable;
}
//更新,展示所有字段的信息
public DataTable GetContinentsNames(string layerName)
{
// 获取指定名称的图层
ILayer layer = GetLayerByName(layerName);
if (layer == null)
{
return null;
}
// 判断是否为要素图层
IFeatureLayer featureLayer = layer as IFeatureLayer;
if (featureLayer == null)
{
return null;
}
// 获取图层属性表
ITable table = featureLayer as ITable;
if (table == null)
{
return null;
}
// 创建 DataTable
DataTable dataTable = new DataTable(layerName);
// 添加列
for (int i = 0; i < table.Fields.FieldCount; i++)
{
DataColumn dataColumn = new DataColumn();
IField field = table.Fields.get_Field(i);
dataColumn.ColumnName = field.Name;
dataColumn.DataType = Type.GetType("System.Object");
dataTable.Columns.Add(dataColumn);
}
// 添加数据行
ICursor cursor = table.Search(null, false);
IRow row = cursor.NextRow();
while (row != null)
{
DataRow dataRow = dataTable.NewRow();
for (int i = 0; i < table.Fields.FieldCount; i++)
{
IField field = table.Fields.get_Field(i);
dataRow[i] = row.get_Value(i);
}
dataTable.Rows.Add(dataRow);
row = cursor.NextRow();
}
//返回设置好的数据表
return dataTable;
}
private void miAccessData_Click(object sender, EventArgs e)
{
DataOperator dataOperator = new DataOperator(axMapControl1.Map);
DataTable dataTable = dataOperator.GetContinentsNames("Continents");
if (dataTable != null)
{
DataBoard dataBoard = new DataBoard("所有字段信息", dataTable);
//运行载有数据的"数据展示台"窗体对象
dataBoard.Show();
}
}
3.4 创建shapefile文件
3.4.1 实现思想
(1)在主窗体添加“创建Shapefile文件”的控件。
(2)添加“数据操作”类,并添加相应引用(Geodatabase,DataSourceFile),获取当前地图对象。
(3)在“数据操作”类中添加“创建shape文件”函数CreateShapfile(String sParentDirectory,String sWorkspaceName,String sFileName),通过指定的上级路径,包含shape文件的文件夹名,shape文件名,创建并编辑“序号”、“名称”和“形状”等字段,创建shape文件。
(4)为“创建Shapefile文件”控件添加“点击”事件响应函数,调用函数创建shape文件。
3.4.2 实现的主体代码及注释
public IFeatureClass CreateShapefile(String sParentDirectory, String sWorkspaceName, String sFileName)
{
//如果指定的路径和文件夹已经存在,则删除此文件夹。
if (System.IO.Directory.Exists(sParentDirectory + sWorkspaceName))
{
System.IO.Directory.Delete(sParentDirectory + sWorkspaceName, true);
}
//通过IWorkspaceFactory接口创建针对Shape文件的工作空间工场对象,并通过
//参数创建相关工作空间(文件夹),用于包含Shape文件。
IWorkspaceFactory workspaceFactory = new ShapefileWorkspaceFactoryClass();
IWorkspaceName workspaceName = workspaceFactory.Create(sParentDirectory, sWorkspaceName, null, 0);
ESRI.ArcGIS.esriSystem.IName name = workspaceName as ESRI.ArcGIS.esriSystem.IName;
//打开新建的工作空间,并通过IFeatureworkspace 接口来访问它。
IWorkspace workspace = (IWorkspace)name.Open();
IFeatureWorkspace featureWorkspace = workspace as IFeatureWorkspace;
// Shape文件在概念层次上是一个要素类。创建并编辑该要素类所需的字段集。
IFields fields = new FieldsClass();
IFieldsEdit fieldsEdit = fields as IFieldsEdit;
// 创建并编辑“序号”字段。此字段为要素类必需字段。
IFieldEdit fieldEdit = new FieldClass();
fieldEdit.Name_2 = "OID";
fieldEdit.AliasName_2 = "序号";
fieldEdit.Type_2 = esriFieldType.esriFieldTypeOID;
fieldsEdit.AddField((IField)fieldEdit);
// 创建并编辑“名称”字段。
fieldEdit = new FieldClass();
fieldEdit.Name_2 = "Name";
fieldEdit.AliasName_2 = "名称";
fieldEdit.Type_2 = esriFieldType.esriFieldTypeString;
fieldsEdit.AddField((IField)fieldEdit);
// 创建地理定义,设置其空间参考和几何类型,为创建“形状”字段做准备。
IGeometryDefEdit geoDefEdit = new GeometryDefClass();
ISpatialReference spatialReference = m_map.SpatialReference;
geoDefEdit.SpatialReference_2 = spatialReference;
geoDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPoint;
//创建并编辑“形状”字段。此字段为要素类必需字段。
fieldEdit = new FieldClass(); String sShapeFieldName = "Shape";
fieldEdit.Name_2 = sShapeFieldName; fieldEdit.AliasName_2 = "形状";
fieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
fieldEdit.GeometryDef_2 = geoDefEdit;
fieldsEdit.AddField((IField)fieldEdit);
//调用IFeatureWorkspace 接口的 CreateFeatureClass方法,创建要素类。并判
//断是否创建成功。
IFeatureClass featureClass = featureWorkspace.CreateFeatureClass(sFileName, fields, null, null, esriFeatureType.esriFTSimple, "Shape", "");
if (featureClass == null)
{
return null;
}
//将创建好的要素类作为结果返回
return featureClass;
}
// featureClass,将要被添加的要素类
// sLayerName,图层名称
public bool AddFeatureClassToMap(IFeatureClass featureClass, String sLayerName)
{
//判断要素类、图层名和地图对象是否为空。如为空,则函数返回false。
if (featureClass == null || sLayerName == "" || m_map == null)
{
return false;
}
// 通过IFeatureLayer 接口创建要素图层对象,将要素类以层的形式进行操作。
IFeatureLayer featureLayer = new FeatureLayerClass();
featureLayer.FeatureClass = featureClass;
featureLayer.Name = sLayerName;
//将要素图层转换为一般图层,并判断是否成功。若失败,函数返回
ILayer layer = featureLayer as ILayer;
if (layer == null)
{
return false;
}
// 将创建好的图层添加至地图对象。将地图对象转化为活动视图,并判断是否成
// 功。若失败,函数返回false。
m_map.AddLayer(layer);
IActiveView activeView = m_map as IActiveView;
if (activeView == null)
{
return false;
}
//活动视图进行刷新,新添加的图层将被展示在控件中。函数返回 true。
activeView.Refresh();
return true;
}
//创建shape文件
private void miCreateShapefile_Click(object sender, EventArgs e)
{
//创建 Shape文件,将其以要素类形式获取,并判断是否成功。若失败,消息框
//提示,函数返回空。
DataOperator dataOperator = new DataOperator(axMapControl1.Map);
IFeatureClass featureClass = dataOperator.CreateShapefile("C:\\Users\\Admin\\Desktop\\", " ShapefileWorkspace", "ShapefileSample");
if (featureClass == null)
{
MessageBox.Show("创建 Shape文件失败!");
return;
}
//将要素类添加到地图中,其图层名为“Observation Stations”(观测站),并记
//录其结果。若为true,将“创建Shapefile”按钮禁用,消息框提示,函数返回空。
bool bRes = dataOperator.AddFeatureClassToMap(featureClass, "Observation Stations");
if (bRes)
{
miCreateShapefile.Enabled = false;
return;
}
else
{
MessageBox.Show("将新建Shape文件加入地图失败!");
return;
}
}
3.5 新建地图文档
3.5.1 实现思想
(1)主窗口添加“新建地图文档”控件。
(2)新建类MxdOperator,用MapDocumentClass()创建地图文档,用Save()方法保存地图文档。
(3)为“新建地图文档”控件生成点击事件响应函数
3.5.2 实现的主体代码及注释
using System;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
//新建地图文档
public void NewMxd(ESRI.ArcGIS.Controls.AxMapControl basicControl)
{
try
{
if (basicControl.LayerCount != 0)
{
MessageBox.Show("是否保存当前操作?");
string sMxdFileName = basicControl.DocumentFilename;
IMapDocument pMapDocument = new MapDocumentClass();
if (sMxdFileName != null && basicControl.CheckMxFile(sMxdFileName))
{
if (pMapDocument.get_IsReadOnly(sMxdFileName))
{
MessageBox.Show("本地图文档是只读的,不能保存!");
pMapDocument.Close();
return;
}
}
else
{
SaveFileDialog pSavedlg = new SaveFileDialog();
pSavedlg.Title = "请选择保存路径";
pSavedlg.OverwritePrompt = true;
pSavedlg.Filter = "ArcMap文档(*.mxd)|*.mxd|ArcMap模板(*.mxt)|*.mxt";
pSavedlg.RestoreDirectory = true;
if (pSavedlg.ShowDialog() == DialogResult.OK)
{
sMxdFileName = pSavedlg.FileName;
}
else
{
return;
}
}
pMapDocument.New(sMxdFileName);
pMapDocument.ReplaceContents(basicControl.Map as IMxdContents);
pMapDocument.Save(pMapDocument.UsesRelativePaths, true);
pMapDocument.Close();
//MessageBox.Show("保存地图文档成功!");
MessageBox.Show("新建地图文档成功");
}
//basicControl.ClearLayers();
//basicControl.Update();
//basicControl.ActiveView.Refresh();
//MessageBox.Show("新建地图文档成功");
}
catch (Exception ex)
{
MessageBox.Show("新建地图文档失败" + ex.Message);
}
}
//新建地图文档
private void newMxd_Click(object sender, EventArgs e)
{
MxdOperator mxdOperator = new MxdOperator();
mxdOperator.NewMxd(axMapControl1);
}