arcEngine 求点到polyline集合的最近点 包括垂足计算

来源:互联网 发布:安卓软件开发教程 编辑:程序博客网 时间:2024/05/21 17:08

测试代码

  private void buttonItem21_Click(object sender, EventArgs e)
        {
            DateTime dt1 = DateTime.Now;
            CBuffer buffer = new CBuffer();
            //List<IGeometry> geoList = buffer.GetBufferInterList(this.myMapControl1.get_Layer(0) as IFeatureLayer, this.PntCurrent, 100000);
            int disNum = -1;
            ILine line = buffer.GetNearestLine(this.myMapControl1.get_Layer(0) as IFeatureLayer, this.PntCurrent, 100000, ref disNum);
            IGraphicsContainer pGraphicsContainer = this.myMapControl1.Map as IGraphicsContainer;
            pGraphicsContainer.DeleteAllElements();


            //foreach (IGeometry kv in geoList)
            //{
            //    ILineElement pLineElement;
            //    pLineElement = new LineElementClass();
            //    IElement pElement;
            //    pElement = pLineElement as IElement;
            //    pElement.Geometry = kv;
            //    pGraphicsContainer.AddElement((IElement)pLineElement, 0);
            //}          


            IMarkerElement pMarkerElement4;
            pMarkerElement4 = new MarkerElementClass();
            IElement pElement4;
            pElement4 = pMarkerElement4 as IElement;
            pElement4.Geometry = this.PntCurrent;
            pGraphicsContainer.AddElement((IElement)pMarkerElement4, 0);


            IMarkerElement pMarkerElement;
            pMarkerElement = new MarkerElementClass();
            IElement pElement2;
            pElement2 = pMarkerElement as IElement;
            pElement2.Geometry = line.FromPoint;
            pGraphicsContainer.AddElement((IElement)pMarkerElement, 0);


            IMarkerElement pMarkerElement2;
            pMarkerElement2 = new MarkerElementClass();
            IElement pElement3;
            pElement3 = pMarkerElement2 as IElement;
            pElement3.Geometry = line.ToPoint;
            pGraphicsContainer.AddElement((IElement)pMarkerElement2, 0);


            IPoint pnt = null;
            if (disNum == 0)
            {
                pnt = buffer.GetCrossPnt(line, this.PntCurrent);
            }
            else if (disNum == 1)
            {
                pnt = line.FromPoint;
            }
            else pnt = line.ToPoint;




            ISimpleMarkerSymbol pSimpleMarkerSymbol = new SimpleMarkerSymbolClass();


            pSimpleMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSSquare;
            pSimpleMarkerSymbol.Size = 10;
            pSimpleMarkerSymbol.Outline = true;
            pSimpleMarkerSymbol.OutlineSize = 4;


            IRgbColor pRGBColor = new RgbColorClass();


            pRGBColor.Red = 212;
            pRGBColor.Green = 212;
            pRGBColor.Blue = 212;
            pSimpleMarkerSymbol.OutlineColor = pRGBColor;


            IMarkerElement pMarkerElement5;
            pMarkerElement5 = new MarkerElementClass();
        
            pMarkerElement5.Symbol = pSimpleMarkerSymbol as IMarkerSymbol; 
            IElement pElement5;
            pElement5 = pMarkerElement5 as IElement;
            pElement5.Geometry = pnt;
            pGraphicsContainer.AddElement((IElement)pMarkerElement5, 0);




            this.myMapControl1.ActiveView.Refresh();


            MessageBox.Show(((DateTime.Now - dt1).Milliseconds / 1000.0).ToString());


        }




public class CBuffer

    {
        IPoint myPnt;
        public IGeometry buffer(IGeometry geo, double dis)
        {
            this.myPnt = geo as IPoint;


            ITopologicalOperator topolOperator = geo as ITopologicalOperator;
            IGeometry bufferGeometry = topolOperator.Buffer(dis);
            return bufferGeometry;  
        }






     /// <summary>
     /// 垂足
     /// </summary>
     /// <param name="line"></param>
     /// <param name="pnt"></param>
     /// <returns></returns>
      public  IPoint GetCrossPnt(ILine line, IPoint pnt)
        {
            IPoint pt1 = line.FromPoint;
            IPoint pt2 = line.ToPoint;
            double A = (pt1.Y - pt2.Y) / (pt1.X - pt2.X);
            double B = (pt1.Y - A * pt1.X);
            /// > 0 = ax +b -y;  对应垂线方程为 -x -ay + m = 0;(m为系数)
            /// > A = a; B = b;
            double m = pnt.X + A * pnt.Y;


            /// 求两直线交点坐标
            IPoint ptCross = new PointClass();


            ptCross.X = ((m - A * B) / (A * A + 1));
            ptCross.Y = (A * ptCross.X + B);
            return ptCross;
        }


      public ILine GetNearestLine(IFeatureLayer fLayer, IGeometry geo, double dis, ref int disNum)
        {
            List<IGeometry> listgeo = GetBufferInterList(fLayer, geo, dis);
            return this.GetNearestLine(listgeo,ref disNum);
        }


       public  List<IGeometry> GetBufferInterList(IFeatureLayer fLayer, IGeometry geo, double dis)
        {
            List<IGeometry> list = new List<IGeometry>();
            IGeometry geoBuffer = buffer(geo, dis);         


            ESRI.ArcGIS.Geodatabase.ISpatialFilter spatialFilter = new ESRI.ArcGIS.Geodatabase.SpatialFilterClass();
            spatialFilter.Geometry = geoBuffer;
            spatialFilter.SpatialRel = ESRI.ArcGIS.Geodatabase.esriSpatialRelEnum.esriSpatialRelIntersects;
            ESRI.ArcGIS.Geodatabase.IFeatureCursor featureCursor = fLayer.Search(spatialFilter, false);


            ESRI.ArcGIS.Geodatabase.IFeature pFeature;
            while ((pFeature = featureCursor.NextFeature()) != null)
            {
                list.Add(pFeature.Shape);
            }


            return list;
        }


        ILine GetNearestLine(List<IGeometry> listGeo,ref int disNum)
        {
            ILine line = null;


            double distance = 99999999;
            foreach (IPolyline pl in listGeo)
            {
                double dis = -1;
                int dnum = -1;
                ILine L = GetNearestLine(pl, ref dis, ref dnum);
                if (distance > dis)
                {
                    disNum = dnum;
                    distance = dis;
                    line = L;
                }
            }


            return line;
        }


        ILine GetNearestLine(IPolyline pline,ref double dis,ref int disNum)
        {
            ILine line = null;
            IPointCollection pcl = pline as IPointCollection;


            dis = 9999999;
            for(int i = 1;i<pcl.PointCount;i++)
            {
                ILine l = new LineClass();
                l.FromPoint = pcl.get_Point(i - 1);
                l.ToPoint = pcl.get_Point(i);
                int dnum = -1;
                double d = getPointDistance(l, this.myPnt, ref dnum);
                if (dis > d) {
                    disNum = dnum;
                    dis = d;
                    line = l;
                }


            }


            return line;
        }


        double getPointDistance(ILine line, IPoint pnt, ref int disNum)
        {          
            return GetNearestDistance(line.FromPoint, line.ToPoint, pnt, ref disNum);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="PA"></param>
        /// <param name="PB"></param>
        /// <param name="P3"></param>
        /// <param name="disNum">在线段上的位置</param>
        /// <returns></returns>
        double GetNearestDistance(IPoint PA, IPoint PB, IPoint P3,ref int disNum)
        {


            //----------图2--------------------   
            double a, b, c;
            a = GetPointDistance(PB, P3);
            if (a <= 0.00001)
            {
                disNum = 2;//在线段的B点
                return 0.0f;
            }
            b = GetPointDistance(PA, P3);
            if (b <= 0.00001)
            {
                disNum = 1;//在线段的A点
                return 0.0f;
            }
            c = GetPointDistance(PA, PB);
            if (c <= 0.00001)
                return a;//如果PA和PB坐标相同,则退出函数,并返回距离   
            //------------------------------   


            if (a * a >= b * b + c * c)//--------图3--------   
            {
                disNum = 1;
                return b;
            }
            if (b * b >= a * a + c * c)//--------图4-------   
            {
                disNum = 2;
                return a;
            }


            //图1   
            double l = (a + b + c) / 2;     //周长的一半   
            double s = Math.Sqrt(l * (l - a) * (l - b) * (l - c));  //海伦公式求面积   
            disNum = 0;//在线段中间
            return 2 * s / c;
        }


        double GetPointDistance(IPoint p1, IPoint p2)
        {
            return Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
        }
    }
0 0
原创粉丝点击