2015年10月8日木曜日

Swift2で二地点の緯度・経度からその距離を計算するには?

二地点の緯度・経度からその距離を計算する(日本は山だらけ〜)

のJava版をSwift2に移植しました。数学は分かりません。理論も分かりません。でもSwiftとJavaは分かるので移植はできるのです(^^);

オリジナルがMITライセンスなので、このコードもリスペクトを込めてMITライセンスとします。


//
//  GeoUtil.swift
//

import Foundation


/**
*  二地点の緯度・経度からその距離を計算する(日本は山だらけ〜) - http://yamadarake.jp/trdi/report000001.html
*/
@objc(GeoUtil) class GeoUtil: NSObject {
    
    
    static let BESSEL_A: Double = 6377397.155;
    static let BESSEL_E2: Double = 0.00667436061028297;
    static let BESSEL_MNUM: Double = 6334832.10663254;
    
    static let GRS80_A: Double = 6378137.000;
    static let GRS80_E2: Double = 0.00669438002301188;
    static let GRS80_MNUM: Double = 6335439.32708317;
    
    static let WGS84_A: Double = 6378137.000;
    static let WGS84_E2: Double = 0.00669437999019758;
    static let WGS84_MNUM: Double = 6335439.32729246;
    
    static let BESSEL: Int = 0;
    static let GRS80: Int = 1;
    static let WGS84: Int = 2;
    
    
    static func deg2rad(deg: Double) -> Double {
        return deg * M_PI / 180.0;
    }
    
    
    static func calcDistHubeny(lat1: Double, lng1: Double, lat2: Double, lng2: Double, a: Double, e2: Double, mnum: Double) -> Double {
        
        let my: Double = deg2rad((lat1 + lat2) / 2.0);
        let dy: Double = deg2rad(lat1 - lat2);
        let dx: Double = deg2rad(lng1 - lng2);
        
        let sinVal: Double = sin(my);
        let w: Double = sqrt(1.0 - e2 * sinVal * sinVal);
        let m: Double = mnum / (w * w * w);
        let n: Double = a / w;
        
        let dym: Double = dy * m;
        let dxncos: Double = dx * n * cos(my);
        
        return sqrt(dym * dym + dxncos * dxncos);
        
    }
    
    
    static func calcDistHubeny(lat1: Double, lng1: Double, lat2: Double, lng2: Double) -> Double {
        return calcDistHubeny(lat1, lng1: lng1, lat2: lat2, lng2: lng2, a: GRS80_A, e2: GRS80_E2, mnum: GRS80_MNUM);
    }
    
    
    static func calcDistHubery(lat1: Double, lng1: Double, lat2: Double, lng2: Double, type: Int) -> Double {
        switch(type) {
        case BESSEL:
            return calcDistHubeny(lat1, lng1: lng1, lat2: lat2, lng2: lng2, a: BESSEL_A, e2: BESSEL_E2, mnum: BESSEL_MNUM);
        case WGS84:
            return calcDistHubeny(lat1, lng1: lng1, lat2: lat2, lng2: lng2, a: WGS84_A, e2: WGS84_E2, mnum: WGS84_MNUM);
        default:
            return calcDistHubeny(lat1, lng1: lng1, lat2: lat2, lng2: lng2, a: GRS80_A, e2: GRS80_E2, mnum: GRS80_MNUM);
        }
    }
    
    
}