pax_global_header00006660000000000000000000000064126511077170014521gustar00rootroot0000000000000052 comment=16d4fedea411bb7d711520098f79bd225e78f427 maurycyp-vincenty-16d4fed/000077500000000000000000000000001265110771700157265ustar00rootroot00000000000000maurycyp-vincenty-16d4fed/.gitignore000066400000000000000000000000111265110771700177060ustar00rootroot00000000000000*.py[co] maurycyp-vincenty-16d4fed/LICENSE000066400000000000000000000022731265110771700167370ustar00rootroot00000000000000This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to maurycyp-vincenty-16d4fed/README.rst000066400000000000000000000020001265110771700174050ustar00rootroot00000000000000Vincenty ======== Calculate the geographical distance (in kilometers or miles) between 2 points with extreme accuracy. This library implements Vincenty's solution to the inverse geodetic problem. It is based on the WGS 84 reference ellipsoid and is accurate to within 1 mm (!) or better. This formula is widely used in geographic information systems (GIS) and is much more accurate than methods for computing the great-circle distance (which assume a spherical Earth). Example: distance between Boston and New York City -------------------------------------------------- .. code:: python >>> from vincenty import vincenty >>> boston = (42.3541165, -71.0693514) >>> newyork = (40.7791472, -73.9680804) >>> vincenty(boston, newyork) 298.396057 >>> vincenty(boston, newyork, miles=True) 185.414657 Installation ------------ .. code:: bash $ pip install vincenty References ---------- * https://en.wikipedia.org/wiki/Vincenty's_formulae * https://en.wikipedia.org/wiki/World_Geodetic_System maurycyp-vincenty-16d4fed/setup.py000066400000000000000000000015671265110771700174510ustar00rootroot00000000000000try: from setuptools import setup except ImportError: from distutils.core import setup setup( name='vincenty', version='0.1.4', description='Calculate the geographical distance between 2 points with extreme accuracy.', long_description=open('README.rst').read(), author='Maurycy Pietrzak', author_email=['github.com@wayheavy.com'], url='https://github.com/maurycyp/vincenty', packages=['vincenty'], license='Unlicense', classifiers=[ 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', 'License :: Public Domain', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 3', 'Topic :: Scientific/Engineering :: Mathematics', ], # TODO zip_safe, package_data ) maurycyp-vincenty-16d4fed/vincenty/000077500000000000000000000000001265110771700175655ustar00rootroot00000000000000maurycyp-vincenty-16d4fed/vincenty/__init__.py000066400000000000000000000061531265110771700217030ustar00rootroot00000000000000import math # WGS 84 a = 6378137 # meters f = 1 / 298.257223563 b = 6356752.314245 # meters; b = (1 - f)a MILES_PER_KILOMETER = 0.621371 MAX_ITERATIONS = 200 CONVERGENCE_THRESHOLD = 1e-12 # .000,000,000,001 def vincenty_inverse(point1, point2, miles=False): """ Vincenty's formula (inverse method) to calculate the distance (in kilometers or miles) between two points on the surface of a spheroid Doctests: >>> vincenty((0.0, 0.0), (0.0, 0.0)) # coincident points 0.0 >>> vincenty((0.0, 0.0), (0.0, 1.0)) 111.319491 >>> vincenty((0.0, 0.0), (1.0, 0.0)) 110.574389 >>> vincenty((0.0, 0.0), (0.5, 179.5)) # slow convergence 19936.288579 >>> vincenty((0.0, 0.0), (0.5, 179.7)) # failure to converge >>> boston = (42.3541165, -71.0693514) >>> newyork = (40.7791472, -73.9680804) >>> vincenty(boston, newyork) 298.396057 >>> vincenty(boston, newyork, miles=True) 185.414657 """ # short-circuit coincident points if point1[0] == point2[0] and point1[1] == point2[1]: return 0.0 U1 = math.atan((1 - f) * math.tan(math.radians(point1[0]))) U2 = math.atan((1 - f) * math.tan(math.radians(point2[0]))) L = math.radians(point2[1] - point1[1]) Lambda = L sinU1 = math.sin(U1) cosU1 = math.cos(U1) sinU2 = math.sin(U2) cosU2 = math.cos(U2) for iteration in range(MAX_ITERATIONS): sinLambda = math.sin(Lambda) cosLambda = math.cos(Lambda) sinSigma = math.sqrt((cosU2 * sinLambda) ** 2 + (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) ** 2) if sinSigma == 0: return 0.0 # coincident points cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda sigma = math.atan2(sinSigma, cosSigma) sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma cosSqAlpha = 1 - sinAlpha ** 2 try: cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha except ZeroDivisionError: cos2SigmaM = 0 C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha)) LambdaPrev = Lambda Lambda = L + (1 - C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM ** 2))) if abs(Lambda - LambdaPrev) < CONVERGENCE_THRESHOLD: break # successful convergence else: return None # failure to converge uSq = cosSqAlpha * (a ** 2 - b ** 2) / (b ** 2) A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq))) B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq))) deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM ** 2) - B / 6 * cos2SigmaM * (-3 + 4 * sinSigma ** 2) * (-3 + 4 * cos2SigmaM ** 2))) s = b * A * (sigma - deltaSigma) s /= 1000 # meters to kilometers if miles: s *= MILES_PER_KILOMETER # kilometers to miles return round(s, 6) vincenty = vincenty_inverse if __name__ == '__main__': import doctest doctest.testmod()