传入AxmapControl参数即可实现实时面积测量
代码如下:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AxESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;
namespace PartOfJRSpace
{
public class MeasureArea
{
//地图面板
AxMapControl myMapControl;
//地图面板容器
IGraphicsContainer g;
//点集
IPointCollection pAreaPointCol = new MultipointClass();
//画线
NewLineFeedbackClass m_NewLineFeedback;
//线段起始点
IPoint starPoint;
//第一个点
IPoint firstPoint;
//面积显示标签
IElement measureAreaText;
//动态连接线
IElement firstPointToLast,lastLine;
//连接线标签
IElement firstPointToLastText;
//连接线标签
IElement moveText;
public MeasureArea(AxMapControl pMapControl)
{
myMapControl = pMapControl;
myMapControl.OnMouseDown += new IMapControlEvents2_OnMouseDownEventHandler(myMapControl_OnMouseDown);
myMapControl.OnDoubleClick += new IMapControlEvents2_OnDoubleClickEventHandler(myMapControl_OnDoubleClick);
myMapControl.OnMouseMove += new IMapControlEvents2_OnMouseMoveEventHandler(myMapControl_OnMouseMove);
g = myMapControl.Map as IGraphicsContainer;
}
private void myMapControl_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent e)
{
if (m_NewLineFeedback == null)
{
return;
}
IPoint pt = new PointClass();
pt.X = e.mapX;
pt.Y = e.mapY;
if (pAreaPointCol.PointCount==1)
{
m_NewLineFeedback.MoveTo(pt);
return;
}
ILine laLine = new LineClass();
laLine.PutCoords(starPoint, pt);
#region//动态连接线starTolast
try
{
object missing = Type.Missing;
ISegmentCollection segColl = new PolylineClass();
segColl.AddSegment(laLine as ISegment, ref missing, ref missing);
if (lastLine != null)
{
g.DeleteElement(lastLine);
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, lastLine, null);
}
lastLine = CreateElement(segColl as IPolyline);
g.AddElement(lastLine, 0);
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, lastLine, null);
}
catch
{
throw;
}
#endregion
//连接起点和终点
ILine firstToLastLine = new LineClass();
firstToLastLine.PutCoords(firstPoint, pt);
#region 动态连接线
try
{
object missing = Type.Missing;
ISegmentCollection segColl = new PolylineClass();
segColl.AddSegment(firstToLastLine as ISegment, ref missing, ref missing);
//删除上一个连接线
if (firstPointToLast != null)
{
g.DeleteElement(firstPointToLast);
//myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, firstPointToLast, null);
}
firstPointToLast = CreateElement(segColl as IPolyline);
g.AddElement(firstPointToLast, 0);
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, firstPointToLast, null);
}
catch
{
throw;
}
#endregion
#region 动态连接线长度
try
{
double angle = firstToLastLine.Angle;
if ((angle > (Math.PI / 2) && angle < (Math.PI)) || (angle > -Math.PI && angle < -(Math.PI / 2))) // 大于90度小于等于180
angle += Math.PI;
//标注点Y值偏移量
double d_OffsetY = myMapControl.ActiveView.ScreenDisplay.DisplayTransformation.FromPoints(9);
//标注点
double d_CenterX = (firstPoint.X + pt.X) / 2;
double d_CenterY = (firstPoint.Y + pt.Y) / 2 + d_OffsetY; //向上偏移
IPoint labelPt = new PointClass();
labelPt.PutCoords(d_CenterX, d_CenterY);
//删除上一个长度标签
if (firstPointToLastText != null)
{
g.DeleteElement(firstPointToLastText);
//刷新
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, firstPointToLastText, null);
}
ITextElement txtElement = CreateTextElement(firstToLastLine.Length.ToString("0.00") + GetMapLenUnit(myMapControl.Map.MapUnits));
firstPointToLastText = txtElement as IElement;
firstPointToLastText.Geometry = labelPt;
object oElement = (object)firstPointToLastText;
//根据角度旋转
TransformByRotate(ref oElement, labelPt, angle);
////添加到GraphicsContainer
g.AddElement(firstPointToLastText, 0);
//刷新
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, firstPointToLastText, null);
}
catch
{
throw;
}
#endregion
#region 计算单线的长度,并将结果显示在单线中点偏上上面
try
{
ILine line = new LineClass();
line.PutCoords(starPoint, pt);
//删除上一个连接线
if (moveText != null)
{
g.DeleteElement(moveText);
//刷新
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, moveText, null);
}
double angle = line.Angle;
if ((angle > (Math.PI / 2) && angle < (Math.PI)) || (angle > -Math.PI && angle < -(Math.PI / 2))) // 大于90度小于等于180
angle += Math.PI;
//标注点Y值偏移量
double d_OffsetY = myMapControl.ActiveView.ScreenDisplay.DisplayTransformation.FromPoints(9);
//标注点
double d_CenterX = (starPoint.X + pt.X) / 2;
double d_CenterY = (starPoint.Y + pt.Y) / 2 + d_OffsetY; //向上偏移
IPoint labelPt = new PointClass();
labelPt.PutCoords(d_CenterX, d_CenterY);
ITextElement txtElement = CreateTextElement(line.Length.ToString("0.00") + GetMapLenUnit(myMapControl.Map.MapUnits));
moveText = txtElement as IElement;
moveText.Geometry = labelPt;
object oElement = (object)moveText;
//根据角度旋转
TransformByRotate(ref oElement, labelPt, angle);
////添加到GraphicsContainer
g.AddElement(moveText, 0);
//刷新
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, moveText, null);
}
catch
{
throw;
}
#endregion
}
private void myMapControl_OnDoubleClick(object sender, IMapControlEvents2_OnDoubleClickEvent e)
{
m_NewLineFeedback.Stop();
m_NewLineFeedback = null;
pAreaPointCol.RemovePoints(0, pAreaPointCol.PointCount);
//删除g中的所有要素
g.DeleteAllElements();
starPoint=null;
firstPoint=null;
lastLine = null;
measureAreaText = null;
firstPointToLast = null;
firstPointToLastText = null;
//刷新
myMapControl.ActiveView.Refresh();
}
private void myMapControl_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
{
if (e.button == 1)
{
IPoint pt = new PointClass();
pt.X = e.mapX;
pt.Y = e.mapY;
pAreaPointCol.AddPoint(pt);
#region 绘制结点
try
{
pt.X = e.mapX;
pt.Y = e.mapY;
IElement pointElement = CreateElement(pt);
//
g.AddElement(pointElement, 0);
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, pointElement, null);
}
catch
{
throw;
}
#endregion
//画线
if (m_NewLineFeedback == null)
{
m_NewLineFeedback = new NewLineFeedbackClass();
ISimpleLineSymbol pLine = m_NewLineFeedback.Symbol as ISimpleLineSymbol;
RgbColorClass pColor = new RgbColorClass();
pColor.Red = 255;
pColor.Green = 0;
pColor.Blue = 0;
pLine.Color = pColor;
m_NewLineFeedback.Display = myMapControl.ActiveView.ScreenDisplay;
m_NewLineFeedback.Start(pt);
firstPoint = pt;
}
else
{
m_NewLineFeedback.AddPoint(pt);
}
if (starPoint == null)
{
}
else
{
ILine line = new LineClass();
line.PutCoords(starPoint, pt);
if (lastLine != null)
{
g.DeleteElement(lastLine);
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, lastLine, null);
lastLine = null;
}
#region 绘制轨迹线
try
{
object missing = Type.Missing;
ISegmentCollection segColl = new PolylineClass();
segColl.AddSegment(line as ISegment, ref missing, ref missing);
IElement traceElement = CreateElement(segColl as IPolyline);
g.AddElement(traceElement, 0);
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, traceElement, null);
}
catch
{
throw;
}
#endregion
#region 计算单线的长度,并将结果显示在单线中点偏上上面
try
{
double angle = line.Angle;
if ((angle > (Math.PI / 2) && angle < (Math.PI)) || (angle > -Math.PI && angle < -(Math.PI / 2))) // 大于90度小于等于180
angle += Math.PI;
//标注点Y值偏移量
double d_OffsetY = myMapControl.ActiveView.ScreenDisplay.DisplayTransformation.FromPoints(9);
//标注点
double d_CenterX = (starPoint.X + pt.X) / 2;
double d_CenterY = (starPoint.Y + pt.Y) / 2 + d_OffsetY; //向上偏移
IPoint labelPt = new PointClass();
labelPt.PutCoords(d_CenterX, d_CenterY);
ITextElement txtElement = CreateTextElement(line.Length.ToString("0.00") + GetMapLenUnit(myMapControl.Map.MapUnits));
IElement labelelement = txtElement as IElement;
labelelement.Geometry = labelPt;
object oElement = (object)labelelement;
//根据角度旋转
TransformByRotate(ref oElement, labelPt, angle);
////添加到GraphicsContainer
g.AddElement(labelelement, 0);
//刷新
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, labelelement, null);
}
catch
{
throw;
}
#endregion
if (pAreaPointCol.PointCount >= 3)
{
//连接起点和终点
ILine firstToLastLine = new LineClass();
firstToLastLine.PutCoords(firstPoint,pt);
#region 动态连接线
try
{
object missing = Type.Missing;
ISegmentCollection segColl = new PolylineClass();
segColl.AddSegment(firstToLastLine as ISegment, ref missing, ref missing);
//删除上一个连接线
if (firstPointToLast != null)
{
g.DeleteElement(firstPointToLast);
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, firstPointToLast, null);
}
firstPointToLast = CreateElement(segColl as IPolyline);
g.AddElement(firstPointToLast, 0);
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, firstPointToLast, null);
}
catch
{
throw;
}
#endregion
#region 动态连接线长度
try
{
double angle = firstToLastLine.Angle;
if ((angle > (Math.PI / 2) && angle < (Math.PI)) || (angle > -Math.PI && angle < -(Math.PI / 2))) // 大于90度小于等于180
angle += Math.PI;
//标注点Y值偏移量
double d_OffsetY = myMapControl.ActiveView.ScreenDisplay.DisplayTransformation.FromPoints(9);
//标注点
double d_CenterX = (firstPoint.X + pt.X) / 2;
double d_CenterY = (firstPoint.Y + pt.Y) / 2 + d_OffsetY; //向上偏移
IPoint labelPt = new PointClass();
labelPt.PutCoords(d_CenterX, d_CenterY);
if (firstPointToLastText!=null)
{
g.DeleteElement(firstPointToLastText);
//刷新
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, firstPointToLastText, null);
}
ITextElement txtElement = CreateTextElement(firstToLastLine.Length.ToString("0.00") + GetMapLenUnit(myMapControl.Map.MapUnits));
firstPointToLastText = txtElement as IElement;
firstPointToLastText.Geometry = labelPt;
object oElement = (object)firstPointToLastText;
//根据角度旋转
TransformByRotate(ref oElement, labelPt, angle);
////添加到GraphicsContainer
g.AddElement(firstPointToLastText, 0);
//刷新
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, firstPointToLastText, null);
}
catch
{
throw;
}
#endregion
IPointCollection pPointCol = new Polygon();
IPolygon pPolygon = new PolygonClass();
for (int i = 0; i < pAreaPointCol.PointCount; i++)
{
pPointCol.AddPoint(pAreaPointCol.Point[i]);
}
pPolygon = pPointCol as IPolygon;
if (pPolygon != null)
{
//使封闭
pPolygon.Close();
IArea pArea = pPolygon as IArea;
//几何中心点
IPoint iPnt = pArea.Centroid;
ITextElement txtElement = CreateTextElement(Math.Abs(pArea.Area).ToString("0.00") + GetMapAreaUnit(myMapControl.Map.MapUnits));
if (measureAreaText != null)
{
g.DeleteElement(measureAreaText);
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, measureAreaText, null);
}
//文字注记
measureAreaText = txtElement as IElement;
measureAreaText.Geometry = iPnt;
g.AddElement(measureAreaText, 0);
myMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, measureAreaText, null);
}
}
}
starPoint = pt;
}
}
/// <summary>
/// 按指定的角度旋转
/// </summary>
/// <param name="obj"></param>
/// <param name="originPt"></param>
/// <param name="rotate"></param>
private void TransformByRotate(ref object obj, IPoint originPt, double rotate)
{
if (obj == null && originPt == null)
return;
try
{
ITransform2D transform2D = obj as ITransform2D;
if (transform2D == null)
return;
transform2D.Rotate(originPt, rotate);
}
catch
{
throw;
}
}
/// <summary>
/// 绘制几何图形
/// </summary>
/// <param name="geoType"></param>
/// <param name="geometry"></param>
/// <returns></returns>
private ESRI.ArcGIS.Carto.IElement CreateElement(ESRI.ArcGIS.Geometry.IGeometry geometry)
{
IElement element = null;
try
{
switch (geometry.GeometryType)
{
case esriGeometryType.esriGeometryPolygon://设置Polygon面
IRgbColor polygonRGB = new RgbColorClass();
polygonRGB.Blue = 255;
polygonRGB.Red = 179;
polygonRGB.Green = 196;
polygonRGB.Transparency = (byte)0;
IFillSymbol polygonFill = new SimpleFillSymbolClass();
polygonFill.Color = polygonRGB;
IFillShapeElement fillShapeElement = new PolygonElementClass();
fillShapeElement.Symbol = polygonFill;
element = fillShapeElement as IElement;
element.Geometry = geometry;
break;
case esriGeometryType.esriGeometryPolyline://Polyline线
ISimpleLineSymbol simpleLineSymbol = m_NewLineFeedback.Symbol as ISimpleLineSymbol;
ILineElement lineElement = new LineElementClass();
lineElement.Symbol = simpleLineSymbol as ILineSymbol;
element = lineElement as IElement;
element.Geometry = geometry;
break;
case esriGeometryType.esriGeometryPoint://设置结点符号
IRgbColor pRGB = new RgbColorClass();
pRGB.Red = 255;
pRGB.Green = 0;
pRGB.Blue = 0;
ISimpleMarkerSymbol pSimpleMarkSymbol = new SimpleMarkerSymbolClass();
pSimpleMarkSymbol.Color = pRGB as IColor;
pSimpleMarkSymbol.Size = 2;
pSimpleMarkSymbol.Style = esriSimpleMarkerStyle.esriSMSSquare;
IMarkerElement pMarkerElement = new MarkerElementClass();
pMarkerElement.Symbol = pSimpleMarkSymbol as IMarkerSymbol;
element = pMarkerElement as IElement;
element.Geometry = geometry as IGeometry;
break;
}
}
catch
{
throw;
}
return element;
}
/// <summary>
/// 创建一个TextElement
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
private ITextElement CreateTextElement(string text)
{
//创建一个TextSymbol
ITextSymbol txtSymbol = new TextSymbolClass();
//设置字体
Font dispFont = new Font("Arial", 10, FontStyle.Regular);
txtSymbol.Font = (stdole.IFontDisp)ESRI.ArcGIS.ADF.COMSupport.OLE.GetIFontDispFromFont(dispFont);
//设置属性
txtSymbol.Color = TransColorToAEColor(Color.Red); //颜色
//创建一个TextElement
ITextElement txtElement = new TextElementClass();
txtElement.Symbol = txtSymbol;
txtElement.Text = text;
return txtElement;
}
/// <summary>
/// 获取当前地图的面积单位
/// </summary>
/// <param name="pEsriUnits"></param>
/// <returns></returns>
private string GetMapAreaUnit(esriUnits pEsriUnits)
{
string sMapUnits = string.Empty;
switch (pEsriUnits)
{
case esriUnits.esriCentimeters:
sMapUnits = "平方厘米";
break;
case esriUnits.esriDecimalDegrees:
sMapUnits = "十进制度";
break;
case esriUnits.esriDecimeters:
sMapUnits = "分米";
break;
case esriUnits.esriFeet:
sMapUnits = "尺";
break;
case esriUnits.esriInches:
sMapUnits = "英寸";
break;
case esriUnits.esriKilometers:
sMapUnits = "平方千米";
break;
case esriUnits.esriMeters:
sMapUnits = "平方米";
break;
case esriUnits.esriMiles:
sMapUnits = "英里";
break;
case esriUnits.esriMillimeters:
sMapUnits = "毫米";
break;
case esriUnits.esriNauticalMiles:
sMapUnits = "海里";
break;
case esriUnits.esriPoints:
sMapUnits = "点";
break;
case esriUnits.esriUnitsLast:
sMapUnits = "UnitsLast";
break;
case esriUnits.esriUnknownUnits:
sMapUnits = "";
break;
case esriUnits.esriYards:
sMapUnits = "码";
break;
default:
break;
}
return sMapUnits;
}
/// <summary>
/// 获取当前地图的长度单位
/// </summary>
/// <param name="pEsriUnits"></param>
/// <returns></returns>
private string GetMapLenUnit(esriUnits pEsriUnits)
{
string sMapUnits = string.Empty;
switch (pEsriUnits)
{
case esriUnits.esriCentimeters:
sMapUnits = "厘米";
break;
case esriUnits.esriDecimalDegrees:
sMapUnits = "十进制度";
break;
case esriUnits.esriDecimeters:
sMapUnits = "分米";
break;
case esriUnits.esriFeet:
sMapUnits = "尺";
break;
case esriUnits.esriInches:
sMapUnits = "英寸";
break;
case esriUnits.esriKilometers:
sMapUnits = "千米";
break;
case esriUnits.esriMeters:
sMapUnits = "米";
break;
case esriUnits.esriMiles:
sMapUnits = "英里";
break;
case esriUnits.esriMillimeters:
sMapUnits = "毫米";
break;
case esriUnits.esriNauticalMiles:
sMapUnits = "海里";
break;
case esriUnits.esriPoints:
sMapUnits = "点";
break;
case esriUnits.esriUnitsLast:
sMapUnits = "UnitsLast";
break;
case esriUnits.esriUnknownUnits:
sMapUnits = "";
break;
case esriUnits.esriYards:
sMapUnits = "码";
break;
default:
break;
}
return sMapUnits;
}
/// <summary>
/// 将系统颜色转换为IColor
/// </summary>
/// <param name="color"></param>
/// <returns></returns>
ESRI.ArcGIS.Display.IColor TransColorToAEColor(Color color)
{
IRgbColor rgb = new RgbColorClass();
rgb.RGB = color.R + color.G * 256 + color.B * 65536;
return rgb as IColor;
}
/// <summary>
/// 关闭测量工具,并清除所绘制的内容
/// </summary>
public void Close()
{
m_NewLineFeedback = null;
pAreaPointCol.RemovePoints(0, pAreaPointCol.PointCount);
//删除g中的所有要素
g.DeleteAllElements();
starPoint = null;
firstPoint = null;
lastLine = null;
measureAreaText = null;
firstPointToLast = null;
firstPointToLastText = null;
//刷新
myMapControl.ActiveView.Refresh();
//去除地图绑定的事件
myMapControl.OnMouseDown -= new IMapControlEvents2_OnMouseDownEventHandler(myMapControl_OnMouseDown);
//去除鼠标双击事件
myMapControl.OnDoubleClick -= new IMapControlEvents2_OnDoubleClickEventHandler(myMapControl_OnDoubleClick);
//去除鼠标移动事件
myMapControl.OnMouseMove -= new IMapControlEvents2_OnMouseMoveEventHandler(myMapControl_OnMouseMove);
}
}
}