/// <summary> /// 转换坐标点根据经纬度 /// </summary> /// <param name="lat">纬度后面一位必须带N or S</param> /// <param name="lon">经度后面一位必须带E or W</param> /// <returns></returns> public static PointCoordinate GetPointCoordinate(string lat, string lon) { PointCoordinate p = new PointCoordinate(); if (lat.Substring(lat.Length - 1, 1) == "N") { lat = lat.Substring(0, lat.Length - 1); p.Latitide = double.Parse(lat) / 10000; } else { lat = lat.Substring(0, lat.Length - 1); p.Latitide = 0 - double.Parse(lat) / 10000; } if (lon.Substring(lon.Length - 1, 1) == "E") { lon = lon.Substring(0, lon.Length - 1); p.Longitude = double.Parse(lon) / 10000; } else { lon = lon.Substring(0, lon.Length - 1); p.Longitude = 0 - double.Parse(lon) / 10000; } return(p); }
/// <summary> /// 根据已经点、方位和角度,计算另一点坐标。 /// </summary> /// <param name="angle">航线角(磁方向,弧度单位)</param> /// <param name="distance">距离(公里)</param> /// <param name="point">参考点</param> /// <returns></returns> public static PointCoordinate CalcuateCoordinate(PointCoordinate point, double angle, double distance) { PointCoordinate p = new PointCoordinate(); double R = 6371.0; // earth's mean radius in km double d = distance / R; double lat1 = GreatCircleArgorithm.ConvertToARC(GreatCircleArgorithm.ConvertToDeg(point.Latitide)); double lon1 = GreatCircleArgorithm.ConvertToARC(GreatCircleArgorithm.ConvertToDeg(point.Longitude)); double brng = GreatCircleArgorithm.ConvertToDeg(angle) * Math.PI / 180; //将度转换为弧度 double lat2 = lat1 + d * Math.Cos(brng); double dLat = lat2 - lat1; double dPhi = Math.Log(Math.Tan(lat2 / 2 + Math.PI / 4) / Math.Tan(lat1 / 2 + Math.PI / 4)); double q = (Math.Abs(dLat) > 0.000000001) ? dLat / dPhi : Math.Cos(lat1); double dlon = d * Math.Sin(brng) / q; if (Math.Abs(lat2) > Math.PI / 2) { lat2 = lat2 > 0 ? Math.PI - lat2 : -Math.PI - lat2; } double lon2 = (lon1 + dlon + Math.PI) % (2 * Math.PI) - Math.PI; p.Latitide = GreatCircleArgorithm.ConvertToDMS(GreatCircleArgorithm.ConvertToDegree(lat2)); p.Longitude = GreatCircleArgorithm.ConvertToDMS(GreatCircleArgorithm.ConvertToDegree(lon2)); return(p); }
/// <summary> /// 从某已知点和距离、方位角算另一点坐标 /// </summary> /// <param name="point">已知点</param> /// <param name="angle">方位角</param> /// <param name="distance">距离(公里)</param> /// <returns></returns> public static PointCoordinate CalcuateCoordinate(PointCoordinate point, double angle, double distance) { double lat1 = ConvertToARC(ConvertToDeg(point.Latitide)); double lon1 = ConvertToARC(ConvertToDeg(point.Longitude)); double brng = ConvertToARC(ConvertToDeg(angle)); double lat2 = Math.Asin(Math.Sin(lat1) * Math.Cos(distance / R) + Math.Cos(lat1) * Math.Sin(distance / R) * Math.Cos(brng)); double lon2 = lon1 + Math.Atan2(Math.Sin(brng) * Math.Sin(distance / R) * Math.Cos(lat1), Math.Cos(distance / R) - Math.Sin(lat1) * Math.Sin(lat2)); lon2 = (lon2 + Math.PI) % (2 * Math.PI) - Math.PI; //;normalise to -180...+180 PointCoordinate p = new PointCoordinate(); p.Longitude = ConvertToDMS(ConvertToDegree(lon2)); p.Latitide = ConvertToDMS(ConvertToDegree(lat2)); return(p); /* * var R = 6371; // earth's mean radius in km * var lat1 = this.lat.toRad(), lon1 = this.lon.toRad(); * brng = brng.toRad(); * * var lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) + * Math.cos(lat1)*Math.sin(d/R)*Math.cos(brng) ); * var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(lat1), * Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2)); * lon2 = (lon2+Math.PI)%(2*Math.PI) - Math.PI; // normalise to -180...+180 * * if (isNaN(lat2) || isNaN(lon2)) return null; * return new LatLon(lat2.toDeg(), lon2.toDeg()); * * */ }
/// <summary> /// 计算两点间角度 /// </summary> /// <param name="firstPoint"></param> /// <param name="endPoint"></param> /// <returns></returns> public static double CalculateAngle(PointCoordinate firstPoint, PointCoordinate endPoint) { double lat2 = ConvertToARC(ConvertToDeg(endPoint.Latitide)); double lat1 = ConvertToARC(ConvertToDeg(firstPoint.Latitide)); double lon2 = ConvertToARC(ConvertToDeg(endPoint.Longitude)); double lon1 = ConvertToARC(ConvertToDeg(firstPoint.Longitude)); double dLon = lon2 - lon1; double y = Math.Sin(dLon) * Math.Cos(lat2); double x = Math.Cos(lat1) * Math.Sin(lat2) - Math.Sin(lat1) * Math.Cos(lat2) * Math.Cos(dLon); double angle = Math.Atan2(y, x); angle = (angle + Math.PI * 2) % (Math.PI * 2); return(ConvertToDMS(ConvertToDegree(angle))); /* * * lat1 = lat1.toRad(); lat2 = lat2.toRad(); * var dLon = (lon2-lon1).toRad(); * * var y = Math.sin(dLon) * Math.cos(lat2); * var x = Math.cos(lat1)*Math.sin(lat2) - * Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon); * return Math.atan2(y, x).toBrng(); */ }
/// <summary> /// 计算两点距离 /// </summary> /// <param name="firstPoint"></param> /// <param name="endPoint"></param> /// <returns></returns> public static double CalculateDistance(PointCoordinate firstPoint, PointCoordinate endPoint) { double lat2 = ConvertToARC(ConvertToDeg(endPoint.Latitide)); double lat1 = ConvertToARC(ConvertToDeg(firstPoint.Latitide)); double lon2 = ConvertToARC(ConvertToDeg(endPoint.Longitude)); double lon1 = ConvertToARC(ConvertToDeg(firstPoint.Longitude)); double dLat = lat2 - lat1; double dLon = lon2 - lon1; double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2); double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); return(R * c); /* * var R = 6371; // earth's mean radius in km * var dLat = (lat2-lat1).toRad(); * var dLon = (lon2-lon1).toRad(); * lat1 = lat1.toRad(), lat2 = lat2.toRad(); * * var a = Math.sin(dLat/2) * Math.sin(dLat/2) + * Math.cos(lat1) * Math.cos(lat2) * * Math.sin(dLon/2) * Math.sin(dLon/2); * var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); * var d = R * c; * return d; * } * */ }
/// <summary> /// 计算两点的角度。 /// </summary> /// <param name="firstPoint"></param> /// <param name="endPoint"></param> /// <returns>返回60进制的度分秒角度 </returns> public static double CalculateAngle(PointCoordinate firstPoint, PointCoordinate endPoint) { double lat2 = GreatCircleArgorithm.ConvertToDeg(endPoint.Latitide); double lon2 = GreatCircleArgorithm.ConvertToDeg(endPoint.Longitude); double lat1 = GreatCircleArgorithm.ConvertToDeg(firstPoint.Latitide); double lon1 = GreatCircleArgorithm.ConvertToDeg(firstPoint.Longitude); double dLon = GreatCircleArgorithm.ConvertToARC((lon2 - lon1)); double dPhi = Math.Log(Math.Tan(GreatCircleArgorithm.ConvertToARC(lat2) / 2 + Math.PI / 4) / Math.Tan(GreatCircleArgorithm.ConvertToARC(lat1) / 2 + Math.PI / 4)); if (Math.Abs(dLon) > Math.PI) { dLon = dLon > 0 ? -(2 * Math.PI - dLon) : (2 * Math.PI + dLon); } double angle = Math.Atan2(dLon, dPhi); return(GreatCircleArgorithm.ConvertToDMS((GreatCircleArgorithm.ConvertToDegree(angle) + 360) % 360)); }
/// <summary> /// 计算两点间距离。 /// see http://williams.best.vwh.net/avform.htm#Rhumb /// </summary> /// <param name="firstPoint"></param> /// <param name="endPoint"></param> /// <returns></returns> public static double CalculateDistance(PointCoordinate firstPoint, PointCoordinate endPoint) { double R = 6371; double lat2 = GreatCircleArgorithm.ConvertToDeg(endPoint.Latitide); double lon2 = GreatCircleArgorithm.ConvertToDeg(endPoint.Longitude); double lat1 = GreatCircleArgorithm.ConvertToDeg(firstPoint.Latitide); double lon1 = GreatCircleArgorithm.ConvertToDeg(firstPoint.Longitude); double dLat = GreatCircleArgorithm.ConvertToARC(lat2 - lat1); double dLon = Math.Abs(GreatCircleArgorithm.ConvertToARC(lon2 - lon1)); double dPhi = Math.Log(Math.Tan(GreatCircleArgorithm.ConvertToARC(lat2) / 2 + Math.PI / 4) / Math.Tan(GreatCircleArgorithm.ConvertToARC(lat1) / 2 + Math.PI / 4)); double q = (Math.Abs(dLat) > 0.00000001) ? dLat / dPhi : Math.Cos(GreatCircleArgorithm.ConvertToARC(lat1)); if (dLon > Math.PI) { dLon = 2 * Math.PI - dLon; } double d = Math.Sqrt(dLat * dLat + q * q * dLon * dLon); return(d * R); }
/// <summary> /// 根据两点计算坐标。 /// 已经两点坐标,已知未知点到2点的方位角 /// </summary> /// <param name="point1">第一点坐标</param> /// <param name="point2">第二点坐标</param> ///<param name="angle1">到第一点的方位角</param> /// <param name="angle2">到第二点的方位角</param> /// <returns>坐标</returns> public static PointCoordinate CalcuateCoordinate(PointCoordinate point1, double angle1, PointCoordinate point2, double angle2) { PointCoordinate p = new PointCoordinate(); //这个算法东经是负,西经是正,需要转换 double lat1 = ConvertToARC(ConvertToDeg(point1.Latitide)); double lon1 = ConvertToARC(ConvertToDeg(-point1.Longitude)); double lat2 = ConvertToARC(ConvertToDeg(point2.Latitide)); double lon2 = ConvertToARC(ConvertToDeg(-point2.Longitude)); PointCoordinate tempPoint1 = CalcuateCoordinate(point1, angle1, 20000); //第一点方向上的临时点 PointCoordinate tempPoint2 = CalcuateCoordinate(point2, angle2, 20000); //第二点方向上的临时点 angle1 = ConvertToARC(ConvertToDeg(angle1)); angle2 = ConvertToARC(ConvertToDeg(angle2)); double d = Math.PI / 2; double lat1_1 = Math.Asin(sin(lat1) * cos(d) + cos(lat1) * sin(d) * cos(angle1)); double lon1_1 = Math.Atan2(sin(angle1) * sin(d) * cos(lat1), cos(d) - sin(lat1) * sin(lat1_1)); lon1_1 = Modlon(lon1 - lon1_1); double lat2_1 = Math.Asin(sin(lat2) * cos(d) + cos(lat2) * sin(d) * cos(angle2)); double lon2_1 = Math.Atan2(sin(angle2) * sin(d) * cos(lat2), cos(d) - sin(lat2) * sin(lat2_1)); lon2_1 = Modlon(lon2 - lon2_1); double a1 = sin(lat1 - lat1_1) * sin((lon1 + lon1_1) / 2) * cos((lon1 - lon1_1) / 2) - sin(lat1 + lat1_1) * cos((lon1 + lon1_1) / 2) * sin((lon1 - lon1_1) / 2); double b1 = sin(lat1 - lat1_1) * cos((lon1 + lon1_1) / 2) * cos((lon1 - lon1_1) / 2) + sin(lat1 + lat1_1) * sin((lon1 + lon1_1) / 2) * sin((lon1 - lon1_1) / 2); double c1 = cos(lat1) * cos(lat1_1) * sin(lon1 - lon1_1); double a2 = sin(lat2 - lat2_1) * sin((lon2 + lon2_1) / 2) * cos((lon2 - lon2_1) / 2) - sin(lat2 + lat2_1) * cos((lon2 + lon2_1) / 2) * sin((lon2 - lon2_1) / 2); double b2 = sin(lat2 - lat2_1) * cos((lon2 + lon2_1) / 2) * cos((lon2 - lon2_1) / 2) + sin(lat2 + lat2_1) * sin((lon2 + lon2_1) / 2) * sin((lon2 - lon2_1) / 2); double c2 = cos(lat2) * cos(lat2_1) * sin(lon2 - lon2_1); double A = b1 * c2 - c1 * b2; //v1(2) * v2(3) - v1(3) * v2(2) double B = c1 * a2 - a1 * c2; //v1(3) * v2(1) - v1(1) * v2(3) double C = a1 * b2 - b1 * a2; //v1(1) * v2(2) - v1(2) * v2(1)) double Lat01 = Math.Atan2(C, Math.Sqrt(A * A + B * B)); double Lon01 = Math.Atan2(-B, A); PointCoordinate r1 = new PointCoordinate(); r1.Latitide = ConvertToDMS(ConvertToDegree(Lat01)); r1.Longitude = -ConvertToDMS(ConvertToDegree(Lon01)); PointCoordinate r2 = new PointCoordinate(); r2.Latitide = ConvertToDMS(ConvertToDegree(-Lat01)); r2.Longitude = -ConvertToDMS(ConvertToDegree(Modlon(Lon01 + Math.PI))); //有两点,只用最近的点。 double ta = CalculateDistance(r1, point1); //double ta1 = CalculateAngle(r2, point1); //mqg于20110831增加,应该用计算距离的方法 double ta1 = CalculateDistance(r2, point1); if (ta > ta1) { return(r2); } else { return(r1); } }
/// <summary> /// /// </summary> /// <param name="point1"></param> /// <param name="point2"></param> /// <param name="distance">到Point1的距离</param> /// <param name="angle">到Point2的角度</param> /// <returns></returns> public static List <PointCoordinate> CalcuateCoordinate(PointCoordinate point1, PointCoordinate point2, double distance, double angle) { //根据算法描述,Point1为D点,Point2为A点,未知点为B点 List <PointCoordinate> points = new List <PointCoordinate>(); double b = CalculateDistance(point1, point2) / R; //先计算出两点距离 double crs12 = CalculateAngle(point2, point1); //求出两点的方位角 double crs_AB = ConvertToARC(ConvertToDeg(angle)); double crs_AD = ConvertToARC(ConvertToDeg(crs12)); //A点的夹角 double A = (crs_AD - crs_AB + Math.PI) % (Math.PI * 2) - Math.PI; double r = Math.Sqrt((Math.Cos(b) * Math.Cos(b) + Math.Sin(b) * Math.Sin(b) * Math.Cos(A) * Math.Cos(A))); double p = Math.Atan2(Math.Sin(b) * Math.Cos(A), Math.Cos(b)); double d = distance / R; if (Math.Cos(d) * Math.Cos(d) > r * r) { // points.Add(CalcuateCoordinate(point2, angle, p * R)); throw new Exception("要计算的点不存在"); } else { double dp = p + Math.Acos(Math.Cos(d) / r); if (dp > 0) { points.Add(CalcuateCoordinate(point2, angle, dp * R)); } dp = p - Math.Acos(Math.Cos(d) / r); if (dp > 0) { points.Add(CalcuateCoordinate(point2, angle, dp * R)); } } //foreach (PointCoordinate pp in points) //{ // double kkk = CalculateDistance(pp, point1); // double aaa = CalculateAngle(point2, pp); //} if (points.Count == 0) { throw new Exception("要计算的点不存在!"); } return(points); /* * * Let points A and B define a great circle route and D be a third point. Find the points on the great circle through A and B that lie a distance d from D, if they exist. * * A = crs_AD - crs_AB * * ( crs_AB and crs_AD are the initial GC bearings from A to B and D, respectively. Compute using Course between points) * * b = dist_AD * * (dist_AD is the distance from A to D. Compute using Distance between points) * * r=(cos(b)^2+sin(b)^2*cos(A)^2)^(1/2) * * (acos(r) is the XTD) * * p=atan2(sin(b)*cos(A),cos(b)) * * (p is the ATD) * * IF (cos(d)^2 > r^2) THEN * No points exist * ELSE * Two points exist * dp = p +- acos(cos(d)/r) * ENDIF * * dp are the distances of the desired points from A along AB. Their lat/lons can be computed using Lat/lon given radial and distance */ }