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 &amp;&amp; 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;
    }
}

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 &amp;&amp; isMapRouting)
    {
        List<PointLatLng> listPoint1 = new List<PointLatLng>();
        if (latLng.Lat != listPoint[listPoint.Count - 1].经度 &amp;&amp; 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, 文章分类目录,贴了, 标签。将固定链接加入收藏夹。

发表评论