为什么我的叠加线没有产生我在基于极坐标公式 (swift、ios) 的地图中所期望的结果?
Why is the my overlay line not resulting how I expect in the map based on a polar formulae (swift, ios)?
我的目标
根据三位数据绘制一条线:给定坐标、距离、方位角。
我想从我的当前位置沿方位角方向在距离的终点绘制一条线。
切记
我确实在地图上找到了一条线,每次当前位置都会更新,所以在这个意义上没有问题(我显示的代码可能不包括所有定义 - 但假设没有编译错误等)
问题
我的线出现了,但总是在同一个方向,在整个世界的距离(而不是 1 公里!)。我尝试更改标题输入但仍然得到相同的行。
代码
func drawHeadingLine(currentLocation: [Double], heading: Double){
//to radians
let headingR = heading * 0.0174533;
if viewLine != nil{
mapView.removeOverlay(viewLine);
}
// setup data for polar formulae
let pi = M_PI;
let currentLONG = currentLocation[0];
let currentLAT = currentLocation[1];
let currentLongRadian = currentLocation[0] * (pi * 180);
let currentLatRadian = currentLocation[1] * (pi * 180);
let lineDistance: Double = 1; //km
let earthRadius: Double = 6378.1; //km
let angularDistance: Double = lineDistance / earthRadius;
//use polar formulae (given point, distance, bearing) for line end point
let latitude2 = asin( sin(currentLatRadian) * cos(angularDistance)
+ cos(currentLatRadian) * sin(angularDistance) * cos(headingR) );
let longitude2 = currentLongRadian + atan2( cos(angularDistance) - sin(currentLatRadian) * sin(latitude2),
sin(headingR) * sin(angularDistance) * cos(currentLatRadian));
var coordinates1 = CLLocationCoordinate2D();
coordinates1.longitude = currentLONG;
coordinates1.latitude = currentLAT;
var coordinates2 = CLLocationCoordinate2D();
coordinates2.longitude = longitude2;
coordinates2.latitude = latitude2;
var lineCoords = [ coordinates1,coordinates2];
viewLine = MKPolyline(coordinates: &lineCoords, count: lineCoords.count);
self.mapView.addOverlay(viewLine);
}
func mapView(mapView: MKMapView!, viewForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
if (overlay is MKPolyline) {
viewLine = overlay;
let line = MKPolylineRenderer(overlay: viewLine);
line.strokeColor = UIColor.redColor().colorWithAlphaComponent(0.5);
line.lineWidth = 5;
return line;
}
return nil
}
请说明您是否需要更多信息。感谢您的帮助。
你的数学有问题。试试这个:
func drawHeadingLine(currentLocation: [Double], heading: Double){
if viewLine != nil {
mapView.removeOverlay(viewLine!)
}
let (lat, long) = (currentLocation[0], currentLocation[1])
let headingR = heading * M_PI / 180.0
let lineDistance = 1.0 //km
let latDelta = cos(headingR) * lineDistance / EarthMeasurement.lengthOfLatitude(at: lat)
let longDelta = sin(headingR) * lineDistance / EarthMeasurement.lengthOfLongitude(at: lat)
let pointA = CLLocationCoordinate2D(latitude: lat, longitude: long)
let pointB = CLLocationCoordinate2D(latitude: lat + latDelta, longitude: long + longDelta)
// For debugging, let's calculate a geodesic distance between these 2 points
// Results are in meters
let locationA = CLLocation(latitude: lat, longitude: long)
let locationB = CLLocation(latitude: lat + latDelta, longitude: long + longDelta)
print("heading = \(heading), distance = \(locationA.distanceFromLocation(locationB)")
var coordinates = [pointA, pointB]
let polyline = MKPolyline(coordinates: &coordinates, count: 2)
self.mapView.addOverlay(polyline)
}
和 EarthMeasurement
class:
final class EarthMeasurement {
static func lengthOfLatitude(at latitude: Double) -> Double {
return 110.574
}
static func lengthOfLongitude(at latitude: Double) -> Double {
let latitudeR = latitude * M_PI / 180.0
return cos(latitudeR) * 111.320
}
}
思路是Map Kit处理的是纬度和经度,而不是公里,所以我们需要知道纬度/经度有多少公里。这远非简单,因为地球不是一个完美的球体。但我们可以做出近似值:
- 当您靠近两极时,1 度纬度的长度确实会变长,但差异很小:赤道和两极之间大约相差 1 公里(或 1%)。我们可以忽略它并使用赤道的长度,根据 Wikipedia 是 111.574km。
- 1纬度的长度公式取自this question.
由于我们使用的是近似值,因此这不会给出恰好 1 公里远的点。误差在赤道附近的纬度较小,并且随着您接近两极(~10m)而逐渐增加。如果您想要更准确的结果,请相应地调整 EarthMeasurement
class。
我的目标
根据三位数据绘制一条线:给定坐标、距离、方位角。
我想从我的当前位置沿方位角方向在距离的终点绘制一条线。
切记
我确实在地图上找到了一条线,每次当前位置都会更新,所以在这个意义上没有问题(我显示的代码可能不包括所有定义 - 但假设没有编译错误等)
问题
我的线出现了,但总是在同一个方向,在整个世界的距离(而不是 1 公里!)。我尝试更改标题输入但仍然得到相同的行。
代码
func drawHeadingLine(currentLocation: [Double], heading: Double){
//to radians
let headingR = heading * 0.0174533;
if viewLine != nil{
mapView.removeOverlay(viewLine);
}
// setup data for polar formulae
let pi = M_PI;
let currentLONG = currentLocation[0];
let currentLAT = currentLocation[1];
let currentLongRadian = currentLocation[0] * (pi * 180);
let currentLatRadian = currentLocation[1] * (pi * 180);
let lineDistance: Double = 1; //km
let earthRadius: Double = 6378.1; //km
let angularDistance: Double = lineDistance / earthRadius;
//use polar formulae (given point, distance, bearing) for line end point
let latitude2 = asin( sin(currentLatRadian) * cos(angularDistance)
+ cos(currentLatRadian) * sin(angularDistance) * cos(headingR) );
let longitude2 = currentLongRadian + atan2( cos(angularDistance) - sin(currentLatRadian) * sin(latitude2),
sin(headingR) * sin(angularDistance) * cos(currentLatRadian));
var coordinates1 = CLLocationCoordinate2D();
coordinates1.longitude = currentLONG;
coordinates1.latitude = currentLAT;
var coordinates2 = CLLocationCoordinate2D();
coordinates2.longitude = longitude2;
coordinates2.latitude = latitude2;
var lineCoords = [ coordinates1,coordinates2];
viewLine = MKPolyline(coordinates: &lineCoords, count: lineCoords.count);
self.mapView.addOverlay(viewLine);
}
func mapView(mapView: MKMapView!, viewForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
if (overlay is MKPolyline) {
viewLine = overlay;
let line = MKPolylineRenderer(overlay: viewLine);
line.strokeColor = UIColor.redColor().colorWithAlphaComponent(0.5);
line.lineWidth = 5;
return line;
}
return nil
}
你的数学有问题。试试这个:
func drawHeadingLine(currentLocation: [Double], heading: Double){
if viewLine != nil {
mapView.removeOverlay(viewLine!)
}
let (lat, long) = (currentLocation[0], currentLocation[1])
let headingR = heading * M_PI / 180.0
let lineDistance = 1.0 //km
let latDelta = cos(headingR) * lineDistance / EarthMeasurement.lengthOfLatitude(at: lat)
let longDelta = sin(headingR) * lineDistance / EarthMeasurement.lengthOfLongitude(at: lat)
let pointA = CLLocationCoordinate2D(latitude: lat, longitude: long)
let pointB = CLLocationCoordinate2D(latitude: lat + latDelta, longitude: long + longDelta)
// For debugging, let's calculate a geodesic distance between these 2 points
// Results are in meters
let locationA = CLLocation(latitude: lat, longitude: long)
let locationB = CLLocation(latitude: lat + latDelta, longitude: long + longDelta)
print("heading = \(heading), distance = \(locationA.distanceFromLocation(locationB)")
var coordinates = [pointA, pointB]
let polyline = MKPolyline(coordinates: &coordinates, count: 2)
self.mapView.addOverlay(polyline)
}
和 EarthMeasurement
class:
final class EarthMeasurement {
static func lengthOfLatitude(at latitude: Double) -> Double {
return 110.574
}
static func lengthOfLongitude(at latitude: Double) -> Double {
let latitudeR = latitude * M_PI / 180.0
return cos(latitudeR) * 111.320
}
}
思路是Map Kit处理的是纬度和经度,而不是公里,所以我们需要知道纬度/经度有多少公里。这远非简单,因为地球不是一个完美的球体。但我们可以做出近似值:
- 当您靠近两极时,1 度纬度的长度确实会变长,但差异很小:赤道和两极之间大约相差 1 公里(或 1%)。我们可以忽略它并使用赤道的长度,根据 Wikipedia 是 111.574km。
- 1纬度的长度公式取自this question.
由于我们使用的是近似值,因此这不会给出恰好 1 公里远的点。误差在赤道附近的纬度较小,并且随着您接近两极(~10m)而逐渐增加。如果您想要更准确的结果,请相应地调整 EarthMeasurement
class。