-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy paththin.r
47 lines (43 loc) · 1.4 KB
/
thin.r
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
# Implementation of the Douglas-Peucker algorithm for line thinning
# http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
simplify_rec <- function(points, tol = 0.01) {
n <- nrow(points)
if (n <= 2) return() # c(1, n))
dist <- with(points, point_line_dist(x, y, x[1], y[1], x[n], y[n]))
if (max(dist, na.rm = T) > tol) {
furthest <- which.max(dist)
c(
simplify_rec(points[1:(furthest - 1), ], tol),
furthest,
simplify_rec(points[(furthest + 1):n, ], tol) + furthest
)
} else {
c()
}
}
# From http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
point_line_dist <- function(px, py, lx_1, ly_1, lx_2, ly_2) {
abs((lx_2 - lx_1) * (ly_1 - py) - (lx_1 - px) * (ly_2 - ly_1)) /
sqrt((lx_2 - lx_1) ^ 2 + (ly_2 - ly_1) ^ 2)
}
# Precompute all tolerances so that we can post-select quickly
compute_tol <- function(points, offset = 0) {
n <- nrow(points)
if (n <= 2) {
c()
} else if (n == 3) {
with(points,
point_line_dist(long[2], lat[2], long[1], lat[1], long[3], lat[3]))
} else {
dist <- with(points,
point_line_dist(long[2:(n-1)], lat[2:(n-1)], long[1], lat[1], long[n], lat[n])
)
furthest <- which.max(dist)
if (length(furthest) == 0) browser()
c(
compute_tol(points[1:(furthest + 1), ], offset),
dist[furthest],
compute_tol(points[(furthest + 1):n, ], furthest + offset)
)
}
}