主要功能代码如下:
#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; } } 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在这里。
最终效果:
