Skip to content

Instantly share code, notes, and snippets.

@Tristramg
Created February 20, 2019 09:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tristramg/d8c57a5b099ecb53260078908ce8feed to your computer and use it in GitHub Desktop.
Save Tristramg/d8c57a5b099ecb53260078908ce8feed to your computer and use it in GitHub Desktop.
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