Определение средней точки между двумя координатами
Я пытаюсь определить среднюю точку между двумя точками в MKMapView
. Я следую методу, описанному здесь (и здесь), и переписал его в Objective-C, но карта центрирована где-то к северо-востоку от острова Баффина, где нет места рядом с двумя точками.
Мой метод основан на Java-методе, указанном выше:
+(CLLocationCoordinate2D)findCenterPoint:(CLLocationCoordinate2D)_lo1 :(CLLocationCoordinate2D)_loc2 {
CLLocationCoordinate2D center;
double lon1 = _lo1.longitude * M_PI / 180;
double lon2 = _loc2.longitude * M_PI / 100;
double lat1 = _lo1.latitude * M_PI / 180;
double lat2 = _loc2.latitude * M_PI / 100;
double dLon = lon2 - lon1;
double x = cos(lat2) * cos(dLon);
double y = cos(lat2) * sin(dLon);
double lat3 = atan2( sin(lat1) + sin(lat2), sqrt((cos(lat1) + x) * (cos(lat1) + x) + y * y) );
double lon3 = lon1 + atan2(y, cos(lat1) + x);
center.latitude = lat3 * 180 / M_PI;
center.longitude = lon3 * 180 / M_PI;
return center;
}
2 параметра имеют следующие данные:
_loc1:
latitude = 45.4959839
longitude = -73.67826455
_loc2:
latitude = 45.482889
longitude = -73.57522299
Вышеуказанное правильно размещено на карте (в Монреале и его окрестностях). Я пытаюсь центрировать карту в средней точке между двумя, но мой метод возвращает следующее:
latitude = 65.29055
longitude = -82.55425
который где-то в Арктике, когда он должен быть около 500 миль на юг.
Ответы
Ответ 1
Просто догадка, но я заметил, что ваши переменные lon2
и lat2
вычисляются с помощью M_PI/100
а не M_PI/180
.
double lon1 = _lo1.longitude * M_PI / 180;
double lon2 = _loc2.longitude * M_PI / 100;
double lat1 = _lo1.latitude * M_PI / 180;
double lat2 = _loc2.latitude * M_PI / 100;
Изменение их на 180 может немного помочь.
Ответ 2
Если кому-то нужен код в Swift, я написал библиотечную функцию в Swift для вычисления средней точки между координатами MULTIPLE:
// /** Degrees to Radian **/
class func degreeToRadian(angle:CLLocationDegrees) -> CGFloat {
return ( (CGFloat(angle)) / 180.0 * CGFloat(M_PI) )
}
// /** Radians to Degrees **/
class func radianToDegree(radian:CGFloat) -> CLLocationDegrees {
return CLLocationDegrees( radian * CGFloat(180.0 / M_PI) )
}
class func middlePointOfListMarkers(listCoords: [CLLocationCoordinate2D]) -> CLLocationCoordinate2D {
var x = 0.0 as CGFloat
var y = 0.0 as CGFloat
var z = 0.0 as CGFloat
for coordinate in listCoords{
var lat:CGFloat = degreeToRadian(coordinate.latitude)
var lon:CGFloat = degreeToRadian(coordinate.longitude)
x = x + cos(lat) * cos(lon)
y = y + cos(lat) * sin(lon)
z = z + sin(lat)
}
x = x/CGFloat(listCoords.count)
y = y/CGFloat(listCoords.count)
z = z/CGFloat(listCoords.count)
var resultLon: CGFloat = atan2(y, x)
var resultHyp: CGFloat = sqrt(x*x+y*y)
var resultLat:CGFloat = atan2(z, resultHyp)
var newLat = radianToDegree(resultLat)
var newLon = radianToDegree(resultLon)
var result:CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: newLat, longitude: newLon)
return result
}
Подробный ответ можно найти здесь
Ответ 3
Для быстрых пользователей исправленный вариант как @dinjas предлагает
import Foundation
import MapKit
extension CLLocationCoordinate2D {
// MARK: CLLocationCoordinate2D+MidPoint
func middleLocationWith(location:CLLocationCoordinate2D) -> CLLocationCoordinate2D {
let lon1 = longitude * M_PI / 180
let lon2 = location.longitude * M_PI / 180
let lat1 = latitude * M_PI / 180
let lat2 = location.latitude * M_PI / 180
let dLon = lon2 - lon1
let x = cos(lat2) * cos(dLon)
let y = cos(lat2) * sin(dLon)
let lat3 = atan2( sin(lat1) + sin(lat2), sqrt((cos(lat1) + x) * (cos(lat1) + x) + y * y) )
let lon3 = lon1 + atan2(y, cos(lat1) + x)
let center:CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat3 * 180 / M_PI, lon3 * 180 / M_PI)
return center
}
}
Ответ 4
Важно сказать, что формула, используемая ОП для расчета географической средней точки, основана на этой формуле, которая объясняет вычисление cos/sin/sqrt.
Эта формула даст вам географическую среднюю точку для любого большого расстояния, включая четыре четверти и главный меридиан.
Но, если ваш расчет для ближнего расстояния около 1 километра, использование простого среднего даст те же результаты в средней точке. то есть:
let firstPoint = CLLocation(....)
let secondPoint = CLLocation(....)
let midPointLat = (firstPoint.coordinate.latitude + secondPoint.coordinate.latitude) / 2
let midPointLong = (firstPoint.coordinate.longitude + secondPoint.coordinate.longitude) / 2
На самом деле вы можете использовать его на 10 км, но ожидайте отклонение - если вам нужна только оценка для средней точки на коротких дистанциях с быстрым решением, этого будет достаточно.
Ответ 5
Я думаю, ты уже немного об этом думаешь. Просто выполните:
float lon3 = ((lon1 + lon2) / 2)
float lat3 = ((lat1 + lat2) / 2)
lat3 и lon3 будут центральной точкой.