-
Notifications
You must be signed in to change notification settings - Fork 17
/
rdp_alg.py
84 lines (71 loc) · 2.26 KB
/
rdp_alg.py
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
"""
rdp
~~~
Pure Python implementation of the Ramer-Douglas-Peucker algorithm.
:copyright: (c) 2014 Fabian Hirschmann <[email protected]>
:license: MIT, see LICENSE.txt for more details.
"""
import numpy as np
def pldist(x0, x1, x2):
"""
Calculates the distance from the point ``x0`` to the line given
by the points ``x1`` and ``x2``.
:param x0: a point
:type x0: a 2x1 numpy array
:param x1: a point of the line
:type x1: 2x1 numpy array
:param x2: another point of the line
:type x2: 2x1 numpy array
"""
x0, x1, x2 = x0[:2], x1[:2], x2[:2] # discard timestamp
if x1[0] == x2[0]:
return np.abs(x0[0] - x1[0])
return np.divide(np.linalg.norm(np.linalg.det([x2 - x1, x1 - x0])),
np.linalg.norm(x2 - x1))
def _rdp(M, epsilon, dist):
"""
Simplifies a given array of points.
:param M: an array
:type M: Nx2 numpy array
:param epsilon: epsilon in the rdp algorithm
:type epsilon: float
:param dist: distance function
:type dist: function with signature ``f(x1, x2, x3)``
"""
dmax = 0.0
index = -1
for i in range(1, M.shape[0]):
d = dist(M[i], M[0], M[-1])
if d > dmax:
index = i
dmax = d
if dmax > epsilon:
r1 = _rdp(M[:index + 1], epsilon, dist)
r2 = _rdp(M[index:], epsilon, dist)
return np.vstack((r1[:-1], r2))
else:
return np.vstack((M[0], M[-1]))
def _rdp_nn(seq, epsilon, dist):
"""
Simplifies a given array of points.
:param seq: a series of points
:type seq: sequence of 2-tuples
:param epsilon: epsilon in the rdp algorithm
:type epsilon: float
:param dist: distance function
:type dist: function with signature ``f(x1, x2, x3)``
"""
return _rdp(np.array(seq), epsilon, dist).tolist()
def rdp(M, epsilon=0, dist=pldist):
"""
Simplifies a given array of points.
:param M: a series of points
:type M: either a Nx2 numpy array or sequence of 2-tuples
:param epsilon: epsilon in the rdp algorithm
:type epsilon: float
:param dist: distance function
:type dist: function with signature ``f(x1, x2, x3)``
"""
if "numpy" in str(type(M)):
return _rdp(M, epsilon, dist)
return _rdp_nn(M, epsilon, dist)