-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathfrechetdist.py
105 lines (87 loc) · 3.19 KB
/
frechetdist.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
__all__ = ['frdist']
def _c(ca, i, j, p, q):
if ca[i, j] > -1:
return ca[i, j]
elif i == 0 and j == 0:
ca[i, j] = np.linalg.norm(p[i]-q[j])
elif i > 0 and j == 0:
ca[i, j] = max(_c(ca, i-1, 0, p, q), np.linalg.norm(p[i]-q[j]))
elif i == 0 and j > 0:
ca[i, j] = max(_c(ca, 0, j-1, p, q), np.linalg.norm(p[i]-q[j]))
elif i > 0 and j > 0:
ca[i, j] = max(
min(
_c(ca, i-1, j, p, q),
_c(ca, i-1, j-1, p, q),
_c(ca, i, j-1, p, q)
),
np.linalg.norm(p[i]-q[j])
)
else:
ca[i, j] = float('inf')
return ca[i, j]
def frdist(p, q):
"""
Computes the discrete Fréchet distance between
two curves. The Fréchet distance between two curves in a
metric space is a measure of the similarity between the curves.
The discrete Fréchet distance may be used for approximately computing
the Fréchet distance between two arbitrary curves,
as an alternative to using the exact Fréchet distance between a polygonal
approximation of the curves or an approximation of this value.
This is a Python 3.* implementation of the algorithm produced
in Eiter, T. and Mannila, H., 1994. Computing discrete Fréchet distance.
Tech. Report CD-TR 94/64, Information Systems Department, Technical
University of Vienna.
http://www.kr.tuwien.ac.at/staff/eiter/et-archive/cdtr9464.pdf
Function dF(P, Q): real;
input: polygonal curves P = (u1, . . . , up) and Q = (v1, . . . , vq).
return: δdF (P, Q)
ca : array [1..p, 1..q] of real;
function c(i, j): real;
begin
if ca(i, j) > −1 then return ca(i, j)
elsif i = 1 and j = 1 then ca(i, j) := d(u1, v1)
elsif i > 1 and j = 1 then ca(i, j) := max{ c(i − 1, 1), d(ui, v1) }
elsif i = 1 and j > 1 then ca(i, j) := max{ c(1, j − 1), d(u1, vj) }
elsif i > 1 and j > 1 then ca(i, j) :=
max{ min(c(i − 1, j), c(i − 1, j − 1), c(i, j − 1)), d(ui, vj ) }
else ca(i, j) = ∞
return ca(i, j);
end; /* function c */
begin
for i = 1 to p do for j = 1 to q do ca(i, j) := −1.0;
return c(p, q);
end.
Parameters
----------
P : Input curve - two dimensional array of points
Q : Input curve - two dimensional array of points
Returns
-------
dist: float64
The discrete Fréchet distance between curves `P` and `Q`.
Examples
--------
>>> from frechetdist import frdist
>>> P=[[1,1], [2,1], [2,2]]
>>> Q=[[2,2], [0,1], [2,4]]
>>> frdist(P,Q)
>>> 2.0
>>> P=[[1,1], [2,1], [2,2]]
>>> Q=[[1,1], [2,1], [2,2]]
>>> frdist(P,Q)
>>> 0
"""
p = np.array(p, np.float64)
q = np.array(q, np.float64)
len_p = len(p)
len_q = len(q)
if len_p == 0 or len_q == 0:
raise ValueError('Input curves are empty.')
ca = (np.ones((len_p, len_q), dtype=np.float64) * -1)
dist = _c(ca, len_p-1, len_q-1, p, q)
return dist