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

距离量测和面积量测

        距离量测即根据鼠标点击的位置得到地图上的距离。首先建立一个量测结果显示对话框,如下图:
对话框中的函数如下:
 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();
        }
里面主要是写了一个编辑Label框的函数。在这里提到了delegate (委托),虽然在这个功能里面没有用到,但我还是贴出来顺便介绍一下(暴漏了这些其实是别人的代码的真相)。主要是第一次接触delegete这个方法,觉得挺有意思。
介绍委托:

引言

    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----------------------------------------------------------

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值