您的位置:首页 > 其它

AE学习笔记之距离量测和面积量测

2016-10-14 16:14 323 查看
[align=center]距离量测和面积量测[/align]
[align=left]
[/align]
[align=left]        距离量测即根据鼠标点击的位置得到地图上的距离。首先建立一个量测结果显示对话框,如下图:[/align]



[align=left]对话框中的函数如下:[/align]

public delegate void FormClosedEventHandler();
public FormClosedEventHandler frmClosed = null;

public FormMeasureResult()
{
InitializeComponent();

}
public void setLabelText(string text)
{
label2.Text = text;
}

private void FormMeasureResult_FormClosed(object sender, FormClosedEventArgs e)
{
if (frmClosed != null)
frmClosed();
}

[align=left]里面主要是写了一个编辑Label框的函数。在这里提到了delegate (委托),虽然在这个功能里面没有用到,但我还是贴出来顺便介绍一下(暴漏了这些其实是别人的代码的真相)。主要是第一次接触delegete这个方法,觉得挺有意思。[/align]
[align=left]介绍委托:[/align]

引言

    Delegate是Dotnet1.0的时候已经存在的特性了,但由于在实际工作中一直没有机会使用Delegate这个特性,所以一直没有对它作整理。这两天,我再度翻阅了一些关于Delegate的资料,并开始正式整理这个C#中著名的特性。本文将由浅入深的谈一下Delegate这个特性。

一.Delegate是什么?

    Delegate中文翻译为“委托”。Msdn中对Delegate的解释如下:

    C#中的委托类似于C或C++中的函数指针。使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与C或C++中的函数指针不同,委托是面向对象、类型安全的,并且是安全的。

    如果你是第一次接触Delegate这个概念,你可能会对上面这段文字感觉不知所云,不过不要紧,你可以先把Delegate认为就是一个函数指针。

    而当你面对一个虚无的概念时,最好的应对方法就是直接看实例。下面一个简单的Delegate使用例子。

class Program
{
static void OtherClassMethod(){
Console.WriteLine("Delegate an other class's method");
}

static void Main(string[] args)
{
var test = new TestDelegate();
test.delegateMethod = new TestDelegate.DelegateMethod(test.NonStaticMethod);
test.delegateMethod += new TestDelegate.DelegateMethod(TestDelegate.StaticMethod);
test.delegateMethod += Program.OtherClassMethod;
test.RunDelegateMethods();
}
}

class TestDelegate
{
public delegate void DelegateMethod();  //声明了一个Delegate Type

public DelegateMethod delegateMethod;   //声明了一个Delegate对象

public static void StaticMethod()
{
Console.WriteLine("Delegate a static method");
}

public void NonStaticMethod()
{
Console.WriteLine("Delegate a non-static method");
}

public void RunDelegateMethods()
{
if(delegateMethod != null){
Console.WriteLine("---------");
delegateMethod.Invoke();

Console.WriteLine("---------");
}
}
}


上面是一个Delegate的使用例子,运行看看结果吧。下面我稍微解释一下:

【1】public delegate void DelegateMethod();这里声明了一个Delegate的类型,名为DelegateMethod,这种Delegate类型可以搭载:返回值为void,无传入参数的函数。

【2】public DelegateMethod delegateMethod;这里声明了一个DelegateMethod的对象(即,声明了某种Delegate类型的对象)。

区分:DelegateMethod是类型,delegateMethod是对象。

【3】为什么上面说Delegate可以看做是函数指针呢?看下面这段代码:

test.delegateMethod = new TestDelegate.DelegateMethod(test.NonStaticMethod);
test.delegateMethod += new TestDelegate.DelegateMethod(TestDelegate.StaticMethod);
test.delegateMethod += Program.OtherClassMethod;

这里delegateMethod搭载了3个函数,而且可以通过调用delegateMethod.Invoke();运行被搭载的函数。这就是Delegate可以看作为函数指针的原因。上面这段代码中,delegateMethod只能搭载:返回值为void,无传入参数的函数(见:NonStaticMethod,StaticMethod,OtherClassMethod的定义),这和Delegate类型声明有关(见DelegateMethod的声明:publicdelegate
void DelegateMethod())。

【4】Delegate在搭载多个方法时,可以通过+=增加搭载的函数,也可以通过-=来去掉Delegate中的某个函数。

2、Form中添加成员变量

 
#region 地图量测
//显示地图量测结果
private FormMeasureResult frmMeasureResult = null;//量算结果窗体
private ESRI.ArcGIS.Display.INewLineFeedback pNewLineFeedback;   //追踪线对象
private ESRI.ArcGIS.Display.INewPolygonFeedback pNewPolygonFeedback;   //追踪面对象
private ESRI.ArcGIS.Geometry.IPoint pPointpt = null;     //鼠标点击点位置
private ESRI.ArcGIS.Geometry.IPoint pMovePoint = null;   //鼠标移动点位置
private double dToltalLength = 0.0;                       //量测总长度
private double dSegmentLength = 0.0;                     //片段距离

private ESRI.ArcGIS.Geometry.IPointCollection pAreaPointCol = new ESRI.ArcGIS.Geometry.MultipointClass();

private string sMapUnits = "UnKnow";
#endregion

3、鼠标移动处理函数,获取鼠标移动的位置显示一个变化的距离值。
private void axMapControl1_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent e)
{
sMapUnits = GetMapUnit(axMapControl1.Map.MapUnits);
pMovePoint = (axMapControl1.Map as IActiveView).ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);//屏幕坐标转换为地图坐标

//距离测量结果实时显示
if (pMouseOperate == "MeasureLength")
{
if (pNewLineFeedback != null)
{
pNewLineFeedback.MoveTo(pMovePoint);
}
double disX = 0.0;  //两点之间X差值
double disY = 0.0;  //两点之间Y差值
if ((pPointpt != null) && (pNewLineFeedback != null))
{
disX = pMovePoint.X - pPointpt.X;
disY = pMovePoint.Y - pPointpt.Y;

dSegmentLength = Math.Round(Math.Sqrt((disX * disX) + (disY * disY)), 3);
dToltalLength = dToltalLength + dSegmentLength;
if (frmMeasureResult != null)
{
frmMeasureResult.setLabelText(String.Format(
"当前线段长度:{0:.###}{1};\r\n总长度为: {2:.###}{1}",
dSegmentLength, sMapUnits, dToltalLength));
dToltalLength = dToltalLength - dSegmentLength; //鼠标移动到新点重新开始计算
}
frmMeasureResult.frmClosed += new FormMeasureResult.FormClosedEventHandler(frmMeasureResult_frmColsed);
}

}
//面积测量结果实时显示
if(pMouseOperate=="MeasureArea")
{
if(pNewPolygonFeedback!=null)
{
pNewPolygonFeedback.MoveTo(pMovePoint);
}
IPointCollection pPointCol=new Polygon();
IPolygon pPolygon=new PolygonClass();
IGeometry pGeo=null;
ITopologicalOperator pTopo=null;
for(int i=0;i<pAreaPointCol.PointCount;++i)
{
pPointCol.AddPoint(pAreaPointCol.get_Point(i));

}
pPointCol.AddPoint(pMovePoint);
if(pPointCol.PointCount<3) return;
pPolygon=pPointCol as IPolygon;
if(pPolygon!=null)
{
pPolygon.Close();
pGeo=pPolygon as IGeometry;
pTopo= pGeo as ITopologicalOperator;
//使几何图形的拓扑正确
pTopo.Simplify();
pGeo.Project(axMapControl1.Map.SpatialReference);
IArea pArea = pGeo as IArea;

frmMeasureResult.setLabelText( String.Format(
"总面积为:{0:.####}平方{1};\r\n总长度为:{2:.####}{1}",
pArea.Area, sMapUnits, pPolygon.Length));
pPolygon = null;

}
}

}


4、获取当前的距离单位,并将其改为汉字的单位。
private string GetMapUnit(esriUnits _esriMapUnit)
{
string sMapUnits = string.Empty;
switch (_esriMapUnit)
{
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;
}


5、单击距离计算按钮响应函数
private void MeasureLength_Click(object sender, EventArgs e)
{
axMapControl1.CurrentTool = null;
pMouseOperate = "MeasureLength";
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair;
if (frmMeasureResult == null || frmMeasureResult.IsDisposed)
{
frmMeasureResult = new FormMeasureResult();
frmMeasureResult.frmClosed += new FormMeasureResult.FormClosedEventHandler(frmMeasureResult_frmColsed);
frmMeasureResult.Text = "距离量测";
frmMeasureResult.setLabelText("");
frmMeasureResult.Show();
}
else
{
frmMeasureResult.Activate();
}

}


6、双击结束选择,得到最终距离量测结果
private void axMapControl1_OnDoubleClick(object sender, IMapControlEvents2_OnDoubleClickEvent e)
    {
        if (pMouseOperate == "MeasureLength") 
            { 
                if (frmMeasureResult != null) 
                { 
                    frmMeasureResult.setLabelText("线段总长度为:" + dToltalLength + sMapUnits); 
                } 
                if (pNewLineFeedback != null) 
                { 
                    pNewLineFeedback.Stop(); 
                    pNewLineFeedback = null; 
                    //清空所画的线对象 
                    (axMapControl1.Map as IActiveView).PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null); 
                } 
                dToltalLength = 0; 
                dSegmentLength = 0; 
            } 
        if(pMouseOperate=="MeasureArea")
        {
             if (pNewPolygonFeedback != null) 
                { 
                    pNewPolygonFeedback.Stop(); 
                    pNewPolygonFeedback = null; 
                    //清空所画的线对象 
                    (axMapControl1.Map as IActiveView).PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null); 
                } 
                pAreaPointCol.RemovePoints(0, pAreaPointCol.PointCount); //清空点集中所有点 
        }
    }


7、面积量测函数
private void MeasureArea_Click(object sender, EventArgs e)
{
axMapControl1.CurrentTool = null;
pMouseOperate = "MeasureArea";
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair;
if (frmMeasureResult == null || frmMeasureResult.IsDisposed)
{
frmMeasureResult = new FormMeasureResult();
frmMeasureResult.frmClosed += new FormMeasureResult.FormClosedEventHandler(frmMeasureResult_frmColsed);
frmMeasureResult.setLabelText("");
frmMeasureResult.Text = "面积量测";
frmMeasureResult.Show();
}
else
{
frmMeasureResult.Activate();    //激活窗体
}

}


运行结果:



--------------------------------------------------------------end----------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: