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