2

私は線形回帰を求めている一連の座標を持っていますので、線の方程式を見つけることができます。だから、座標の集合から線形回帰を求める結果が得られません

enter image description here

51.48163827836369, -0.019464668521006683 
51.481654860705667, -0.019452641350085287 
51.481674140657908, -0.01943882290242982 
51.481690344713748, -0.019423713183982727 
51.481705506128442, -0.019419045258473489 
51.481722553489625, -0.01940979681751287 
51.48173752576799, -0.019412687104136239 
51.48174912673462, -0.019409150632213823 
51.4817646359283, -0.019389300889997685 
51.481779676567427, -0.019388957697628939 
51.481792568262044, -0.019402453532393338 
51.481804168699682, -0.019415663863242116 
51.481822746271966, -0.019423725406568337 
51.481838162880258, -0.019428618620622728 
51.481855587496689, -0.01942372804705883 
51.481867836051975, -0.019430554178484272 
51.481883136496599, -0.019432972610502475 
51.481899505688553, -0.019425501321734373 
51.481914919015246, -0.019424832166464512 
51.481932613348015, -0.019457392982985766 
51.481949346615657, -0.019472056279255412 
51.481968002664601, -0.019458232757642691 
51.481986902059589, -0.019446792660346546 
51.482003086257393, -0.019433403642779012 

darrinward.comを使用してマップにこれを追加し、私は大体北上、このパスを取得:私は、座標のこのセットにスウィフトアルゴリズムクラブからLinear Regression algorithmを使用していますそこから、ベアリングを得るために、私は最初の座標の経度(緯度を得るために)の回帰を取る、:

let regression = linearRegression(longitudes, latitudes) 

    let firstRegressionCoordinate = CLLocationCoordinate2D(latitude: regression(firstCoordinate.longitude), longitude:firstCoordinate.longitude) 
    let lastRegressionCoordinate = CLLocationCoordinate2D(latitude: regression(lastCoordinate.longitude), longitude: lastCoordinate.longitude) 

    return firstRegressionCoordinate.bearing(to: lastRegressionCoordinate) 

私のベアリング機能は正常に動作し、私に156.20969のベアリングを与えます。私が期待しているのは、実際の経路を取ると、0度に近い数値か、360度に近い数値です。

私は問題が線形回帰アルゴリズムやベアリング関数ではないと感じていますが、私の座標ではベアリングを決定するために求めています。私は間違ったことを求めていますか?別のことをしなければならない何か他にはありますか?遊び場で実行することができます

完全なコード、:

import CoreLocation 

public extension FloatingPoint { 
    public var degreesToRadians: Self { return self * .pi/180 } 
    public var radiansToDegrees: Self { return self * 180/.pi } 
} 

extension CLLocationCoordinate2D { 
    ///Returns the initial bearing of travel to another coordinate 
    func bearing(to: CLLocationCoordinate2D) -> CLLocationDegrees { 
     let fromLatRadians = latitude.degreesToRadians 
     let fromLongRadians = longitude.degreesToRadians 

     let toLatRadians = to.latitude.degreesToRadians 
     let toLongRadians = to.longitude.degreesToRadians 

     let y = sin(toLongRadians - fromLongRadians) * cos(toLatRadians) 
     let x = cos(fromLatRadians) * sin(toLatRadians) - sin(fromLatRadians) * cos(toLatRadians) * cos(toLongRadians - fromLongRadians) 

     var bearing = atan2(y, x).radiansToDegrees 

     bearing = (bearing + 360.0).truncatingRemainder(dividingBy: 360.0) 

     return bearing 
    } 
} 

extension Array where Element == CLLocationCoordinate2D { 
    func linearRegressionBearing() -> Double { 
     var longitudes = [CLLocationDegrees]() 
     var latitudes = [CLLocationDegrees]() 

     for coordinate in self { 
      longitudes.append(coordinate.longitude) 
      latitudes.append(coordinate.latitude) 
     } 

     let regression = linearRegression(longitudes, latitudes) 

     let firstCoordinate = CLLocationCoordinate2D(latitude: regression(self.first!.longitude), longitude: self.first!.longitude) 
     let lastCoordinate = CLLocationCoordinate2D(latitude: regression(self.last!.longitude), longitude: self.last!.longitude) 

     return firstCoordinate.bearing(to: lastCoordinate) 
    } 
} 

// A closed form solution 
func average(_ input: [Double]) -> Double { 
    return input.reduce(0, +)/Double(input.count) 
} 

func multiply(_ a: [Double], _ b: [Double]) -> [Double] { 
    return zip(a, b).map(*) 
} 

func linearRegression(_ xs: [Double], _ ys: [Double]) -> (Double) -> Double { 
    let sum1 = average(multiply(xs, ys)) - average(xs) * average(ys) 
    let sum2 = average(multiply(xs, xs)) - pow(average(xs), 2) 
    let slope = sum1/sum2 
    let intercept = average(ys) - slope * average(xs) 
    return { x in intercept + slope * x } 
} 

let coordinates = [ 
    CLLocationCoordinate2D(latitude: 51.48163827836369, longitude: -0.019464668521006683), 
    CLLocationCoordinate2D(latitude: 51.481654860705667, longitude: -0.019452641350085287), 
    CLLocationCoordinate2D(latitude: 51.481674140657908, longitude: -0.01943882290242982), 
    CLLocationCoordinate2D(latitude: 51.481690344713748, longitude: -0.019423713183982727), 
    CLLocationCoordinate2D(latitude: 51.481705506128442, longitude: -0.019419045258473489), 
    CLLocationCoordinate2D(latitude: 51.481722553489625, longitude: -0.01940979681751287), 
    CLLocationCoordinate2D(latitude: 51.48173752576799, longitude: -0.019412687104136239), 
    CLLocationCoordinate2D(latitude: 51.48174912673462, longitude: -0.019409150632213823), 
    CLLocationCoordinate2D(latitude: 51.4817646359283, longitude: -0.019389300889997685), 
    CLLocationCoordinate2D(latitude: 51.481779676567427, longitude: -0.019388957697628939), 
    CLLocationCoordinate2D(latitude: 51.481792568262044, longitude: -0.019402453532393338), 
    CLLocationCoordinate2D(latitude: 51.481804168699682, longitude: -0.019415663863242116), 
    CLLocationCoordinate2D(latitude: 51.481822746271966, longitude: -0.019423725406568337), 
    CLLocationCoordinate2D(latitude: 51.481838162880258, longitude: -0.019428618620622728), 
    CLLocationCoordinate2D(latitude: 51.481855587496689, longitude: -0.01942372804705883), 
    CLLocationCoordinate2D(latitude: 51.481867836051975, longitude: -0.019430554178484272), 
    CLLocationCoordinate2D(latitude: 51.481883136496599, longitude: -0.019432972610502475), 
    CLLocationCoordinate2D(latitude: 51.481899505688553, longitude: -0.019425501321734373), 
    CLLocationCoordinate2D(latitude: 51.481914919015246, longitude: -0.019424832166464512), 
    CLLocationCoordinate2D(latitude: 51.481932613348015, longitude: -0.019457392982985766), 
    CLLocationCoordinate2D(latitude: 51.481949346615657, longitude: -0.019472056279255412), 
    CLLocationCoordinate2D(latitude: 51.481968002664601, longitude: -0.019458232757642691), 
    CLLocationCoordinate2D(latitude: 51.481986902059589, longitude: -0.019446792660346546), 
    CLLocationCoordinate2D(latitude: 51.482003086257393, longitude: -0.019433403642779012) 
] 

coordinates.linearRegressionBearing() 

答えて

2

は、私はあなたの軸受機能が正常に動作することを確認します。しかし、緯度の回帰値は51.45437262420372です。これは、回帰直線が経度= 0.0と交差するところです。私はあなたのマップ領域内のフィット緯度、lon値を計算するために回帰直線の交点と勾配の両方を使用し、それらの値を使って方位を見つける必要があると思います。

後部追加: ここで重要な問題は、経度座標が距離に対して線形ではないことです。経度によってカバーされる距離は緯度によって異なります。私は、最も簡単な解決策は、緯度、経度値の配列をlat、normalisedLon値に変換することです(normalizedLon = lon * cosine(lat))。

これを行うと、最初の座標から最後の座標= 3.055度までのパスの角度(正しいと思われる北の東側)。

これを実行すると、回帰直線の傾きは、実際にあなたが探している方向、つまり見出し= atan(傾き)を表します。

しかし、あなたの回帰コードは私にとってはうまくいかないようです。 3度も非常に近い結果が得られるはずですが、それは邪魔です。

関連する問題