GMap.NET地图鼠标点击测距,带固定点吸附效果

主要功能代码如下:

  #region 测距模块

        List<Model.MeasurePoint> listPoint = new List<Model.MeasurePoint>();
        bool isMapRouting = false;

        private void gMapControl1_Click(object sender, EventArgs e)
        {
            if (isMapRouting)
            {
                //当前正在测距模式
                MouseEventArgs me = (MouseEventArgs)e;
                if (me.Button == MouseButtons.Right)
                {
                    isMapRouting = false;
                    this.gMapControl1.MouseWheelZoomType = MouseWheelZoomType.MousePositionWithoutCenter;
                    Map_Temporarily.Routes.Clear();
                }
                else
                {

                    Model.MeasurePoint measurePoint = getCloserFixPoint(me.X, me.Y);

                    if (measurePoint == null)
                    {
                        PointLatLng clickPoint = this.gMapControl1.FromLocalToLatLng(me.X, me.Y);
                        measurePoint = new Model.MeasurePoint(clickPoint.Lat, clickPoint.Lng, double.MinValue);
                    }
                    this.Map_Scribing.Routes.Clear();        //清空路线图层  
                    listPoint.Add(measurePoint);
                    //根据坐标list计算点list
                    List<PointLatLng> listRoute = new List<PointLatLng>();
                    foreach (Model.MeasurePoint point in listPoint)
                    {
                        listRoute.Add(new PointLatLng(point.经度, point.纬度));
                    }
                    GMapRoute item = new GMapRoute(listRoute, "line");
                    item.Stroke.Color = Color.Red;
                    item.Stroke.Width = 1;  //设置画线粗细
                    Map_Scribing.Routes.Add(item);

                    //地图坐标点
                    GMapMarker marker = new GMarkerGoogle(new PointLatLng(measurePoint.经度, measurePoint.纬度), measurePoint.高度 == double.MinValue ? GMarkerGoogleType.red_small : GMarkerGoogleType.green_small);
                    if (listPoint.Count == 1)
                    {
                        //起点

                        marker.ToolTip = new GMapBaloonToolTip(marker);
                        marker.ToolTipMode = MarkerTooltipMode.Always;
                        marker.ToolTip.Foreground = new SolidBrush(Color.White);
                        marker.ToolTip.Stroke = new Pen(Color.FromArgb(64, 84, 62));
                        marker.ToolTip.Offset = new Point(-10, -40);
                        marker.ToolTip.Font = new Font("Arial", 8);
                        marker.ToolTip.Fill = new SolidBrush(Color.FromArgb(64, 84, 62));
                        marker.ToolTipText = String.Format("起点");
                        Map_Scribing.Markers.Add(marker);
                    }
                    else
                    {
                        //计算距离
                        string text = "";
                        Model.MeasurePoint pointCurrent = listPoint[listPoint.Count - 1];
                        Model.MeasurePoint pointLast = listPoint[listPoint.Count - 2];
                        if (pointCurrent.高度 != double.MinValue && pointLast.高度 != double.MinValue)
                        {
                            //3D距离
                            double d = DistanceUtils.getInstance().GetDistance(pointCurrent.经度, pointCurrent.纬度, pointLast.经度, pointLast.纬度);
                            double d3d = DistanceUtils.getInstance().GetDistance3D(pointCurrent.经度, pointCurrent.纬度, pointCurrent.高度, pointLast.经度, pointLast.纬度, pointLast.高度);
                            text = string.Format("水平距离:{0}米\r\n三维距离:{1}米", d, d3d);
                        }
                        else
                        {
                            double d = DistanceUtils.getInstance().GetDistance(pointCurrent.经度, pointCurrent.纬度, pointLast.经度, pointLast.纬度);
                            text = string.Format("水平距离:{0}米", d);
                        }
                        marker.ToolTip = new GMapBaloonToolTip(marker);
                        marker.ToolTipMode = MarkerTooltipMode.Always;
                        marker.ToolTip.Foreground = new SolidBrush(Color.White);
                        marker.ToolTip.Stroke = new Pen(Color.FromArgb(64, 84, 62));
                        marker.ToolTip.Offset = new Point(-10, -40);
                        marker.ToolTip.Font = new Font("Arial", 8);
                        marker.ToolTip.Fill = new SolidBrush(Color.FromArgb(64, 84, 62));
                        marker.ToolTipText = text;
                        Map_Scribing.Markers.Add(marker);
                    }
                }
            }
        }

        //计算周围30像素坐标内有没有固定点
        private Model.MeasurePoint getCloserFixPoint(int clickX, int clickY)
        {
            PointLatLng clickPoint = this.gMapControl1.FromLocalToLatLng(clickX, clickY);
            PointLatLng closerPoint = this.gMapControl1.FromLocalToLatLng(clickX - 30, clickY);
            double distance = DistanceUtils.getInstance().GetDistance(clickPoint.Lat, clickPoint.Lng, closerPoint.Lat, closerPoint.Lng);
            //计算辐射源是否在附近
            if (listRadiation != null)
            {
                foreach (Model.辐射源 model in listRadiation)
                {
                    double distanceCloser = DistanceUtils.getInstance().GetDistance(clickPoint.Lat, clickPoint.Lng, model.经度, model.纬度);
                    if (distanceCloser < distance)
                    {
                        return new Model.MeasurePoint(model.经度, model.纬度, model.高度);
                    }
                }
            }
            //计算标注点是否在附近
            if (listMark != null)
            {
                foreach (Model.标注点 model in listMark)
                {
                    double distanceCloser = DistanceUtils.getInstance().GetDistance(clickPoint.Lat, clickPoint.Lng, model.经度, model.纬度);
                    if (distanceCloser < distance)
                    {
                        return new Model.MeasurePoint(model.经度, model.纬度, model.高度);
                    }
                }
            }
            //计算自定位是否在附近
            if (modelSelf != null)
            {
                double distanceCloser = DistanceUtils.getInstance().GetDistance(clickPoint.Lat, clickPoint.Lng, modelSelf.经度, modelSelf.纬度);
                if (distanceCloser < distance)
                {
                    return new Model.MeasurePoint(modelSelf.经度, modelSelf.纬度, modelSelf.高度);
                }
            }
            return null;
        }

        private void gMapControl1_DoubleClick(object sender, EventArgs e)
        {
            MouseEventArgs me = (MouseEventArgs)e;
            if (me.Button == MouseButtons.Right)
            {
                listPoint.Clear();
                Map_Scribing.Markers.Clear();
                Map_Scribing.Routes.Clear();
                Map_Temporarily.Routes.Clear();
                isMapRouting = false;
                this.gMapControl1.MouseWheelZoomType = MouseWheelZoomType.MousePositionWithoutCenter;
            }

            //if (gMapControl1.Overlays.Contains(Map_label))
            //{
            //    if (listPoint.Count >= 2)
            //    {
            //        double d = 0;
            //        //for (int i = 0; i < listPoint.Count; i++)
            //        //{
            //        //    if (listPoint.Count != i + 1)
            //        //    {
            //        //        d += GetDistance(listPoint[i].Lat, listPoint[i].Lng, listPoint[i + 1].Lat, listPoint[i + 1].Lng);
            //        //    }
            //        //}
            //        //GMapMarkerBS gMapMarker = new GMapMarkerBS(listPoint[listPoint.Count - 1], string.Format("总距离={0}千米", d.ToString()), "Measurement");
            //        //Map_label.Markers.Add(gMapMarker);
            //        Map_Temporarily.Routes.Clear();
            //    }
            //}
        }

        private void gMapControl1_MouseMove(object sender, MouseEventArgs e)
        {
            PointLatLng latLng = this.gMapControl1.FromLocalToLatLng(e.X, e.Y);
            //显示当前鼠标坐标
            this.labelMouseLatLng.Text = String.Format("{0}, {1}", latLng.Lat, latLng.Lng);
            //测距的时候画线
            if (listPoint.Count > 0 && isMapRouting)
            {
                List<PointLatLng> listPoint1 = new List<PointLatLng>();
                if (latLng.Lat != listPoint[listPoint.Count - 1].经度 && latLng.Lng != listPoint[listPoint.Count - 1].纬度)
                {
                    listPoint1.Add(new PointLatLng(listPoint[listPoint.Count - 1].经度, listPoint[listPoint.Count - 1].纬度));
                    listPoint1.Add(new PointLatLng(latLng.Lat, latLng.Lng));

                    Map_Temporarily.Routes.Clear();
                    GMapRoute item = new GMapRoute(listPoint1, "line");
                    item.Stroke.Color = Color.Red;
                    item.Stroke.Width = 1;  //设置画线粗细
                    Map_Temporarily.Routes.Add(item);
                }
            }
        }

        private void metroButton测距_Click(object sender, EventArgs e)
        {
            isMapRouting = true;
            this.gMapControl1.MouseWheelZoomType = MouseWheelZoomType.MousePositionAndCenter;
            listPoint.Clear();
            Map_Scribing.Markers.Clear();
            Map_Scribing.Routes.Clear();
            Map_Temporarily.Routes.Clear();
        }



        #endregion

其中测量距离类如下:

class DistanceUtils
    {

        private DistanceUtils()
        {
        }

        /**
         * 获取实例
         * @author hefan
         * @date 2018/9/27 10:05
         */
        public static DistanceUtils getInstance()
        {
            return new DistanceUtils();
        }

        //平面坐标测距
        private double rad(double d)
        {
            return d * Math.PI / 180.0;
        }

        public double GetDistance(double lat1, double lng1, double lat2, double lng2)
        {

            // instantiate the calculator
            GeodeticCalculator geoCalc = new GeodeticCalculator();

            // select a reference elllipsoid
            Ellipsoid reference = Ellipsoid.WGS84;

            // set Lincoln Memorial coordinates
            GlobalCoordinates lincolnMemorial;
            lincolnMemorial = new GlobalCoordinates(lat1, lng1);

            // set Eiffel Tower coordinates
            GlobalCoordinates eiffelTower;
            eiffelTower = new GlobalCoordinates(lat2, lng2);

            // calculate the geodetic curve
            GeodeticCurve geoCurve = geoCalc.CalculateGeodeticCurve(reference, lincolnMemorial, eiffelTower);

            return Math.Round(geoCurve.EllipsoidalDistance, 2);
        }

        public double GetDistance3D(double lat1, double lng1, double height1,  double lat2, double lng2, double height2)
        {
            // instantiate the calculator
            GeodeticCalculator geoCalc = new GeodeticCalculator();

            // select a reference elllipsoid
            Ellipsoid reference = Ellipsoid.WGS84;

            // set Pike's Peak position
            GlobalPosition pikesPeak;
            pikesPeak = new GlobalPosition(new GlobalCoordinates(new Angle(lat1), new Angle(lng1)), height1);

            // set Alcatraz Island coordinates
            GlobalPosition alcatrazIsland;
            alcatrazIsland = new GlobalPosition(new GlobalCoordinates(new Angle(lat2), new Angle(lng2)), height2);

            // calculate the geodetic measurement
            GeodeticMeasurement geoMeasurement;

            geoMeasurement = geoCalc.CalculateGeodeticMeasurement(reference, pikesPeak, alcatrazIsland);

            return Math.Round(geoMeasurement.PointToPointDistance, 2);
        }

        //获取一个小数的整数部分和小数部分
        static double[] modf(double t)
        {
            t += 1.0e-14;//避免角度转换过程产生无效近似
            double t_integer = Math.Floor(t);
            return new double[] { t_integer, t - t_integer };
        }

        //角度转弧度
        static double turn1(double t)
        {
            double[] t1 = modf(t);
            double[] t2 = modf(t1[1] * 100);
            double x1 = t1[0];
            double x2 = t2[0];
            double x3 = t2[1] * 100;
            //Console.Write("{0:N} \t {1:N}\t {2:N}\r\n", x1, x2, x3);
            return (x1 + x2 / 60 + x3 / 3600) / 180 * Math.PI;
        }

        //经度、纬度和大地高转向空间直角坐标
        private double[] LBH2XYZ(double[] lbh)
        {
            double B = turn1(lbh[1]);
            double L = turn1(lbh[0]);
            double H = lbh[2];
            double A = 1 / 298.257223563;
            double a = 6378137.0000000000;

            double E = 2 * A - A * A;
            double W = Math.Sqrt(1 - E * Math.Sin(B) * Math.Sin(B));
            double N = a / W;

            double[] xyz = { 0.0, 0.0, 0.0 };
            xyz[0] = (N + H) * Math.Cos(B) * Math.Cos(L);
            xyz[1] = (N + H) * Math.Cos(B) * Math.Sin(L);
            xyz[2] = (N * (1 - E) + H) * Math.Sin(B);

            return xyz;
        }


        //火星坐标变换
        private double transformLat(double x, double y)
        {
            double pi = 3.14159265358979324;

            var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.Sqrt(Math.Abs(x));
            ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0;
            ret += (20.0 * Math.Sin(y * pi) + 40.0 * Math.Sin(y / 3.0 * pi)) * 2.0 / 3.0;
            ret += (160.0 * Math.Sin(y / 12.0 * pi) + 320 * Math.Sin(y * pi / 30.0)) * 2.0 / 3.0;
            return ret;
        }
        private double transformLng(double x, double y)
        {
            double pi = 3.14159265358979324;

            var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.Sqrt(Math.Abs(x));
            ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0;
            ret += (20.0 * Math.Sin(x * pi) + 40.0 * Math.Sin(x / 3.0 * pi)) * 2.0 / 3.0;
            ret += (150.0 * Math.Sin(x / 12.0 * pi) + 300 * Math.Sin(x / 30.0 * pi)) * 2.0 / 3.0;
            return ret;
        }
        public double[] transform(double wgLat, double wgLng)  //84 -MARS
        {
            double[] mypointc = new double[2];
            double pi = 3.14159265358979324;
            double a = 6378245.0;
            double ee = 0.00669342162296594323;

            var dLat = transformLat(wgLng - 105.0, wgLat - 35.0);
            var dLng = transformLng(wgLng - 105.0, wgLat - 35.0);
            var radLat = wgLat / 180.0 * pi;
            var magic = Math.Sin(radLat);
            magic = 1 - ee * magic * magic;
            var sqrtMagic = Math.Sqrt(magic);
            dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
            dLng = (dLng * 180.0) / (a / sqrtMagic * Math.Cos(radLat) * pi);
            mypointc[0] = wgLat + dLat;
            mypointc[1] = wgLng + dLng;
            return mypointc;
        }
    }

测距用了这个类库Gavaghan.Geodesy, DLL在这里

最终效果:

发表在 .NET, 文章 | 标签为 , | 留下评论

斐讯插排TC1改造,基于ESP8266和阿里云IOT

继续阅读

发表在 单片机, 文章 | 标签为 , , , | 留下评论

群晖SurveillanceStation连接萤石C6Tc摄像头

继续阅读

发表在 文章 | 留下评论

【雕刻机】制作雕刻机控制箱

继续阅读

发表在 作品, 雕刻机 | 标签为 , | 留下评论

【算法练习题】纸牌游戏——小猫钓鱼

继续阅读

发表在 文章, 算法 | 留下评论

【算法练习题】排序合集

继续阅读

发表在 文章, 算法 | 留下评论

【算法练习题】求解数组最大差值

继续阅读

发表在 文章, 算法 | 留下评论

【C#】Visual Studio 常用快捷键

继续阅读

发表在 文章 | 留下评论

【C#】通过调用minitab自动化生成报表

继续阅读

发表在 .NET, 文章 | 留下评论

【C#】ASCII和十六进制码转换小工具ASCII2Hex

继续阅读

发表在 作品, 应用程序 | 留下评论