2012-05-11 4 views
18

MKMapViewの位置の中間点を決定しようとしています。 here(およびhere)の概要を説明し、Objective-Cで書き直しましたが、マップはバッフィン島の北東のどこかに集中しています。 2つのパラメータは、以下のデータを持っている2つのクワリジネート間の中点を決定する

+(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; 
} 

:上記のリンクJavaメソッドに基づいて

私の方法

_loc1: 
    latitude = 45.4959839 
    longitude = -73.67826455 

_loc2: 
    latitude = 45.482889 
    longitude = -73.57522299 

上記が正しく(モントリオールとその周辺)地図上置きされています。私は2の間の中間点にマップを中央にしようとしています、まだ私の方法は、以下を返す:

北極ではどこか、それは約500マイル南でなければなりません
latitude = 65.29055 
longitude = -82.55425 

答えて

11

私はあなたの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に変更すると、少しお役に立てます。

+0

はい...そうでしょう。 –

-4

あなたは少し考えていると思います。ちょうど:

float lon3 = ((lon1 + lon2)/2) 
float lat3 = ((lat1 + lat2)/2) 

lat3とlon3が中心点になります。

+10

地球は平坦ではありません。そのため、開発者はしばしばこのような単純なアルゴリズムを使いたくないのです。 – Nate

+7

^^^ Heretic !!!!!!!!! – wbarksdale

8

誰かがスウィフトのコードを必要とする場合、私は、複数の座標間の中間点を計算するスウィフトにライブラリ関数を書かれている:

//  /** 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 

} 

詳細な回答は迅速ユーザーの場合here

4

を見つけることができる、バリアントを修正as @dinjas suggest

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 
    } 
} 
+1

おかげさま - でも、これは主子午線を横切るかもしれないという事実を説明していますか? – Fattie

関連する問題