1、距离测量

距离测量时,片段长度通过两点之间距离计算得到,全部长度通过片段长度的和计算得到。主要用到INewLineFeedback和IScreenDisplay两个接口。

1)INewLineFeedback接口

该接口的主要方法如表:

方法 描述
Start 从指定点开始绘制追踪线的绘制
MoveTo 鼠标移动到的点,并实时绘制与上一节点的连接线
AddPoint 添加一个点
Stop 停止追踪线的绘制,并返回用户绘制的几何体

2)IScreenDisplay接口

MapControl中的每一个视图都有一个ScreenDisplay对象,用于控制视图中的图形绘制。ScreenDisplay对象除了管理窗体屏幕的显示属性外,也管理缓存和视图屏幕的变化等。可以通过IActiveView接口的ScreenDisplay属性获取ScreenDisplay对象。通ScreenDisplay对象的DisplayTransformation属性进行设备单位和地图单位的转换。

3)实现的思路

    • 鼠标点击时,首先判断INewLineFeedback接口的实例化对象pNewLineFeedback是否为空,如果为空就实例化,并设当前的鼠标点为pNewLineFeedback的起始点。反之,则把当前鼠标点添加到pNewLineFeedback中。
    • 鼠标移动时。实时计算鼠标移动点与上一鼠标点击点的距离,以及所画线的长度。
    • 鼠标双击时,停止绘制,并清空pNewLineFeedback对象
    • btnMeasureLine的单击事件打结果窗体,并设置bMeasurelength为true,以便从数据视图的鼠标事件中判断量算功能是否开启。

2、面积量测

面积量测通过INewPolygonFeedback接口绘制多边形来实现。使用NewPolygonFeedback和使用NewLineFeedback的方法类似,但其显示和返回的几何特征是一个封闭多边形,这意味着画多边形停止时,起点将成为终点,从而结束形状的绘制,该方法至少需要三个点被添加到几何对象中。

实现的思路如下

1)、点击鼠标时首先判断INewPolygonFeedback接口的实例化对象pNewPolygonFeedback是否为空,则实例化,并设当前鼠标点为pNewPolygonFeedback的起始点;反之则把当前的鼠标点添加到pNewPolygonFeedback中。

2)、鼠标移动时,判断绘制多边形时点的个数pPointCol是否超过3个点,如果超过三个,则由点击构建IPolygon接口,IArea接口,进而计算出面的总长度和面积。

3)、鼠标双击时,停止绘制,并清空pNewPloygonFeedback对象。


3、面积测量和距离测量的具体代码分布:

1.前提:新建一个用来显示测量结果的公共窗体
2.二者的button_click事件:
  #region 距离的测量按钮单击事件
private void barButtonItem10_ItemClick(object sender, ItemClickEventArgs e)
{
mainMapControl.CurrentTool = null;
pMouseOperate = "MeasureLength";
mainMapControl.MousePointer = esriControlsMousePointer.esriPointerCrosshair;
if (frmMeasureResult == null || frmMeasureResult.IsDisposed)
{
frmMeasureResult = new FormMeasureResult();
frmMeasureResult.frmClosed += new FormMeasureResult.FormClosedEventHandler(frmMeasureResult_frmColsed);
frmMeasureResult.labToltal.Text = "";
frmMeasureResult.Text = "距离量测";
frmMeasureResult.Show();
}
else
{
frmMeasureResult.Activate();
}
}
#endregion
  #region 面积测量按钮单击事件
private void btnPolyMeasure_ItemClick(object sender, ItemClickEventArgs e)
{
mainMapControl.CurrentTool = null;
pMouseOperate = "MeasureArea";
mainMapControl.MousePointer = esriControlsMousePointer.esriPointerCrosshair;//光标样式为十字丝
if (frmMeasureResult == null || frmMeasureResult.IsDisposed)
{
frmMeasureResult = new FormMeasureResult();
frmMeasureResult.frmClosed += new FormMeasureResult.FormClosedEventHandler(frmMeasureResult_frmColsed); ;
frmMeasureResult.labToltal.Text = "";
frmMeasureResult.Text = "面积测量";
frmMeasureResult.Show();
}
else
{
frmMeasureResult.Activate();
}
}
#endregion
3.在mainForm中定义全局变量
  #region 变量的定义
//变量的定义
//距离和面积量测的变量
private FormMeasureResult frmMeasureResult = null;//量算的结果窗体
private INewLineFeedback pNewLineFeedback;//追踪线对象
private INewPolygonFeedback pNewPolyFeedback;//追踪面对象
private IPoint pPoint = null;//鼠标点击点
private IPoint pMovePt = null;//鼠标移动时的当前点
private double dToltalLength = ;//量测总长度
private double dSegmentLength = ;//片段距离
private IPointCollection pArearPointCol = new MultipointClass();//对面积量算时画的点进行存储
//定义状态栏坐标显示工具
private string sMapUnits = "未知单位";//地图单位变量
private object missing = Type.Missing;
#endregion
4.在mianMapControl控件的OnMouse_Down事件中进行switch语句注册
 #region   距离量测
case "MeasureLength":
//判断追踪线对象是否为空,若是则实例化并设置当前鼠标点为起始点
if (pNewLineFeedback == null)
{
//实例化追踪线对象
pNewLineFeedback = new NewLineFeedbackClass();
pNewLineFeedback.Display = (mainMapControl.Map as IActiveView).ScreenDisplay;
//设置起点,开始动态线绘制
pNewLineFeedback.Start(pPoint);
dToltalLength = ;
}
else //如果追踪线对象不为空,则添加当前鼠标点
{
pNewLineFeedback.AddPoint(pPoint);
}
//pGeometry = m_PointPt;
if (dSegmentLength != )
{
dToltalLength = dToltalLength + dSegmentLength;
}
break;
#endregion
#region 面积测量
case "MeasureArea":
if (pNewPolyFeedback == null)
{
//实例化追踪面对象
pNewPolyFeedback = new NewPolygonFeedback();
pNewPolyFeedback.Display = (mainMapControl.Map as IActiveView).ScreenDisplay;
pArearPointCol.RemovePoints(, pArearPointCol.PointCount);
//开始绘制多边形
pNewPolyFeedback.Start(pPoint);
pArearPointCol.AddPoint(pPoint, ref missing, ref missing);
}
else
{
pNewPolyFeedback.AddPoint(pPoint);
pArearPointCol.AddPoint(pPoint,ref missing,ref missing ); }
break;
#endregion
5.在mapControl的OnMouseMove事件中进行设置鼠标移动的实时测量结果
  #region 长度量算 实时显示测量结果
if (pMouseOperate == "MeasureLength")
{
if (pNewLineFeedback != null)
{
pNewLineFeedback.MoveTo(pMovePt);
}
double deltaX = ; //两点之间X差值
double deltaY = ; //两点之间Y差值 if ((pPoint != null) && (pNewLineFeedback != null))
{
deltaX = pMovePt.X - pPoint.X;
deltaY = pMovePt.Y - pPoint.Y;
dSegmentLength = Math.Round(Math.Sqrt((deltaX * deltaX) + (deltaY * deltaY)), );
dToltalLength = dToltalLength + dSegmentLength;
if (frmMeasureResult != null)
{
frmMeasureResult.labToltal .Text = String.Format("当前线段长度{0}{1}",dSegmentLength,sMapUnits );
frmMeasureResult.labToltalLength.Text = String.Format("总长度:{0}{1}",dToltalLength,sMapUnits );
//// frmMeasureResult.labToltal.Text = String.Format(
// "当前线段长度:{0:.###}{1};\r\n总长度为: {2:.###}{1}",
// dSegmentLength, sMapUnits, dToltalLength);
dToltalLength = dToltalLength - dSegmentLength; //鼠标移动到新点重新开始计算
}
frmMeasureResult.frmClosed += new FormMeasureResult.FormClosedEventHandler(frmMeasureResult_frmColsed);
}
}
#endregion
#region 面积量算
if(pMouseOperate=="MeasureArea")
{
if(pNewPolyFeedback!=null)
{
pNewPolyFeedback .MoveTo(pMovePt);
}
IPointCollection pPointCol=new Polygon();
IPolygon pPolygon=new PolygonClass();
IGeometry pGeo=null;
ITopologicalOperator pTopo=null;
for(int i=;i<=pArearPointCol.PointCount-;i++)
{
pPointCol.AddPoint(pArearPointCol.get_Point(i),ref missing,ref missing);
}
pPointCol.AddPoint(pMovePt,ref missing,ref missing);
if(pPointCol.PointCount<) return;
pPolygon=pPointCol as IPolygon;
if((pPolygon!=null))
{
pPolygon.Close();
pGeo=pPolygon as IGeometry;
pTopo=pGeo as ITopologicalOperator ;
//使几何图形的拓扑正确
pTopo.Simplify();
pGeo.Project(mainMapControl.Map.SpatialReference);
IArea pArea=pGeo as IArea ;//面积量算所画的面
frmMeasureResult.labToltal.Text=String.Format("总面积为:{0}平方{1}",pArea.Area,sMapUnits);
frmMeasureResult.labToltalLength.Text=String.Format("总长度为:{0}{1}",pPolygon.Length,sMapUnits);
pPolygon=null;
}
}
#endregion
6.mainMapControl的OnDoubleclick事件中
  #region 距离量测的结束设置
if (pMouseOperate == "MeasureLength")
{
if (frmMeasureResult != null)
{
frmMeasureResult .labToltalLength .Text = "线段总长度为:" + dToltalLength + sMapUnits;
}
if (pNewLineFeedback != null)
{
pNewLineFeedback.Stop();
pNewLineFeedback = null;
//清空所画的线对象
(mainMapControl.Map as IActiveView).PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null);
}
dToltalLength = ;
dSegmentLength = ;
}
#endregion
#region 面积测量的结束设置
if (pMouseOperate == "MeasureArea")
{
if (pNewPolyFeedback != null)
{
pNewPolyFeedback.Stop();
pNewPolyFeedback = null;
//清空所画的线对象
(mainMapControl.Map as IActiveView).PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null);
}
pArearPointCol.RemovePoints(, pArearPointCol.PointCount);//清空点集中的所有点
}
#endregion

综上述:一个完美的距离和面积测量的工具就完成了!欢迎同行们相互交流和学习。

ArcGIS Engine开发之量测功能的更多相关文章

  1. ArcGIS Engine开发鹰眼图的功能(代码优化篇)

    在上一篇,ArcGIS Engine开发鹰眼图的功能(基础篇) 上一篇的实现效果图如下, 如果仔细观察,会发现一个问题,即在“鹰眼”的区域,只要在红色线框内的注记会被覆盖. 如果红色框包括整张图的话, ...

  2. ArcGIS Engine开发鹰眼图的功能(基础篇)

    鹰眼是用于调节全视域范围内主地图显示范围情况的副地图.它体现了地图整体与详细局部的关系. 用户可以通过鼠标单击或者画框等动作实现鹰眼与主地图的交互情况. 鹰眼功能的原理是通过主地图窗口的地图控件和鹰眼 ...

  3. ArcGIS Engine开发的ArcGIS 版本管理的功能

    原文:ArcGIS Engine开发的ArcGIS 版本管理的功能 转自:http://blog.csdn.net/linghe301/article/details/7965901 这是以前的Arc ...

  4. ArcGIS Engine开发之地图基本操作(4)

    ArcGIS Engine开发中数据库的加载 1.加载个人地理数据库数据 个人地理数据库(Personal Geodatabase)使用Miscrosoft Access文件(*.mdb)进行空间数据 ...

  5. ArcGIS Engine开发前基础知识(3)

    对象模型图 一.对象模型图中的类与接口 ArcGIS Engine 提供大量的对象,这些对象之间存在各种各样的关系,如继承.组合.关联等.对象模型图(Object model diagram,ODM) ...

  6. ArcGIS Engine开发前基础知识(2)

    ArcGIS基本控件简介 ArcGIS Engine控件是一组可视化的开发组件,每个ArcGIS Engine控件都是一个COM组件.这些组件包括MapControl,PageLayoutContro ...

  7. C#,ArcGIS Engine开发入门教程

    C#,ArcGIS Engine开发入门教程 转自:http://blog.csdn.net/yanleigis/article/details/2233674  目录(?)[+] 五实现 一 加载A ...

  8. ArcGIS Engine开发基础总结(一)

    标准Engine功能 地图浏览    地图制作 数据查询 数据分析 及 所有的开发控件 —MapControl, PageLayout, Toolbar, TOC, ArcReader 对所有矢量和栅 ...

  9. VC、OpenGL、ArcGIS Engine开发的二维三维结合的GIS系统

    一.前言 众所周知,二维GIS技术发展了近四十年,伴随着计算机软硬件以及关系型数据库的飞速发展,二维GIS技术已日臻完善.在对地理信息的分析功能上有着无可比拟的优势.一些宏观的地理信息,一维的地理信息 ...

随机推荐

  1. MVVM大比拼之AngularJS源码精析

    MVVM大比拼之AngularJS源码精析 简介 AngularJS的学习资源已经非常非常多了,AngularJS基础请直接看官网文档.这里推荐几个深度学习的资料: AngularJS学习笔记 作者: ...

  2. JqueryQrcode生成二维码不支持中文的解决办法

    JqueryQrcode.js有一个小小的缺点,就是默认不支持中文. 这跟js的机制有关系,jquery-qrcode这个库是采用 charCodeAt() 这个方式进行编码转换的, 而这个方法默认会 ...

  3. 你还可以再诡异点吗——SQL日志文件不断增长

    前言 今天算是遇到了一个罕见的案例. SQL日志文件不断增长的各种实例不用多说,园子里有很多牛人有过介绍,如果我再阐述这些陈谷子芝麻,想必已会被无数次吐槽. 但这次我碰到的问题确实比较诡异,其解决方式 ...

  4. C# OracleDBhelper

    引用 using System.Configuration;using System.Data.OracleClient; 连接字符串 <connectionStrings> <ad ...

  5. 巧用javascript对象属性,向事件绑定的匿名函数内传递循环控制变量的值

    遇到一个需要向匿名函数传递循环控制变量的问题,我受到园子里这篇文章的启发[笔记]js获取当前点击元素的索引,解决了这个问题.现在把代码贴出来,以防止自己忘记. if ($('#labModal').l ...

  6. SQL Server中TOP子句可能导致的问题以及解决办法

    简介      在SQL Server中,针对复杂查询使用TOP子句可能会出现对性能的影响,这种影响可能是好的影响,也可能是坏的影响,针对不同的情况有不同的可能性.      关系数据库中SQL语句只 ...

  7. 使用AWS亚马逊云搭建Gmail转发服务(二)

    title: 使用AWS亚马逊云搭建Gmail转发服务(二) author:青南 date: 2014-12-31 14:44:27 categories: [Python] tags: [Pytho ...

  8. 关于android中调用系统拍照,返回图片是旋转90度

    转载博客:http://blog.csdn.net/walker02/article/details/8211628 项目开发中遇到的一个问题,对于三星手机在做手机照片选择时出现图片显示不正常,研究后 ...

  9. ASP.NET MVC5+EF6+EasyUI 后台管理系统(45)-工作流设计-设计步骤

    系列目录 步骤设计很重要,特别是规则的选择. 我这里分为几个规则 1.按自行选择(在起草时候自行选审批人,比较灵活) 2.按上级(无需指定,当时需要知道用户的上司是谁,可以在职位管理设置,或者在用户表 ...

  10. 【CSS进阶】试试酷炫的 3D 视角

    写这篇文章的缘由是因为看到了这个页面: 戳我看看(移动端页面,使用模拟器观看) 运用 CSS3 完成的 3D 视角,虽然有一些晕3D,但是使人置身于其中的交互体验感觉非常棒,运用在移动端制作一些 H5 ...