1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use num::Float;
use types::{Point, LineString};
use algorithm::distance::Distance;
fn point_line_distance<T>(point: &Point<T>, start: &Point<T>, end: &Point<T>) -> T
where T: Float
{
if start == end {
point.distance(start)
} else {
let numerator = ((end.x() - start.x()) * (start.y() - point.y()) -
(start.x() - point.x()) * (end.y() - start.y()))
.abs();
let denominator = start.distance(end);
numerator / denominator
}
}
fn rdp<T>(points: &[Point<T>], epsilon: &T) -> Vec<Point<T>>
where T: Float
{
if points.is_empty() {
return points.to_vec();
}
let mut dmax = T::zero();
let mut index: usize = 0;
let mut distance: T;
for (i, _) in points.iter().enumerate().take(points.len() - 1).skip(1) {
distance = point_line_distance(&points[i],
&points[0],
&*points.last().unwrap());
if distance > dmax {
index = i;
dmax = distance;
}
}
if dmax > *epsilon {
let mut intermediate = rdp(&points[..index + 1], &*epsilon);
intermediate.pop();
intermediate.extend_from_slice(&rdp(&points[index..], &*epsilon));
intermediate
} else {
vec![*points.first().unwrap(), *points.last().unwrap()]
}
}
pub trait Simplify<T, Epsilon = T> {
fn simplify(&self, epsilon: &T) -> Self where T: Float;
}
impl<T> Simplify<T> for LineString<T>
where T: Float
{
fn simplify(&self, epsilon: &T) -> LineString<T> {
LineString(rdp(&self.0, epsilon))
}
}
#[cfg(test)]
mod test {
use types::{Point};
use super::{point_line_distance, rdp};
use test_helpers::within_epsilon;
#[test]
fn perpdistance_test() {
let start = Point::new(1.0, 2.0);
let end = Point::new(3.0, 4.0);
let p = Point::new(1.0, 1.0);
let dist = point_line_distance(&p, &start, &end);
assert!(within_epsilon(dist, 0.7071067811865475, 1.0e-15));
}
#[test]
fn rdp_test() {
let mut vec = Vec::new();
vec.push(Point::new(0.0, 0.0));
vec.push(Point::new(5.0, 4.0));
vec.push(Point::new(11.0, 5.5));
vec.push(Point::new(17.3, 3.2));
vec.push(Point::new(27.8, 0.1));
let mut compare = Vec::new();
compare.push(Point::new(0.0, 0.0));
compare.push(Point::new(5.0, 4.0));
compare.push(Point::new(11.0, 5.5));
compare.push(Point::new(27.8, 0.1));
let simplified = rdp(&vec, &1.0);
assert_eq!(simplified, compare);
}
#[test]
fn rdp_test_empty_linestring() {
let vec = Vec::new();
let compare = Vec::new();
let simplified = rdp(&vec, &1.0);
assert_eq!(simplified, compare);
}
#[test]
fn rdp_test_two_point_linestring() {
let mut vec = Vec::new();
vec.push(Point::new(0.0, 0.0));
vec.push(Point::new(27.8, 0.1));
let mut compare = Vec::new();
compare.push(Point::new(0.0, 0.0));
compare.push(Point::new(27.8, 0.1));
let simplified = rdp(&vec, &1.0);
assert_eq!(simplified, compare);
}
}