Created
February 20, 2019 09:51
-
-
Save Tristramg/d8c57a5b099ecb53260078908ce8feed to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::f64; | |
#[derive(Clone)] | |
pub struct Point { | |
pub lat: f64, // plutôt y (cf le pâté en bas) | |
pub lon: f64, // plutôt x | |
} | |
// la convention est plutôt d’avoir juste new. Point::new est moins redondant que Point::new_point | |
// Cependant, tout particulièrement dans le cas des coordonnées l’ordre est source de confusion. | |
// Typiquement, tu utilises des coordonnées cartésiennes (distance euclidiennes), pas sphériques) | |
// On s’attendrait donc à saisir (x, y) et non pas (y, x) comme tu l’as fait là | |
// Il vaut donc mieux donc obliger être explicite et donc faire : | |
// Point { lat: 2.0, lon: 1.0} et ne pas avoir de constructeur du tout | |
fn new_point(lat: f64, lon: f64) -> Point { | |
Point { lat, lon } | |
} | |
fn main() { | |
let a = vec![new_point(1.0, 1.0), new_point(2.0, 1.0), new_point(2.0, 2.0)]; | |
let b = vec![new_point(2.0, 2.0), new_point(0.0, 1.0), new_point(2.0, 4.0)]; | |
println!("{}", dist_frechet(&a, &b)); | |
} | |
pub struct Data { | |
cache: Vec<Vec<f64>>, | |
linestring_a: Vec<Point>, | |
linestring_b: Vec<Point>, | |
} | |
impl Data { | |
fn c(&mut self, i: usize, j: usize) -> f64 { | |
if self.cache[i][j] > -1.0 { | |
return self.cache[i][j]; | |
// Essayer de voir si c’est possible à coups de match :) | |
} else if i == 1 && j == 1 { | |
self.cache[i][j] = self.eucl_dist(0, 0) | |
} else if i > 1 && j == 1 { | |
// En fait, à chaque fois, c’est eucl_dist(i,j) qui est appelé | |
// Le mettre en constante en début sera probablement plus lisible | |
// Et évitera d’avoir specifique à Data | |
self.cache[i][j] = self.c(i - 1, 1).max(self.eucl_dist(i, 0)) | |
} else if i == 1 && j > 1 { | |
self.cache[i][j] = self.c(1, j - 1).max(self.eucl_dist(0, j)) | |
} else if i > 1 && j > 1 { | |
self.cache[i][j] = ((self.c(i - 1, j).min(self.c(i - 1, j - 1))).min(self.c(i, j - 1))) | |
.max(self.eucl_dist(i, j)) | |
} else { | |
self.cache[i][j] = f64::INFINITY | |
} | |
return self.cache[i][j]; | |
} | |
fn eucl_dist(&self, i: usize, j: usize) -> f64 { | |
eucl_dist(&self.linestring_a[i], &self.linestring_a[j]) | |
} | |
// Quitte à avoir un constructeur, autant utiliser le constructeur poun initialiser le cache ;) | |
fn new(cache: Vec<Vec<f64>>, linestring_a: Vec<Point>, linestring_b: Vec<Point>) -> Self { | |
Data { | |
cache, | |
linestring_a, | |
linestring_b, | |
} | |
} | |
} | |
fn dist_frechet(p: &Vec<Point>, q: &Vec<Point>) -> f64 { | |
let mut d = Data::new(vec![vec![-1.; q.len()]; p.len()], p.to_vec(), q.to_vec()); | |
// Pas besoin de définir une constante pour la retourner immédiatement, autant retourner directement le résultat | |
let dist = d.c(p.len()-1, q.len()-1); | |
dist | |
} | |
fn eucl_dist(p: &Point, q: &Point) -> f64 { | |
((p.lat - q.lat).powi(2) + (p.lon - q.lon).powi(2)).sqrt() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment