commit python-geographiclib for openSUSE:Factory
Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-geographiclib for openSUSE:Factory checked in at 2021-06-01 10:35:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-geographiclib (Old) and /work/SRC/openSUSE:Factory/.python-geographiclib.new.1898 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-geographiclib" Tue Jun 1 10:35:04 2021 rev:2 rq:895182 version:1.50 Changes: -------- --- /work/SRC/openSUSE:Factory/python-geographiclib/python-geographiclib.changes 2019-08-13 13:22:54.833392341 +0200 +++ /work/SRC/openSUSE:Factory/.python-geographiclib.new.1898/python-geographiclib.changes 2021-06-01 10:35:31.292614852 +0200 @@ -1,0 +2,8 @@ +Mon May 24 14:03:36 UTC 2021 - pgajdos@suse.com + +- version update to 1.50 + * no upstream changelog found +- modified sources + % LICENSE.txt + +------------------------------------------------------------------- Old: ---- geographiclib-1.49.tar.gz New: ---- geographiclib-1.50.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-geographiclib.spec ++++++ --- /var/tmp/diff_new_pack.pNQrvy/_old 2021-06-01 10:35:31.796615710 +0200 +++ /var/tmp/diff_new_pack.pNQrvy/_new 2021-06-01 10:35:31.800615717 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-geographiclib # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -12,24 +12,25 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-geographiclib -Version: 1.49 +Version: 1.50 Release: 0 -License: MIT Summary: Python geodesic routines -Url: https://geographiclib.sourceforge.io/ +License: MIT Group: Development/Languages/Python +URL: https://geographiclib.sourceforge.io/ Source: https://files.pythonhosted.org/packages/source/g/geographiclib/geographiclib-%{version}.tar.gz Source1: https://sourceforge.net/p/geographiclib/code/ci/master/tree/LICENSE.txt?form... -BuildRequires: python-rpm-macros BuildRequires: %{python_module base} +BuildRequires: %{python_module setuptools} BuildRequires: fdupes +BuildRequires: python-rpm-macros BuildArch: noarch - %python_subpackages %description @@ -51,10 +52,10 @@ %python_expand %fdupes %{buildroot}%{$python_sitelib} %check -%python_exec setup.py test +%pyunittest discover -v geographiclib/test %files %{python_files} -%doc README.rst +%doc README.md %license LICENSE.txt %{python_sitelib}/* ++++++ LICENSE.txt ++++++ --- /var/tmp/diff_new_pack.pNQrvy/_old 2021-06-01 10:35:31.832615771 +0200 +++ /var/tmp/diff_new_pack.pNQrvy/_new 2021-06-01 10:35:31.836615778 +0200 @@ -1,7 +1,7 @@ The MIT License (MIT); this license applies to GeographicLib, versions 1.12 and later. -Copyright (c) 2008-2017, Charles Karney +Copyright (c) 2008-2019, Charles Karney Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation ++++++ geographiclib-1.49.tar.gz -> geographiclib-1.50.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/MANIFEST.in new/geographiclib-1.50/MANIFEST.in --- old/geographiclib-1.49/MANIFEST.in 1970-01-01 01:00:00.000000000 +0100 +++ new/geographiclib-1.50/MANIFEST.in 2019-09-24 15:10:55.000000000 +0200 @@ -0,0 +1 @@ +include README.md diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/PKG-INFO new/geographiclib-1.50/PKG-INFO --- old/geographiclib-1.49/PKG-INFO 2017-10-05 13:13:23.000000000 +0200 +++ new/geographiclib-1.50/PKG-INFO 2019-09-24 15:11:22.000000000 +0200 @@ -1,18 +1,18 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: geographiclib -Version: 1.49 +Version: 1.50 Summary: The geodesic routines from GeographicLib -Home-page: https://geographiclib.sourceforge.io/1.49/python +Home-page: https://geographiclib.sourceforge.io/1.50/python Author: Charles Karney Author-email: charles@karney.com License: MIT Description: This implements - `algorithms for geodesics <https://doi.org/10.1007/s00190-012-0578-z>`_ + [Algorithms for Geodesics](https://doi.org/10.1007/s00190-012-0578-z) (Karney, 2013) for solving the direct and inverse problems for an ellipsoid of revolution. Documentation is available at - `<https://geographiclib.sourceforge.io/1.49/python/>`_. + <https://geographiclib.sourceforge.io/1.50/python/>. Keywords: gis geographical earth distance geodesic Platform: UNKNOWN @@ -24,3 +24,4 @@ Classifier: Programming Language :: Python Classifier: Topic :: Scientific/Engineering :: GIS Classifier: Topic :: Software Development :: Libraries :: Python Modules +Description-Content-Type: text/markdown diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/README.md new/geographiclib-1.50/README.md --- old/geographiclib-1.49/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/geographiclib-1.50/README.md 2019-09-24 14:55:55.000000000 +0200 @@ -0,0 +1,7 @@ +This implements +[Algorithms for Geodesics](https://doi.org/10.1007/s00190-012-0578-z) +(Karney, 2013) for solving the direct and inverse problems for an +ellipsoid of revolution. + +Documentation is available at +<https://geographiclib.sourceforge.io/1.50/python/>. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/README.rst new/geographiclib-1.50/README.rst --- old/geographiclib-1.49/README.rst 2017-10-05 12:11:24.000000000 +0200 +++ new/geographiclib-1.50/README.rst 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -This implements -`algorithms for geodesics <https://doi.org/10.1007/s00190-012-0578-z>`_ -(Karney, 2013) for solving the direct and inverse problems for an -ellipsoid of revolution. - -Documentation is available at -`<https://geographiclib.sourceforge.io/1.49/python/>`_. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/geographiclib/__init__.py new/geographiclib-1.50/geographiclib/__init__.py --- old/geographiclib-1.49/geographiclib/__init__.py 2017-10-05 12:11:24.000000000 +0200 +++ new/geographiclib-1.50/geographiclib/__init__.py 2019-09-24 14:55:55.000000000 +0200 @@ -1,7 +1,7 @@ """geographiclib: geodesic routines from GeographicLib""" -__version_info__ = (1, 49, 0) +__version_info__ = (1, 50, 0) """GeographicLib version as a tuple""" -__version__ = "1.49" +__version__ = "1.50" """GeographicLib version as a string""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/geographiclib/accumulator.py new/geographiclib-1.50/geographiclib/accumulator.py --- old/geographiclib-1.49/geographiclib/accumulator.py 2017-10-05 12:11:24.000000000 +0200 +++ new/geographiclib-1.50/geographiclib/accumulator.py 2019-09-24 14:55:55.000000000 +0200 @@ -7,8 +7,8 @@ # # https://geographiclib.sourceforge.io/html/annotated.html # -# Copyright (c) Charles Karney (2011) <charles@karney.com> and licensed under -# the MIT/X11 License. For more information, see +# Copyright (c) Charles Karney (2011-2019) <charles@karney.com> and +# licensed under the MIT/X11 License. For more information, see # https://geographiclib.sourceforge.io/ ###################################################################### @@ -80,3 +80,8 @@ """Negate sum""" self._s *= -1 self._t *= -1 + + def Remainder(self, y): + """Remainder on division by y""" + self._s = Math.remainder(self._s, y) + self.Add(0.0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/geographiclib/geodesicline.py new/geographiclib-1.50/geographiclib/geodesicline.py --- old/geographiclib-1.49/geographiclib/geodesicline.py 2017-10-05 12:11:24.000000000 +0200 +++ new/geographiclib-1.50/geographiclib/geodesicline.py 2019-09-24 14:55:55.000000000 +0200 @@ -51,7 +51,7 @@ # https://doi.org/10.1007/s00190-012-0578-z # Addenda: https://geographiclib.sourceforge.io/geod-addenda.html # -# Copyright (c) Charles Karney (2011-2016) <charles@karney.com> and licensed +# Copyright (c) Charles Karney (2011-2019) <charles@karney.com> and licensed # under the MIT/X11 License. For more information, see # https://geographiclib.sourceforge.io/ ###################################################################### @@ -112,7 +112,7 @@ """the cosine of the azimuth at the first point (readonly)""" # real cbet1, sbet1 - sbet1, cbet1 = Math.sincosd(Math.AngRound(lat1)); sbet1 *= self._f1 + sbet1, cbet1 = Math.sincosd(Math.AngRound(self.lat1)); sbet1 *= self._f1 # Ensure cbet1 = +epsilon at poles sbet1, cbet1 = Math.norm(sbet1, cbet1); cbet1 = max(Geodesic.tiny_, cbet1) self._dn1 = math.sqrt(1 + geod._ep2 * Math.sq(sbet1)) @@ -205,6 +205,7 @@ else: # Interpret s12_a12 as distance tau12 = s12_a12 / (self._b * (1 + self._A1m1)) + tau12 = tau12 if Math.isfinite(tau12) else Math.nan s = math.sin(tau12); c = math.cos(tau12) # tau2 = tau1 + tau12 B12 = - Geodesic._SinCosSeries(True, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/geographiclib/geomath.py new/geographiclib-1.50/geographiclib/geomath.py --- old/geographiclib-1.49/geographiclib/geomath.py 2017-10-05 12:11:24.000000000 +0200 +++ new/geographiclib-1.50/geographiclib/geomath.py 2019-09-24 14:55:55.000000000 +0200 @@ -6,7 +6,7 @@ # # https://geographiclib.sourceforge.io/html/annotated.html # -# Copyright (c) Charles Karney (2011-2017) <charles@karney.com> and +# Copyright (c) Charles Karney (2011-2019) <charles@karney.com> and # licensed under the MIT/X11 License. For more information, see # https://geographiclib.sourceforge.io/ ###################################################################### @@ -44,7 +44,7 @@ """Real cube root of a number""" y = math.pow(abs(x), 1/3.0) - return y if x >= 0 else -y + return y if x > 0 else (-y if x < 0 else x) cbrt = staticmethod(cbrt) def log1p(x): @@ -70,7 +70,7 @@ y = abs(x) # Enforce odd parity y = Math.log1p(2 * y/(1 - y))/2 - return -y if x < 0 else y + return y if x > 0 else (-y if x < 0 else x) atanh = staticmethod(atanh) def copysign(x, y): @@ -126,16 +126,22 @@ return 0.0 if x == 0 else (-y if x < 0 else y) AngRound = staticmethod(AngRound) - def AngNormalize(x): - """reduce angle to (-180,180]""" - - y = math.fmod(x, 360) + def remainder(x, y): + """remainder of x/y in the range [-y/2, y/2].""" + z = math.fmod(x, y) if Math.isfinite(x) else Math.nan # On Windows 32-bit with python 2.7, math.fmod(-0.0, 360) = +0.0 # This fixes this bug. See also Math::AngNormalize in the C++ library. # sincosd has a similar fix. - y = x if x == 0 else y - return (y + 360 if y <= -180 else - (y if y <= 180 else y - 360)) + z = x if x == 0 else z + return (z + y if z < -y/2 else + (z if z < y/2 else z -y)) + remainder = staticmethod(remainder) + + def AngNormalize(x): + """reduce angle to (-180,180]""" + + y = Math.remainder(x, 360) + return 180 if y == -180 else y AngNormalize = staticmethod(AngNormalize) def LatFix(x): @@ -155,8 +161,8 @@ def sincosd(x): """Compute sine and cosine of x in degrees.""" - r = math.fmod(x, 360) - q = Math.nan if Math.isnan(r) else int(math.floor(r / 90 + 0.5)) + r = math.fmod(x, 360) if Math.isfinite(x) else Math.nan + q = 0 if Math.isnan(r) else int(round(r / 90)) r -= 90 * q; r = math.radians(r) s = math.sin(r); c = math.cos(r) q = q % 4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/geographiclib/polygonarea.py new/geographiclib-1.50/geographiclib/polygonarea.py --- old/geographiclib-1.49/geographiclib/polygonarea.py 2017-10-05 12:11:24.000000000 +0200 +++ new/geographiclib-1.50/geographiclib/polygonarea.py 2019-09-24 14:55:55.000000000 +0200 @@ -39,7 +39,7 @@ # https://doi.org/10.1007/s00190-012-0578-z # Addenda: https://geographiclib.sourceforge.io/geod-addenda.html # -# Copyright (c) Charles Karney (2011-2017) <charles@karney.com> and licensed +# Copyright (c) Charles Karney (2011-2019) <charles@karney.com> and licensed # under the MIT/X11 License. For more information, see # https://geographiclib.sourceforge.io/ ###################################################################### @@ -67,14 +67,60 @@ def _transitdirect(lon1, lon2): """Count crossings of prime meridian for AddEdge.""" # We want to compute exactly - # int(floor(lon2 / 360)) - int(floor(lon1 / 360)) + # int(ceil(lon2 / 360)) - int(ceil(lon1 / 360)) # Since we only need the parity of the result we can use std::remquo but # this is buggy with g++ 4.8.3 and requires C++11. So instead we do lon1 = math.fmod(lon1, 720.0); lon2 = math.fmod(lon2, 720.0) - return ( (0 if ((lon2 >= 0 and lon2 < 360) or lon2 < -360) else 1) - - (0 if ((lon1 >= 0 and lon1 < 360) or lon1 < -360) else 1) ) + return ( (1 if ((lon2 <= 0 and lon2 > -360) or lon2 > 360) else 0) - + (1 if ((lon1 <= 0 and lon1 > -360) or lon1 > 360) else 0) ) _transitdirect = staticmethod(_transitdirect) + def _areareduceA(area, area0, crossings, reverse, sign): + """Reduce accumulator area to allowed range.""" + area.Remainder(area0) + if crossings & 1: + area.Add( (1 if area.Sum() < 0 else -1) * area0/2 ) + # area is with the clockwise sense. If !reverse convert to + # counter-clockwise convention. + if not reverse: area.Negate() + # If sign put area in (-area0/2, area0/2], else put area in [0, area0) + if sign: + if area.Sum() > area0/2: + area.Add( -area0 ) + elif area.Sum() <= -area0/2: + area.Add( area0 ) + else: + if area.Sum() >= area0: + area.Add( -area0 ) + elif area.Sum() < 0: + area.Add( area0 ) + + return 0.0 + area.Sum() + _areareduceA = staticmethod(_areareduceA) + + def _areareduceB(area, area0, crossings, reverse, sign): + """Reduce double area to allowed range.""" + area = Math.remainder(area, area0) + if crossings & 1: + area += (1 if area < 0 else -1) * area0/2 + # area is with the clockwise sense. If !reverse convert to + # counter-clockwise convention. + if not reverse: area *= -1 + # If sign put area in (-area0/2, area0/2], else put area in [0, area0) + if sign: + if area > area0/2: + area -= area0 + elif area <= -area0/2: + area += area0 + else: + if area >= area0: + area -= area0 + elif area < 0: + area += area0 + + return 0.0 + area + _areareduceB = staticmethod(_areareduceB) + def __init__(self, earth, polyline = False): """Construct a PolygonArea object @@ -169,7 +215,12 @@ the area for the rest of the earth :return: a tuple of number, perimeter (meters), area (meters^2) - If the object is a polygon (and not a polygon), the perimeter + Arbitrarily complex polygons are allowed. In the case of + self-intersecting polygons the area is accumulated "algebraically", + e.g., the areas of the 2 loops in a figure-8 polygon will partially + cancel. + + If the object is a polygon (and not a polyline), the perimeter includes the length of a final edge connecting the current point to the initial point. If the object is a polyline, then area is nan. @@ -192,24 +243,8 @@ tempsum = Accumulator(self._areasum) tempsum.Add(S12) crossings = self._crossings + PolygonArea._transit(self.lon1, self._lon0) - if crossings & 1: - tempsum.Add( (1 if tempsum.Sum() < 0 else -1) * self.area0/2 ) - # area is with the clockwise sense. If !reverse convert to - # counter-clockwise convention. - if not reverse: tempsum.Negate() - # If sign put area in (-area0/2, area0/2], else put area in [0, area0) - if sign: - if tempsum.Sum() > self.area0/2: - tempsum.Add( -self.area0 ) - elif tempsum.Sum() <= -self.area0/2: - tempsum.Add( self.area0 ) - else: - if tempsum.Sum() >= self.area0: - tempsum.Add( -self.area0 ) - elif tempsum.Sum() < 0: - tempsum.Add( self.area0 ) - - area = 0.0 + tempsum.Sum() + area = PolygonArea._areareduceA(tempsum, self.area0, crossings, + reverse, sign) return self.num, perimeter, area # return number, perimeter, area @@ -249,24 +284,8 @@ if self.polyline: return num, perimeter, area - if crossings & 1: - tempsum += (1 if tempsum < 0 else -1) * self.area0/2 - # area is with the clockwise sense. If !reverse convert to - # counter-clockwise convention. - if not reverse: tempsum *= -1 - # If sign put area in (-area0/2, area0/2], else put area in [0, area0) - if sign: - if tempsum > self.area0/2: - tempsum -= self.area0 - elif tempsum <= -self.area0/2: - tempsum += self.area0 - else: - if tempsum >= self.area0: - tempsum -= self.area0 - elif tempsum < 0: - tempsum += self.area0 - - area = 0.0 + tempsum + area = PolygonArea._areareduceB(tempsum, self.area0, crossings, + reverse, sign) return num, perimeter, area # return num, perimeter, area @@ -303,22 +322,6 @@ tempsum += S12 crossings += PolygonArea._transit(lon, self._lon0) - if crossings & 1: - tempsum += (1 if tempsum < 0 else -1) * self.area0/2 - # area is with the clockwise sense. If !reverse convert to - # counter-clockwise convention. - if not reverse: tempsum *= -1 - # If sign put area in (-area0/2, area0/2], else put area in [0, area0) - if sign: - if tempsum > self.area0/2: - tempsum -= self.area0 - elif tempsum <= -self.area0/2: - tempsum += self.area0 - else: - if tempsum >= self.area0: - tempsum -= self.area0 - elif tempsum < 0: - tempsum += self.area0 - - area = 0.0 + tempsum + area = PolygonArea._areareduceB(tempsum, self.area0, crossings, + reverse, sign) return num, perimeter, area diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/geographiclib/test/test_geodesic.py new/geographiclib-1.50/geographiclib/test/test_geodesic.py --- old/geographiclib-1.49/geographiclib/test/test_geodesic.py 2017-10-05 12:11:24.000000000 +0200 +++ new/geographiclib-1.50/geographiclib/test/test_geodesic.py 2019-09-24 14:55:55.000000000 +0200 @@ -350,7 +350,7 @@ inv = Geodesic.WGS84.Inverse(5, 0.00000000000001, 10, 180) self.assertAlmostEqual(inv["azi1"], 0.000000000000035, delta = 1.5e-14) self.assertAlmostEqual(inv["azi2"], 179.99999999999996, delta = 1.5e-14) - self.assertAlmostEqual(inv["s12"], 18345191.174332713, delta = 4e-9) + self.assertAlmostEqual(inv["s12"], 18345191.174332713, delta = 5e-9) def test_GeodSolve61(self): # Make sure small negative azimuths are west-going @@ -425,24 +425,27 @@ # Check for backwards from the pole bug reported by Anon on 2016-02-13. # This only affected the Java implementation. It was introduced in Java # version 1.44 and fixed in 1.46-SNAPSHOT on 2016-01-17. + # Also the + sign on azi2 is a check on the normalizing of azimuths + # (converting -0.0 to +0.0). dir = Geodesic.WGS84.Direct(90, 10, 180, -1e6) self.assertAlmostEqual(dir["lat2"], 81.04623, delta = 0.5e-5) self.assertAlmostEqual(dir["lon2"], -170, delta = 0.5e-5) self.assertAlmostEqual(dir["azi2"], 0, delta = 0.5e-5) + self.assertTrue(Math.copysign(1, dir["azi2"]) > 0) def test_GeodSolve74(self): # Check fix for inaccurate areas, bug introduced in v1.46, fixed # 2015-10-16. inv = Geodesic.WGS84.Inverse(54.1589, 15.3872, 54.1591, 15.3877, Geodesic.ALL) - self.assertAlmostEqual(inv["azi1"], 55.723110355, delta = 5e-9); - self.assertAlmostEqual(inv["azi2"], 55.723515675, delta = 5e-9); - self.assertAlmostEqual(inv["s12"], 39.527686385, delta = 5e-9); - self.assertAlmostEqual(inv["a12"], 0.000355495, delta = 5e-9); - self.assertAlmostEqual(inv["m12"], 39.527686385, delta = 5e-9); - self.assertAlmostEqual(inv["M12"], 0.999999995, delta = 5e-9); - self.assertAlmostEqual(inv["M21"], 0.999999995, delta = 5e-9); - self.assertAlmostEqual(inv["S12"], 286698586.30197, delta = 5e-4); + self.assertAlmostEqual(inv["azi1"], 55.723110355, delta = 5e-9) + self.assertAlmostEqual(inv["azi2"], 55.723515675, delta = 5e-9) + self.assertAlmostEqual(inv["s12"], 39.527686385, delta = 5e-9) + self.assertAlmostEqual(inv["a12"], 0.000355495, delta = 5e-9) + self.assertAlmostEqual(inv["m12"], 39.527686385, delta = 5e-9) + self.assertAlmostEqual(inv["M12"], 0.999999995, delta = 5e-9) + self.assertAlmostEqual(inv["M21"], 0.999999995, delta = 5e-9) + self.assertAlmostEqual(inv["S12"], 286698586.30197, delta = 5e-4) def test_GeodSolve76(self): # The distance from Wellington and Salamanca (a classic failure of @@ -460,6 +463,79 @@ self.assertAlmostEqual(inv["azi2"], 134.22776532670, delta = 0.5e-11) self.assertAlmostEqual(inv["s12"], 19974354.765767, delta = 0.5e-6) + def test_GeodSolve80(self): + # Some tests to add code coverage: computing scale in special cases + zero + # length geodesic (includes GeodSolve80 - GeodSolve83) + using an incapable + # line. + inv = Geodesic.WGS84.Inverse(0, 0, 0, 90, Geodesic.GEODESICSCALE) + self.assertAlmostEqual(inv["M12"], -0.00528427534, delta = 0.5e-10) + self.assertAlmostEqual(inv["M21"], -0.00528427534, delta = 0.5e-10) + + inv = Geodesic.WGS84.Inverse(0, 0, 1e-6, 1e-6, Geodesic.GEODESICSCALE) + self.assertAlmostEqual(inv["M12"], 1, delta = 0.5e-10) + self.assertAlmostEqual(inv["M21"], 1, delta = 0.5e-10) + + inv = Geodesic.WGS84.Inverse(20.001, 0, 20.001, 0, Geodesic.ALL) + self.assertAlmostEqual(inv["a12"], 0, delta = 1e-13) + self.assertAlmostEqual(inv["s12"], 0, delta = 1e-8) + self.assertAlmostEqual(inv["azi1"], 180, delta = 1e-13) + self.assertAlmostEqual(inv["azi2"], 180, delta = 1e-13) + self.assertAlmostEqual(inv["m12"], 0, delta = 1e-8) + self.assertAlmostEqual(inv["M12"], 1, delta = 1e-15) + self.assertAlmostEqual(inv["M21"], 1, delta = 1e-15) + self.assertAlmostEqual(inv["S12"], 0, delta = 1e-10) + + inv = Geodesic.WGS84.Inverse(90, 0, 90, 180, Geodesic.ALL) + self.assertAlmostEqual(inv["a12"], 0, delta = 1e-13) + self.assertAlmostEqual(inv["s12"], 0, delta = 1e-8) + self.assertAlmostEqual(inv["azi1"], 0, delta = 1e-13) + self.assertAlmostEqual(inv["azi2"], 180, delta = 1e-13) + self.assertAlmostEqual(inv["m12"], 0, delta = 1e-8) + self.assertAlmostEqual(inv["M12"], 1, delta = 1e-15) + self.assertAlmostEqual(inv["M21"], 1, delta = 1e-15) + self.assertAlmostEqual(inv["S12"], 127516405431022.0, delta = 0.5) + + # An incapable line which can't take distance as input + line = Geodesic.WGS84.Line(1, 2, 90, Geodesic.LATITUDE) + dir = line.Position(1000, Geodesic.EMPTY) + self.assertTrue(Math.isnan(dir["a12"])) + + def test_GeodSolve84(self): + # Tests for python implementation to check fix for range errors with + # {fmod,sin,cos}(inf) (includes GeodSolve84 - GeodSolve91). + dir = Geodesic.WGS84.Direct(0, 0, 90, Math.inf) + self.assertTrue(Math.isnan(dir["lat2"])) + self.assertTrue(Math.isnan(dir["lon2"])) + self.assertTrue(Math.isnan(dir["azi2"])) + dir = Geodesic.WGS84.Direct(0, 0, 90, Math.nan) + self.assertTrue(Math.isnan(dir["lat2"])) + self.assertTrue(Math.isnan(dir["lon2"])) + self.assertTrue(Math.isnan(dir["azi2"])) + dir = Geodesic.WGS84.Direct(0, 0, Math.inf, 1000) + self.assertTrue(Math.isnan(dir["lat2"])) + self.assertTrue(Math.isnan(dir["lon2"])) + self.assertTrue(Math.isnan(dir["azi2"])) + dir = Geodesic.WGS84.Direct(0, 0, Math.nan, 1000) + self.assertTrue(Math.isnan(dir["lat2"])) + self.assertTrue(Math.isnan(dir["lon2"])) + self.assertTrue(Math.isnan(dir["azi2"])) + dir = Geodesic.WGS84.Direct(0, Math.inf, 90, 1000) + self.assertTrue(dir["lat1"] == 0) + self.assertTrue(Math.isnan(dir["lon2"])) + self.assertTrue(dir["azi2"] == 90) + dir = Geodesic.WGS84.Direct(0, Math.nan, 90, 1000) + self.assertTrue(dir["lat1"] == 0) + self.assertTrue(Math.isnan(dir["lon2"])) + self.assertTrue(dir["azi2"] == 90) + dir = Geodesic.WGS84.Direct(Math.inf, 0, 90, 1000) + self.assertTrue(Math.isnan(dir["lat2"])) + self.assertTrue(Math.isnan(dir["lon2"])) + self.assertTrue(Math.isnan(dir["azi2"])) + dir = Geodesic.WGS84.Direct(Math.nan, 0, 90, 1000) + self.assertTrue(Math.isnan(dir["lat2"])) + self.assertTrue(Math.isnan(dir["lon2"])) + self.assertTrue(Math.isnan(dir["azi2"])) + class PlanimeterTest(unittest.TestCase): polygon = Geodesic.WGS84.Polygon(False) @@ -542,3 +618,153 @@ num, perimeter, area = PlanimeterTest.Planimeter(points) self.assertAlmostEqual(perimeter, 1160741, delta = 1) self.assertAlmostEqual(area, 32415230256.0, delta = 1) + + def test_Planimeter15(self): + # Coverage tests, includes Planimeter15 - Planimeter18 (combinations of + # reverse and sign) + calls to testpoint, testedge. + lat = [2, 1, 3] + lon = [1, 2, 3] + r = 18454562325.45119 + a0 = 510065621724088.5093 # ellipsoid area + PlanimeterTest.polygon.Clear() + PlanimeterTest.polygon.AddPoint(lat[0], lon[0]) + PlanimeterTest.polygon.AddPoint(lat[1], lon[1]) + num, perimeter, area = PlanimeterTest.polygon.TestPoint(lat[2], lon[2], + False, True) + self.assertAlmostEqual(area, r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.TestPoint(lat[2], lon[2], + False, False) + self.assertAlmostEqual(area, r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.TestPoint(lat[2], lon[2], + True, True) + self.assertAlmostEqual(area, -r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.TestPoint(lat[2], lon[2], + True, False) + self.assertAlmostEqual(area, a0-r, delta = 0.5) + inv = Geodesic.WGS84.Inverse(lat[1], lon[1], lat[2], lon[2]) + azi1 = inv["azi1"] + s12 = inv["s12"] + num, perimeter, area = PlanimeterTest.polygon.TestEdge(azi1, s12, + False, True) + self.assertAlmostEqual(area, r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.TestEdge(azi1, s12, + False, False) + self.assertAlmostEqual(area, r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.TestEdge(azi1, s12, + True, True) + self.assertAlmostEqual(area, -r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.TestEdge(azi1, s12, + True, False) + self.assertAlmostEqual(area, a0-r, delta = 0.5) + PlanimeterTest.polygon.AddPoint(lat[2], lon[2]) + num, perimeter, area = PlanimeterTest.polygon.Compute(False, True) + self.assertAlmostEqual(area, r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.Compute(False, False) + self.assertAlmostEqual(area, r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.Compute(True, True) + self.assertAlmostEqual(area, -r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.Compute(True, False) + self.assertAlmostEqual(area, a0-r, delta = 0.5) + + def test_Planimeter19(self): + # Coverage tests, includes Planimeter19 - Planimeter20 (degenerate + # polygons) + extra cases. + PlanimeterTest.polygon.Clear() + num, perimeter, area = PlanimeterTest.polygon.Compute(False, True) + self.assertTrue(area == 0) + self.assertTrue(perimeter == 0) + num, perimeter, area = PlanimeterTest.polygon.TestPoint(1, 1, + False, True) + self.assertTrue(area == 0) + self.assertTrue(perimeter == 0) + num, perimeter, area = PlanimeterTest.polygon.TestEdge(90, 1000, + False, True) + self.assertTrue(Math.isnan(area)) + self.assertTrue(Math.isnan(perimeter)) + PlanimeterTest.polygon.AddPoint(1, 1) + num, perimeter, area = PlanimeterTest.polygon.Compute(False, True) + self.assertTrue(area == 0) + self.assertTrue(perimeter == 0) + PlanimeterTest.polyline.Clear() + num, perimeter, area = PlanimeterTest.polyline.Compute(False, True) + self.assertTrue(perimeter == 0) + num, perimeter, area = PlanimeterTest.polyline.TestPoint(1, 1, + False, True) + self.assertTrue(perimeter == 0) + num, perimeter, area = PlanimeterTest.polyline.TestEdge(90, 1000, + False, True) + self.assertTrue(Math.isnan(perimeter)) + PlanimeterTest.polyline.AddPoint(1, 1) + num, perimeter, area = PlanimeterTest.polyline.Compute(False, True) + self.assertTrue(perimeter == 0) + PlanimeterTest.polygon.AddPoint(1, 1) + num, perimeter, area = PlanimeterTest.polyline.TestEdge(90, 1000, + False, True) + self.assertAlmostEqual(perimeter, 1000, delta = 1e-10) + num, perimeter, area = PlanimeterTest.polyline.TestPoint(2, 2, + False, True) + self.assertAlmostEqual(perimeter, 156876.149, delta = 0.5e-3) + + def test_Planimeter21(self): + # Some test to add code coverage: multiple circlings of pole (includes + # Planimeter21 - Planimeter28) + invocations via testpoint and testedge. + lat = 45 + azi = 39.2144607176828184218 + s = 8420705.40957178156285 + r = 39433884866571.4277 # Area for one circuit + a0 = 510065621724088.5093 # Ellipsoid area + PlanimeterTest.polygon.Clear() + PlanimeterTest.polygon.AddPoint(lat, 60) + PlanimeterTest.polygon.AddPoint(lat, 180) + PlanimeterTest.polygon.AddPoint(lat, -60) + PlanimeterTest.polygon.AddPoint(lat, 60) + PlanimeterTest.polygon.AddPoint(lat, 180) + PlanimeterTest.polygon.AddPoint(lat, -60) + for i in [3, 4]: + PlanimeterTest.polygon.AddPoint(lat, 60) + PlanimeterTest.polygon.AddPoint(lat, 180) + num, perimeter, area = PlanimeterTest.polygon.TestPoint(lat, -60, + False, True) + self.assertAlmostEqual(area, i*r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.TestPoint(lat, -60, + False, False) + self.assertAlmostEqual(area, i*r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.TestPoint(lat, -60, + True, True) + self.assertAlmostEqual(area, -i*r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.TestPoint(lat, -60, + True, False) + self.assertAlmostEqual(area, -i*r + a0, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.TestEdge(azi, s, + False, True) + self.assertAlmostEqual(area, i*r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.TestEdge(azi, s, + False, False) + self.assertAlmostEqual(area, i*r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.TestEdge(azi, s, + True, True) + self.assertAlmostEqual(area, -i*r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.TestEdge(azi, s, + True, False) + self.assertAlmostEqual(area, -i*r + a0, delta = 0.5) + PlanimeterTest.polygon.AddPoint(lat, -60) + num, perimeter, area = PlanimeterTest.polygon.Compute(False, True) + self.assertAlmostEqual(area, i*r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.Compute(False, False) + self.assertAlmostEqual(area, i*r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.Compute(True, True) + self.assertAlmostEqual(area, -i*r, delta = 0.5) + num, perimeter, area = PlanimeterTest.polygon.Compute(True, False) + self.assertAlmostEqual(area, -i*r + a0, delta = 0.5) + + def test_Planimeter29(self): + # Check fix to transitdirect vs transit zero handling inconsistency + PlanimeterTest.polygon.Clear() + PlanimeterTest.polygon.AddPoint(0, 0) + PlanimeterTest.polygon.AddEdge( 90, 1000) + PlanimeterTest.polygon.AddEdge( 0, 1000) + PlanimeterTest.polygon.AddEdge(-90, 1000) + num, perimeter, area = PlanimeterTest.polygon.Compute(False, True) + # The area should be 1e6. Prior to the fix it was 1e6 - A/2, where + # A = ellipsoid area. + self.assertAlmostEqual(area, 1000000.0, delta = 0.01) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/geographiclib.egg-info/PKG-INFO new/geographiclib-1.50/geographiclib.egg-info/PKG-INFO --- old/geographiclib-1.49/geographiclib.egg-info/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 +++ new/geographiclib-1.50/geographiclib.egg-info/PKG-INFO 2019-09-24 15:11:22.000000000 +0200 @@ -0,0 +1,27 @@ +Metadata-Version: 2.1 +Name: geographiclib +Version: 1.50 +Summary: The geodesic routines from GeographicLib +Home-page: https://geographiclib.sourceforge.io/1.50/python +Author: Charles Karney +Author-email: charles@karney.com +License: MIT +Description: This implements + [Algorithms for Geodesics](https://doi.org/10.1007/s00190-012-0578-z) + (Karney, 2013) for solving the direct and inverse problems for an + ellipsoid of revolution. + + Documentation is available at + <https://geographiclib.sourceforge.io/1.50/python/>. + +Keywords: gis geographical earth distance geodesic +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Science/Research +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Scientific/Engineering :: GIS +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Description-Content-Type: text/markdown diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/geographiclib.egg-info/SOURCES.txt new/geographiclib-1.50/geographiclib.egg-info/SOURCES.txt --- old/geographiclib-1.49/geographiclib.egg-info/SOURCES.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/geographiclib-1.50/geographiclib.egg-info/SOURCES.txt 2019-09-24 15:11:22.000000000 +0200 @@ -0,0 +1,17 @@ +MANIFEST.in +README.md +setup.py +geographiclib/__init__.py +geographiclib/accumulator.py +geographiclib/constants.py +geographiclib/geodesic.py +geographiclib/geodesiccapability.py +geographiclib/geodesicline.py +geographiclib/geomath.py +geographiclib/polygonarea.py +geographiclib.egg-info/PKG-INFO +geographiclib.egg-info/SOURCES.txt +geographiclib.egg-info/dependency_links.txt +geographiclib.egg-info/top_level.txt +geographiclib/test/__init__.py +geographiclib/test/test_geodesic.py \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/geographiclib.egg-info/dependency_links.txt new/geographiclib-1.50/geographiclib.egg-info/dependency_links.txt --- old/geographiclib-1.49/geographiclib.egg-info/dependency_links.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/geographiclib-1.50/geographiclib.egg-info/dependency_links.txt 2019-09-24 15:11:22.000000000 +0200 @@ -0,0 +1 @@ + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/geographiclib.egg-info/top_level.txt new/geographiclib-1.50/geographiclib.egg-info/top_level.txt --- old/geographiclib-1.49/geographiclib.egg-info/top_level.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/geographiclib-1.50/geographiclib.egg-info/top_level.txt 2019-09-24 15:11:22.000000000 +0200 @@ -0,0 +1 @@ +geographiclib diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/setup.cfg new/geographiclib-1.50/setup.cfg --- old/geographiclib-1.49/setup.cfg 1970-01-01 01:00:00.000000000 +0100 +++ new/geographiclib-1.50/setup.cfg 2019-09-24 15:11:22.000000000 +0200 @@ -0,0 +1,4 @@ +[egg_info] +tag_build = +tag_date = 0 + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/geographiclib-1.49/setup.py new/geographiclib-1.50/setup.py --- old/geographiclib-1.49/setup.py 2017-10-05 12:11:24.000000000 +0200 +++ new/geographiclib-1.50/setup.py 2019-09-24 14:55:55.000000000 +0200 @@ -19,49 +19,36 @@ # The initial version of this file was provided by # Andrew MacIntyre <Andrew.MacIntyre@acma.gov.au>. -from distutils.core import setup -from distutils.cmd import Command - -class TestCommand(Command): - user_options = [] - def initialize_options(self): - pass - def finalize_options(self): - pass - def run(self): - import sys, subprocess - raise SystemExit(subprocess.call([sys.executable, - '-m', - 'unittest', - '-v', - 'geographiclib.test.test_geodesic' - ])) +import setuptools name = "geographiclib" -version = "1.49" +version = "1.50" + +with open("README.md", "r") as fh: + long_description = fh.read() -setup(name = name, - version = version, - description = "The geodesic routines from GeographicLib", - long_description = open("README.rst").read(), - author = "Charles Karney", - author_email = "charles@karney.com", - url = "https://geographiclib.sourceforge.io/" + version + "/python", - packages = ["geographiclib", "geographiclib/test"], - data_files = [], - license = "MIT", - keywords = "gis geographical earth distance geodesic", - classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Topic :: Scientific/Engineering :: GIS", - "Topic :: Software Development :: Libraries :: Python Modules", - ], - cmdclass={ - 'test': TestCommand, - }, +setuptools.setup( + name = name, + version = version, + author = "Charles Karney", + author_email = "charles@karney.com", + description = "The geodesic routines from GeographicLib", + long_description = long_description, + long_description_content_type = "text/markdown", + url = "https://geographiclib.sourceforge.io/" + version + "/python", + include_package_data = True, + packages = setuptools.find_packages(), + license = "MIT", + keywords = "gis geographical earth distance geodesic", + classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Topic :: Scientific/Engineering :: GIS", + "Topic :: Software Development :: Libraries :: Python Modules", + ], + test_suite = "geographiclib.test.test_geodesic", )
participants (1)
-
Source-Sync