LoginSignup
0
0

More than 3 years have passed since last update.

【Rust】緯度経度のcsvデータを読み込んで2点間の距離を求める

Last updated at Posted at 2020-06-29

背景

500点くらいの位置情報がcsvデータにまとめられていて、その全ての組み合わせについて直線距離(km) を求めたい.

緯度経度から距離を求める

以下の記事を参考にさせていただきました.

pub fn cal_rho(lat_a: &f64, lon_a: &f64, lat_b: &f64, lon_b: &f64) -> f64 {
    const RA: f64 = 6378.140; // equatorial radius (km)
    const RB: f64 = 6356.755; // polar radius (km)
    let f: f64;
    let rad_lat_a: f64;
    let rad_lon_a: f64;
    let rad_lat_b: f64;
    let rad_lon_b: f64;
    let pa: f64;
    let pb: f64;
    let xx: f64;
    let c1: f64;
    let c2: f64;
    let dr: f64;
    let rho: f64;

    f = (RA - RB) / RA;
    rad_lat_a = lat_a.to_radians();
    rad_lon_a = lon_a.to_radians();
    rad_lat_b = lat_b.to_radians();
    rad_lon_b = lon_b.to_radians();
    pa = (RB / RA * rad_lat_a.tan()).atan();
    pb = (RB / RA * rad_lat_b.tan()).atan();
    xx = (pa.sin() * pb.sin() + pa.cos() * pb.cos() * (rad_lon_a - rad_lon_b).cos()).acos();
    c1 = ((xx.sin() - xx) * (pa.sin() + pb.sin())).powf(2.0) / ((xx / 2.0).cos()).powf(2.0);
    c2 = ((xx.sin() + xx) * (pa.sin() - pb.sin())).powf(2.0) / ((xx / 2.0).sin()).powf(2.0);
    dr = f / 8.0 * (c1 - c2);
    rho = RA * (xx + dr);
    rho
}

csvの読み込み -> 距離の計算

rdr.records() で取得できる StringRecordsIter を使ってネストのループを作ろうと思ったが、うまく行かなかった.
そのため Iter -> Vec に変換して対応した.

extern crate csv;
use csv::StringRecord;
use std::env;
use std::error::Error;
use std::ffi::OsString;
use std::fs::File;

pub fn run() -> Result<(), Box<Error>> {
    let file_path = "file.csv";
    let file = File::open(file_path)?;
    let mut rdr = csv::Reader::from_reader(file);
    let _records = rdr.records();
    let records: Vec<StringRecord> = _records.map(|x| x.unwrap()).collect();
    let data_len = &records.len();

    for i in 0..*data_len {
        for j in 0..*data_len {
            let r_i = &records[i];
            let lat_i = &r_i[1];
            let lat_i: f64 = lat_i.parse().unwrap();
            let lng_i = &r_i[2];
            let lng_i: f64 = lng_i.parse().unwrap();
            let r_j = &records[j];
            let lat_j = &r_j[1];
            let lat_j: f64 = lat_j.parse().unwrap();
            let lng_j = &r_j[2];
            let lng_j: f64 = lng_j.parse().unwrap();

            let dist = cal_rho(&lat_i, &lng_i, &lat_j, &lng_j);

            println!("{}", dist);
        }
    }
    Ok(())
}

手探りの実装ですので、良い方法あればアドバイスお待ちしています。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0