[Distance] Add geographical distance
authorSimon Chabot <simon.chabot@logilab.fr>
Fri, 26 Oct 2012 13:43:08 +0200
changeset 49 467c3461ad9d
parent 48 a0a6d2c8ba56
child 50 96d6d4a782ad
[Distance] Add geographical distance (Equirectangular projection)
distances.py
test/test_alignment.py
--- a/distances.py	Thu Oct 25 16:43:50 2012 +0200
+++ b/distances.py	Fri Oct 26 13:43:08 2012 +0200
@@ -17,6 +17,7 @@
 
 from dateutil import parser as dateparser
 from scipy import matrix
+from math import cos, sqrt, pi #Needed for geographical distance
 
 def levenshtein(stra, strb):
     """ Compute the Levenshtein distance between stra and strb.
@@ -216,3 +217,20 @@
         return abs(a - b)
     except TypeError:
         return abs(float(a) - float(b))
+
+def geographical(pointa, pointb, inRadians = True):
+    """ Return the geographical distance between two points.
+
+        Both points must be tuples (latitude, longitude)
+    """
+    difflat = pointa[0] - pointb[0]
+    difflong = pointa[1] - pointb[1]
+    meanlat = (pointa[0] + pointb[0])/2.0
+    earthradius = 6371009 #in meters
+
+    if not inRadians:
+        difflat *= pi / 180.0
+        difflong *= pi / 180.0
+        meanlat *= pi / 180.0
+
+    return earthradius * sqrt(difflat**2 + (cos(meanlat) * difflong)**2)
--- a/test/test_alignment.py	Thu Oct 25 16:43:50 2012 +0200
+++ b/test/test_alignment.py	Fri Oct 26 13:43:08 2012 +0200
@@ -41,8 +41,9 @@
 
 import unittest2
 
-from cubes.alignment.distances import (levenshtein, soundex, soundexcode, \
-                                       jaccard, temporal, euclidean)
+from cubes.alignment.distances import (levenshtein, soundex, soundexcode,   \
+                                       jaccard, temporal, euclidean,        \
+                                       geographical)
 from cubes.alignment.normalize import (lunormalize, loadlemmas, lemmatized, \
                                        roundstr, rgxformat, tokenize, simplify)
 
@@ -134,6 +135,14 @@
         self.assertEqual(euclidean(10, 11),
                          euclidean(11, 10))
 
+    def test_geographical(self):
+        paris = (48.856578, 2.351828)
+        london = (51.504872, -0.07857)
+        dist_parislondon = geographical(paris, london, inRadians = False)
+
+        self.assertAlmostEqual(dist_parislondon, 341564, 0)
+
+
 class NormalizerTestCase(unittest2.TestCase):
     def setUp(self):
         self.lemmas = loadlemmas('../data/french_lemmas.txt')