[Git][debian-gis-team/pymap3d][upstream] New upstream version 2.7.0
Antonio Valentino (@antonio.valentino)
gitlab at salsa.debian.org
Tue Aug 17 11:00:48 BST 2021
Antonio Valentino pushed to branch upstream at Debian GIS Project / pymap3d
Commits:
2e278877 by Antonio Valentino at 2021-08-17T09:40:17+00:00
New upstream version 2.7.0
- - - - -
24 changed files:
- − Examples/vdist.py
- Examples/vdist_stability.py
- − Examples/vreckon.py
- README.md
- pyproject.toml
- setup.cfg
- src/pymap3d/__init__.py
- src/pymap3d/ecef.py
- src/pymap3d/enu.py
- src/pymap3d/latitude.py
- src/pymap3d/lox.py
- src/pymap3d/rcurve.py
- src/pymap3d/rsphere.py
- src/pymap3d/tests/test_geodetic.py
- src/pymap3d/tests/test_latitude.py
- src/pymap3d/tests/test_look_spheroid.py
- src/pymap3d/tests/test_rcurve.py
- src/pymap3d/tests/test_rhumb.py
- src/pymap3d/tests/test_rsphere.py
- src/pymap3d/utils.py
- + src/pymap3d/vdist/__init__.py
- + src/pymap3d/vdist/__main__.py
- + src/pymap3d/vreckon/__init__.py
- + src/pymap3d/vreckon/__main__.py
Changes:
=====================================
Examples/vdist.py deleted
=====================================
@@ -1,20 +0,0 @@
-#!/usr/bin/env python
-from pymap3d.vincenty import vdist
-from argparse import ArgumentParser
-
-
-def main():
- p = ArgumentParser(description="vdist distance between WGS-84 coordinates")
- p.add_argument("lat1", help="latitude1 WGS-84 [degrees]", type=float)
- p.add_argument("lon1", help="longitude1 WGS-84 [degrees]", type=float)
- p.add_argument("lat2", help="latitude2 WGS-84 [degrees]", type=float)
- p.add_argument("lon2", help="longitude2 WGS-84 [degrees]", type=float)
- P = p.parse_args()
-
- dist_m = vdist(P.lat1, P.lon1, P.lat2, P.lon2)
-
- print("{:.3f} meters {:.3f} deg azimuth".format(*dist_m))
-
-
-if __name__ == "__main__": # pragma: no cover
- main()
=====================================
Examples/vdist_stability.py
=====================================
@@ -16,7 +16,7 @@ except ImportError as exc:
def matlab_func(lat1: float, lon1: float, lat2: float, lon2: float) -> typing.Tuple[float, float]:
- """ Using Matlab Engine to do same thing as Pymap3d """
+ """Using Matlab Engine to do same thing as Pymap3d"""
ell = eng.wgs84Ellipsoid()
return eng.distance(lat1, lon1, lat2, lon2, ell, nargout=2)
=====================================
Examples/vreckon.py deleted
=====================================
@@ -1,22 +0,0 @@
-#!/usr/bin/env python
-from pymap3d.vincenty import vreckon
-from argparse import ArgumentParser
-
-
-def main():
- p = ArgumentParser(
- description="Given starting latitude, longitude: find final lat,lon for distance and azimuth"
- )
- p.add_argument("lat", help="latitude WGS-84 [degrees]", type=float)
- p.add_argument("lon", help="longitude WGS-84 [degrees]", type=float)
- p.add_argument("range", help="range from start point [meters]", type=float)
- p.add_argument("azimuth", help="clockwise from north: azimuth to start [degrees]", type=float)
- P = p.parse_args()
-
- lat2, lon2 = vreckon(P.lat, P.lon, P.range, P.azimuth)
-
- print("lat, lon = ({:.4f}, {:.4f})".format(lat2, lon2))
-
-
-if __name__ == "__main__": # pragma: no cover
- main()
=====================================
README.md
=====================================
@@ -112,6 +112,15 @@ Abbreviations:
* [NED: North East Down](https://en.wikipedia.org/wiki/North_east_down)
* [radec: right ascension, declination](https://en.wikipedia.org/wiki/Right_ascension)
+### command line
+
+Command line convenience functions provided include:
+
+```sh
+python -m pymap3d.vdist
+python -m pymap3d.vreckon
+```
+
### array vs scalar
Use of pymap3d on embedded systems or other streaming data applications often deal with scalar position data.
=====================================
pyproject.toml
=====================================
@@ -1,6 +1,6 @@
[project]
name = "pymap3d"
-version = "2.5.1"
+version = "2.6.1"
description = "pure Python (no prereqs) coordinate conversions, following convention of several popular Matlab routines."
readme = "README.md"
requires-python = ">=3.7"
=====================================
setup.cfg
=====================================
@@ -1,6 +1,6 @@
[metadata]
name = pymap3d
-version = 2.6.0
+version = 2.7.0
author = Michael Hirsch, Ph.D.
author_email = scivision at users.noreply.github.com
description = pure Python (no prereqs) coordinate conversions, following convention of several popular Matlab routines.
=====================================
src/pymap3d/__init__.py
=====================================
@@ -30,7 +30,7 @@ Companion packages exist for:
"""
from .aer import ecef2aer, aer2ecef, geodetic2aer, aer2geodetic
-from .ellipsoid import Ellipsoid
+
from .enu import enu2geodetic, geodetic2enu, aer2enu, enu2aer
from .ned import ned2ecef, ned2geodetic, geodetic2ned, ecef2nedv, ned2aer, aer2ned, ecef2ned
from .ecef import (
@@ -45,34 +45,7 @@ from .ecef import (
uvw2enu,
)
from .sidereal import datetime2sidereal, greenwichsrt
-from .latitude import (
- geod2geoc,
- geoc2geod,
- geodetic2geocentric,
- geocentric2geodetic,
- geodetic2isometric,
- isometric2geodetic,
- geodetic2conformal,
- conformal2geodetic,
- geodetic2rectifying,
- rectifying2geodetic,
- geodetic2authalic,
- authalic2geodetic,
- geodetic2parametric,
- parametric2geodetic,
-)
-from .rcurve import geocentric_radius, rcurve_parallel, rcurve_meridian, rcurve_transverse
-from .rsphere import (
- rsphere_eqavol,
- rsphere_authalic,
- rsphere_rectifying,
- rsphere_euler,
- rsphere_curve,
- rsphere_triaxial,
- rsphere_biaxial,
-)
-from .lox import meridian_arc, meridian_dist, loxodrome_inverse, loxodrome_direct, departure, meanm
-from .los import lookAtSpheroid
+from .ellipsoid import Ellipsoid
from .timeconv import str2dt
try:
=====================================
src/pymap3d/ecef.py
=====================================
@@ -187,7 +187,7 @@ def ecef2geodetic(
try:
if inside.any(): # type: ignore
# avoid all false assignment bug
- alt[inside] = -alt
+ alt[inside] = -alt[inside]
except (TypeError, AttributeError):
if inside:
alt = -alt
=====================================
src/pymap3d/enu.py
=====================================
@@ -2,19 +2,18 @@
from __future__ import annotations
import typing
+from math import tau
+
try:
- from numpy import asarray, radians, sin, cos, hypot, arctan2 as atan2, degrees, pi, ndarray
+ from numpy import asarray, radians, sin, cos, hypot, arctan2 as atan2, degrees, ndarray
except ImportError:
- from math import radians, sin, cos, hypot, atan2, degrees, pi # type: ignore
+ from math import radians, sin, cos, hypot, atan2, degrees # type: ignore
ndarray = typing.Any # type: ignore
from .ecef import geodetic2ecef, ecef2geodetic, enu2ecef, uvw2enu
from .ellipsoid import Ellipsoid
-# py < 3.6 compatible
-tau = 2 * pi
-
__all__ = ["enu2aer", "aer2enu", "enu2geodetic", "geodetic2enu"]
=====================================
src/pymap3d/latitude.py
=====================================
@@ -2,9 +2,10 @@
from __future__ import annotations
import typing
+
from .ellipsoid import Ellipsoid
from .utils import sanitize
-from .rcurve import rcurve_transverse
+from . import rcurve
try:
from numpy import radians, degrees, tan, sin, exp, pi, sqrt, inf, ndarray
@@ -115,7 +116,7 @@ def geodetic2geocentric(
Office, Washington, DC, 1987, pp. 13-18.
"""
geodetic_lat, ell = sanitize(geodetic_lat, ell, deg)
- r = rcurve_transverse(geodetic_lat, ell, deg=False)
+ r = rcurve.transverse(geodetic_lat, ell, deg=False)
geocentric_lat = atan((1 - ell.eccentricity ** 2 * (r / (r + alt_m))) * tan(geodetic_lat))
return degrees(geocentric_lat) if deg else geocentric_lat
@@ -156,7 +157,7 @@ def geocentric2geodetic(
Office, Washington, DC, 1987, pp. 13-18.
"""
geocentric_lat, ell = sanitize(geocentric_lat, ell, deg)
- r = rcurve_transverse(geocentric_lat, ell, deg=False)
+ r = rcurve.transverse(geocentric_lat, ell, deg=False)
geodetic_lat = atan(tan(geocentric_lat) / (1 - ell.eccentricity ** 2 * (r / (r + alt_m))))
return degrees(geodetic_lat) if deg else geodetic_lat
=====================================
src/pymap3d/lox.py
=====================================
@@ -12,8 +12,8 @@ except ImportError:
import typing
from .ellipsoid import Ellipsoid
-from .rcurve import rcurve_parallel
-from .rsphere import rsphere_rectifying
+from . import rcurve
+from . import rsphere
from .latitude import (
geodetic2rectifying,
rectifying2geodetic,
@@ -79,7 +79,7 @@ def meridian_arc(lat1, lat2: ndarray, ell: Ellipsoid = None, deg: bool = True) -
rlat1 = geodetic2rectifying(lat1, ell, deg=False)
rlat2 = geodetic2rectifying(lat2, ell, deg=False)
- return rsphere_rectifying(ell) * abs(rlat2 - rlat1)
+ return rsphere.rectifying(ell) * abs(rlat2 - rlat1)
def loxodrome_inverse(
@@ -220,7 +220,7 @@ def loxodrome_direct(
# compute the new points
cosaz = cos(a12)
- lat2 = reclat + (rng / rsphere_rectifying(ell)) * cosaz # compute rectifying latitude
+ lat2 = reclat + (rng / rsphere.rectifying(ell)) * cosaz # compute rectifying latitude
lat2 = rectifying2geodetic(lat2, ell, deg=False) # transform to geodetic latitude
newiso = geodetic2isometric(lat2, ell, deg=False)
@@ -265,7 +265,7 @@ def departure(
if deg:
lon1, lon2, lat = radians(lon1), radians(lon2), radians(lat)
- return rcurve_parallel(lat, ell, deg=False) * ((lon2 - lon1) % pi)
+ return rcurve.parallel(lat, ell, deg=False) * ((lon2 - lon1) % pi)
def meanm(
=====================================
src/pymap3d/rcurve.py
=====================================
@@ -13,7 +13,7 @@ except ImportError:
from .ellipsoid import Ellipsoid
from .utils import sanitize
-__all__ = ["rcurve_parallel", "rcurve_meridian", "rcurve_transverse", "geocentric_radius"]
+__all__ = ["parallel", "meridian", "transverse", "geocentric_radius"]
def geocentric_radius(geodetic_lat: float, ell: Ellipsoid = None, deg: bool = True) -> float:
@@ -36,7 +36,7 @@ def geocentric_radius(geodetic_lat: float, ell: Ellipsoid = None, deg: bool = Tr
)
-def rcurve_parallel(lat: ndarray, ell: Ellipsoid = None, deg: bool = True) -> float:
+def parallel(lat: ndarray, ell: Ellipsoid = None, deg: bool = True) -> float:
"""
computes the radius of the small circle encompassing the globe at the specified latitude
@@ -58,10 +58,10 @@ def rcurve_parallel(lat: ndarray, ell: Ellipsoid = None, deg: bool = True) -> fl
if deg:
lat = radians(lat)
- return cos(lat) * rcurve_transverse(lat, ell, deg=False)
+ return cos(lat) * transverse(lat, ell, deg=False)
-def rcurve_meridian(lat: float, ell: Ellipsoid = None, deg: bool = True) -> float:
+def meridian(lat: float, ell: Ellipsoid = None, deg: bool = True) -> float:
"""computes the meridional radius of curvature for the ellipsoid
like Matlab rcurve('meridian', ...)
@@ -91,7 +91,7 @@ def rcurve_meridian(lat: float, ell: Ellipsoid = None, deg: bool = True) -> floa
return f1 / sqrt(f2 ** 3)
-def rcurve_transverse(lat: float | ndarray, ell: Ellipsoid = None, deg: bool = True) -> float:
+def transverse(lat: float | ndarray, ell: Ellipsoid = None, deg: bool = True) -> float:
"""computes the radius of the curve formed by a plane
intersecting the ellipsoid at the latitude which is
normal to the surface of the ellipsoid
=====================================
src/pymap3d/rsphere.py
=====================================
@@ -12,22 +12,22 @@ except ImportError:
ndarray = typing.Any # type: ignore
from .ellipsoid import Ellipsoid
-from .rcurve import rcurve_meridian, rcurve_transverse
+from . import rcurve
from .vincenty import vdist
__all__ = [
- "rsphere_eqavol",
- "rsphere_authalic",
- "rsphere_rectifying",
- "rsphere_euler",
- "rsphere_curve",
- "rsphere_triaxial",
- "rsphere_biaxial",
+ "eqavol",
+ "authalic",
+ "rectifying",
+ "euler",
+ "curve",
+ "triaxial",
+ "biaxial",
]
-def rsphere_eqavol(ell: Ellipsoid = None) -> float:
+def eqavol(ell: Ellipsoid = None) -> float:
"""computes the radius of the sphere with equal volume as the ellipsoid
Parameters
@@ -48,7 +48,7 @@ def rsphere_eqavol(ell: Ellipsoid = None) -> float:
return ell.semimajor_axis * (1 - f / 3 - f ** 2 / 9)
-def rsphere_authalic(ell: Ellipsoid = None) -> float:
+def authalic(ell: Ellipsoid = None) -> float:
"""computes the radius of the sphere with equal surface area as the ellipsoid
Parameters
@@ -75,7 +75,7 @@ def rsphere_authalic(ell: Ellipsoid = None) -> float:
return ell.semimajor_axis
-def rsphere_rectifying(ell: Ellipsoid = None) -> float:
+def rectifying(ell: Ellipsoid = None) -> float:
"""computes the radius of the sphere with equal meridional distances as the ellipsoid
Parameters
@@ -93,7 +93,7 @@ def rsphere_rectifying(ell: Ellipsoid = None) -> float:
return ((ell.semimajor_axis ** (3 / 2) + ell.semiminor_axis ** (3 / 2)) / 2) ** (2 / 3)
-def rsphere_euler(
+def euler(
lat1: ndarray,
lon1: ndarray,
lat2: ndarray,
@@ -131,8 +131,8 @@ def rsphere_euler(
az = vdist(lat1, lon1, lat2, lon2, ell=ell)[1]
# compute meridional and transverse radii of curvature
- rho = rcurve_meridian(latmid, ell, deg=True)
- nu = rcurve_transverse(latmid, ell, deg=True)
+ rho = rcurve.meridian(latmid, ell, deg=True)
+ nu = rcurve.transverse(latmid, ell, deg=True)
az = radians(az)
den = rho * sin(az) ** 2 + nu * cos(az) ** 2
@@ -141,9 +141,7 @@ def rsphere_euler(
return rho * nu / den
-def rsphere_curve(
- lat: float, ell: Ellipsoid = None, deg: bool = True, method: str = "mean"
-) -> float:
+def curve(lat: float, ell: Ellipsoid = None, deg: bool = True, method: str = "mean") -> float:
"""computes the arithmetic average of the transverse and meridional
radii of curvature at a specified latitude point
@@ -167,18 +165,18 @@ def rsphere_curve(
if deg:
lat = radians(lat)
- rho = rcurve_meridian(lat, ell, deg=False)
- nu = rcurve_transverse(lat, ell, deg=False)
+ rho = rcurve.meridian(lat, ell, deg=False)
+ nu = rcurve.transverse(lat, ell, deg=False)
if method == "mean":
return (rho + nu) / 2
elif method == "norm":
return sqrt(rho * nu)
else:
- raise Exception("pymap3d.rsphere.curve: method must be mean or norm")
+ raise ValueError("method must be mean or norm")
-def rsphere_triaxial(ell: Ellipsoid = None, method: str = "mean") -> float:
+def triaxial(ell: Ellipsoid = None, method: str = "mean") -> float:
"""computes triaxial average of the semimajor and semiminor axes of the ellipsoid
Parameters
@@ -202,10 +200,10 @@ def rsphere_triaxial(ell: Ellipsoid = None, method: str = "mean") -> float:
elif method == "norm":
return (ell.semimajor_axis ** 2 * ell.semiminor_axis) ** (1 / 3)
else:
- raise Exception("pymap3d.rsphere.rsphere_triaxial: method must be mean or norm")
+ raise ValueError("method must be mean or norm")
-def rsphere_biaxial(ell: Ellipsoid = None, method: str = "mean") -> float:
+def biaxial(ell: Ellipsoid = None, method: str = "mean") -> float:
"""computes biaxial average of the semimajor and semiminor axes of the ellipsoid
Parameters
@@ -229,4 +227,4 @@ def rsphere_biaxial(ell: Ellipsoid = None, method: str = "mean") -> float:
elif method == "norm":
return sqrt(ell.semimajor_axis * ell.semiminor_axis)
else:
- raise Exception("pymap3d.rsphere.rsphere_biaxial: method must be mean or norm")
+ raise ValueError("method must be mean or norm")
=====================================
src/pymap3d/tests/test_geodetic.py
=====================================
@@ -55,6 +55,38 @@ def test_3d_ecef2geodetic():
assert [lat, lon, alt] == approx(lla0, rel=1e-4)
+def test_array_ecef2geodetic():
+ """
+ tests ecef2geodetic can handle numpy array data in addition to singular floats
+ """
+ np = pytest.importorskip("numpy")
+ # test values with no points inside ellipsoid
+ lla0_array = (
+ np.array([lla0[0], lla0[0]]),
+ np.array([lla0[1], lla0[1]]),
+ np.array([lla0[2], lla0[2]]),
+ )
+ xyz = pm.geodetic2ecef(*lla0_array)
+ lats, lons, alts = pm.ecef2geodetic(*xyz)
+
+ assert lats == approx(lla0_array[0])
+ assert lons == approx(lla0_array[1])
+ assert alts == approx(lla0_array[2])
+
+ # test values with some (but not all) points inside ellipsoid
+ lla0_array_inside = (
+ np.array([lla0[0], lla0[0]]),
+ np.array([lla0[1], lla0[1]]),
+ np.array([lla0[2], -lla0[2]]),
+ )
+ xyz = pm.geodetic2ecef(*lla0_array_inside)
+ lats, lons, alts = pm.ecef2geodetic(*xyz)
+
+ assert lats == approx(lla0_array_inside[0])
+ assert lons == approx(lla0_array_inside[1])
+ assert alts == approx(lla0_array_inside[2])
+
+
def test_xarray():
xarray = pytest.importorskip("xarray")
xr_lla = xarray.DataArray(list(lla0))
=====================================
src/pymap3d/tests/test_latitude.py
=====================================
@@ -2,7 +2,8 @@ import pytest
from pytest import approx
from math import radians, inf
-import pymap3d as pm
+import pymap3d.latitude as latitude
+import pymap3d.rcurve as rcurve
@pytest.mark.parametrize(
@@ -10,16 +11,16 @@ import pymap3d as pm
[(0, 0, 0), (90, 0, 90), (-90, 0, -90), (45, 0, 44.80757678), (-45, 0, -44.80757678)],
)
def test_geodetic_alt_geocentric(geodetic_lat, alt_m, geocentric_lat):
- assert pm.geod2geoc(geodetic_lat, alt_m) == approx(geocentric_lat)
+ assert latitude.geod2geoc(geodetic_lat, alt_m) == approx(geocentric_lat)
- r = pm.geocentric_radius(geodetic_lat)
- assert pm.geoc2geod(geocentric_lat, r) == approx(geodetic_lat)
- assert pm.geoc2geod(geocentric_lat, 1e5 + r) == approx(
- pm.geocentric2geodetic(geocentric_lat, 1e5 + alt_m)
+ r = rcurve.geocentric_radius(geodetic_lat)
+ assert latitude.geoc2geod(geocentric_lat, r) == approx(geodetic_lat)
+ assert latitude.geoc2geod(geocentric_lat, 1e5 + r) == approx(
+ latitude.geocentric2geodetic(geocentric_lat, 1e5 + alt_m)
)
- assert pm.geod2geoc(geodetic_lat, 1e5 + alt_m) == approx(
- pm.geodetic2geocentric(geodetic_lat, 1e5 + alt_m)
+ assert latitude.geod2geoc(geodetic_lat, 1e5 + alt_m) == approx(
+ latitude.geodetic2geocentric(geodetic_lat, 1e5 + alt_m)
)
@@ -29,21 +30,21 @@ def test_geodetic_alt_geocentric(geodetic_lat, alt_m, geocentric_lat):
)
def test_geodetic_geocentric(geodetic_lat, geocentric_lat):
- assert pm.geodetic2geocentric(geodetic_lat, 0) == approx(geocentric_lat)
- assert pm.geodetic2geocentric(radians(geodetic_lat), 0, deg=False) == approx(
+ assert latitude.geodetic2geocentric(geodetic_lat, 0) == approx(geocentric_lat)
+ assert latitude.geodetic2geocentric(radians(geodetic_lat), 0, deg=False) == approx(
radians(geocentric_lat)
)
- assert pm.geocentric2geodetic(geocentric_lat, 0) == approx(geodetic_lat)
- assert pm.geocentric2geodetic(radians(geocentric_lat), 0, deg=False) == approx(
+ assert latitude.geocentric2geodetic(geocentric_lat, 0) == approx(geodetic_lat)
+ assert latitude.geocentric2geodetic(radians(geocentric_lat), 0, deg=False) == approx(
radians(geodetic_lat)
)
def test_numpy_geodetic_geocentric():
pytest.importorskip("numpy")
- assert pm.geodetic2geocentric([45, 0], 0) == approx([44.80757678, 0])
- assert pm.geocentric2geodetic([44.80757678, 0], 0) == approx([45, 0])
+ assert latitude.geodetic2geocentric([45, 0], 0) == approx([44.80757678, 0])
+ assert latitude.geocentric2geodetic([44.80757678, 0], 0) == approx([45, 0])
@pytest.mark.parametrize(
@@ -51,20 +52,24 @@ def test_numpy_geodetic_geocentric():
[(0, 0), (90, inf), (-90, -inf), (45, 50.227466), (-45, -50.227466), (89, 271.275)],
)
def test_geodetic_isometric(geodetic_lat, isometric_lat):
- isolat = pm.geodetic2isometric(geodetic_lat)
+ isolat = latitude.geodetic2isometric(geodetic_lat)
assert isolat == approx(isometric_lat)
assert isinstance(isolat, float)
- assert pm.geodetic2isometric(radians(geodetic_lat), deg=False) == approx(radians(isometric_lat))
+ assert latitude.geodetic2isometric(radians(geodetic_lat), deg=False) == approx(
+ radians(isometric_lat)
+ )
- assert pm.isometric2geodetic(isometric_lat) == approx(geodetic_lat)
- assert pm.isometric2geodetic(radians(isometric_lat), deg=False) == approx(radians(geodetic_lat))
+ assert latitude.isometric2geodetic(isometric_lat) == approx(geodetic_lat)
+ assert latitude.isometric2geodetic(radians(isometric_lat), deg=False) == approx(
+ radians(geodetic_lat)
+ )
def test_numpy_geodetic_isometric():
pytest.importorskip("numpy")
- assert pm.geodetic2isometric([45, 0]) == approx([50.227466, 0])
- assert pm.isometric2geodetic([50.227466, 0]) == approx([45, 0])
+ assert latitude.geodetic2isometric([45, 0]) == approx([50.227466, 0])
+ assert latitude.isometric2geodetic([50.227466, 0]) == approx([45, 0])
@pytest.mark.parametrize(
@@ -72,20 +77,24 @@ def test_numpy_geodetic_isometric():
[(0, 0), (90, 90), (-90, -90), (45, 44.80768406), (-45, -44.80768406), (89, 88.99327)],
)
def test_geodetic_conformal(geodetic_lat, conformal_lat):
- clat = pm.geodetic2conformal(geodetic_lat)
+ clat = latitude.geodetic2conformal(geodetic_lat)
assert clat == approx(conformal_lat)
assert isinstance(clat, float)
- assert pm.geodetic2conformal(radians(geodetic_lat), deg=False) == approx(radians(conformal_lat))
+ assert latitude.geodetic2conformal(radians(geodetic_lat), deg=False) == approx(
+ radians(conformal_lat)
+ )
- assert pm.conformal2geodetic(conformal_lat) == approx(geodetic_lat)
- assert pm.conformal2geodetic(radians(conformal_lat), deg=False) == approx(radians(geodetic_lat))
+ assert latitude.conformal2geodetic(conformal_lat) == approx(geodetic_lat)
+ assert latitude.conformal2geodetic(radians(conformal_lat), deg=False) == approx(
+ radians(geodetic_lat)
+ )
def test_numpy_geodetic_conformal():
pytest.importorskip("numpy")
- assert pm.geodetic2conformal([45, 0]) == approx([44.80768406, 0])
- assert pm.conformal2geodetic([44.80768406, 0]) == approx([45, 0])
+ assert latitude.geodetic2conformal([45, 0]) == approx([44.80768406, 0])
+ assert latitude.conformal2geodetic([44.80768406, 0]) == approx([45, 0])
@pytest.mark.parametrize(
@@ -93,21 +102,21 @@ def test_numpy_geodetic_conformal():
[(0, 0), (90, 90), (-90, -90), (45, 44.855682), (-45, -44.855682)],
)
def test_geodetic_rectifying(geodetic_lat, rectifying_lat):
- assert pm.geodetic2rectifying(geodetic_lat) == approx(rectifying_lat)
- assert pm.geodetic2rectifying(radians(geodetic_lat), deg=False) == approx(
+ assert latitude.geodetic2rectifying(geodetic_lat) == approx(rectifying_lat)
+ assert latitude.geodetic2rectifying(radians(geodetic_lat), deg=False) == approx(
radians(rectifying_lat)
)
- assert pm.rectifying2geodetic(rectifying_lat) == approx(geodetic_lat)
- assert pm.rectifying2geodetic(radians(rectifying_lat), deg=False) == approx(
+ assert latitude.rectifying2geodetic(rectifying_lat) == approx(geodetic_lat)
+ assert latitude.rectifying2geodetic(radians(rectifying_lat), deg=False) == approx(
radians(geodetic_lat)
)
def test_numpy_geodetic_rectifying():
pytest.importorskip("numpy")
- assert pm.geodetic2rectifying([45, 0]) == approx([44.855682, 0])
- assert pm.rectifying2geodetic([44.855682, 0]) == approx([45, 0])
+ assert latitude.geodetic2rectifying([45, 0]) == approx([44.855682, 0])
+ assert latitude.rectifying2geodetic([44.855682, 0]) == approx([45, 0])
@pytest.mark.parametrize(
@@ -115,17 +124,21 @@ def test_numpy_geodetic_rectifying():
[(0, 0), (90, 90), (-90, -90), (45, 44.87170288), (-45, -44.87170288)],
)
def test_geodetic_authalic(geodetic_lat, authalic_lat):
- assert pm.geodetic2authalic(geodetic_lat) == approx(authalic_lat)
- assert pm.geodetic2authalic(radians(geodetic_lat), deg=False) == approx(radians(authalic_lat))
+ assert latitude.geodetic2authalic(geodetic_lat) == approx(authalic_lat)
+ assert latitude.geodetic2authalic(radians(geodetic_lat), deg=False) == approx(
+ radians(authalic_lat)
+ )
- assert pm.authalic2geodetic(authalic_lat) == approx(geodetic_lat)
- assert pm.authalic2geodetic(radians(authalic_lat), deg=False) == approx(radians(geodetic_lat))
+ assert latitude.authalic2geodetic(authalic_lat) == approx(geodetic_lat)
+ assert latitude.authalic2geodetic(radians(authalic_lat), deg=False) == approx(
+ radians(geodetic_lat)
+ )
def test_numpy_geodetic_authalic():
pytest.importorskip("numpy")
- assert pm.geodetic2authalic([45, 0]) == approx([44.87170288, 0])
- assert pm.authalic2geodetic([44.87170288, 0]) == approx([45, 0])
+ assert latitude.geodetic2authalic([45, 0]) == approx([44.87170288, 0])
+ assert latitude.authalic2geodetic([44.87170288, 0]) == approx([45, 0])
@pytest.mark.parametrize(
@@ -133,43 +146,43 @@ def test_numpy_geodetic_authalic():
[(0, 0), (90, 90), (-90, -90), (45, 44.9037878), (-45, -44.9037878)],
)
def test_geodetic_parametric(geodetic_lat, parametric_lat):
- assert pm.geodetic2parametric(geodetic_lat) == approx(parametric_lat)
- assert pm.geodetic2parametric(radians(geodetic_lat), deg=False) == approx(
+ assert latitude.geodetic2parametric(geodetic_lat) == approx(parametric_lat)
+ assert latitude.geodetic2parametric(radians(geodetic_lat), deg=False) == approx(
radians(parametric_lat)
)
- assert pm.parametric2geodetic(parametric_lat) == approx(geodetic_lat)
- assert pm.parametric2geodetic(radians(parametric_lat), deg=False) == approx(
+ assert latitude.parametric2geodetic(parametric_lat) == approx(geodetic_lat)
+ assert latitude.parametric2geodetic(radians(parametric_lat), deg=False) == approx(
radians(geodetic_lat)
)
def test_numpy_geodetic_parametric():
pytest.importorskip("numpy")
- assert pm.geodetic2parametric([45, 0]) == approx([44.9037878, 0])
- assert pm.parametric2geodetic([44.9037878, 0]) == approx([45, 0])
+ assert latitude.geodetic2parametric([45, 0]) == approx([44.9037878, 0])
+ assert latitude.parametric2geodetic([44.9037878, 0]) == approx([45, 0])
@pytest.mark.parametrize("lat", [91, -91])
def test_badvals(lat):
# geodetic_isometric is not included on purpose
with pytest.raises(ValueError):
- pm.geodetic2geocentric(lat, 0)
+ latitude.geodetic2geocentric(lat, 0)
with pytest.raises(ValueError):
- pm.geocentric2geodetic(lat, 0)
+ latitude.geocentric2geodetic(lat, 0)
with pytest.raises(ValueError):
- pm.geodetic2conformal(lat)
+ latitude.geodetic2conformal(lat)
with pytest.raises(ValueError):
- pm.conformal2geodetic(lat)
+ latitude.conformal2geodetic(lat)
with pytest.raises(ValueError):
- pm.geodetic2rectifying(lat)
+ latitude.geodetic2rectifying(lat)
with pytest.raises(ValueError):
- pm.rectifying2geodetic(lat)
+ latitude.rectifying2geodetic(lat)
with pytest.raises(ValueError):
- pm.geodetic2authalic(lat)
+ latitude.geodetic2authalic(lat)
with pytest.raises(ValueError):
- pm.authalic2geodetic(lat)
+ latitude.authalic2geodetic(lat)
with pytest.raises(ValueError):
- pm.geodetic2parametric(lat)
+ latitude.geodetic2parametric(lat)
with pytest.raises(ValueError):
- pm.parametric2geodetic(lat)
+ latitude.parametric2geodetic(lat)
=====================================
src/pymap3d/tests/test_look_spheroid.py
=====================================
@@ -1,8 +1,10 @@
import pytest
from pytest import approx
-import pymap3d as pm
+
from math import nan
+import pymap3d.los as los
+
@pytest.mark.parametrize(
"az,tilt,lat,lon,sr",
@@ -17,7 +19,7 @@ from math import nan
def test_losint(az, tilt, lat, lon, sr):
lla0 = (10, -20, 1e3)
- lat1, lon1, sr1 = pm.lookAtSpheroid(*lla0, az, tilt=tilt)
+ lat1, lon1, sr1 = los.lookAtSpheroid(*lla0, az, tilt=tilt)
nan_ok = True if tilt == 90 else False
@@ -32,7 +34,7 @@ def test_losint(az, tilt, lat, lon, sr):
def test_badval():
with pytest.raises(ValueError):
- pm.lookAtSpheroid(0, 0, -1, 0, 0)
+ los.lookAtSpheroid(0, 0, -1, 0, 0)
def test_array():
@@ -41,7 +43,7 @@ def test_array():
az = [0.0, 10.0, 125.0]
tilt = [30.0, 45.0, 90.0]
lla0 = (42, -82, 200)
- lat, lon, sr = pm.lookAtSpheroid(*lla0, az, tilt)
+ lat, lon, sr = los.lookAtSpheroid(*lla0, az, tilt)
truth = np.array(
[
=====================================
src/pymap3d/tests/test_rcurve.py
=====================================
@@ -1,6 +1,8 @@
import pytest
from pytest import approx
+
import pymap3d as pm
+import pymap3d.rcurve as rcurve
ell = pm.Ellipsoid()
A = ell.semimajor_axis
@@ -10,12 +12,12 @@ A = ell.semimajor_axis
"lat,curvature", [(0, A), (90, 0), (-90, 0), (45.0, 4517590.87884893), (-45, 4517590.87884893)]
)
def test_rcurve_parallel(lat, curvature):
- assert pm.rcurve_parallel(lat) == approx(curvature, abs=1e-9)
+ assert rcurve.parallel(lat) == approx(curvature, abs=1e-9)
def test_numpy_parallel():
pytest.importorskip("numpy")
- assert pm.rcurve_parallel([0, 90]) == approx([A, 0], abs=1e-9)
+ assert rcurve.parallel([0, 90]) == approx([A, 0], abs=1e-9)
@pytest.mark.parametrize(
@@ -29,14 +31,14 @@ def test_numpy_parallel():
],
)
def test_rcurve_meridian(lat, curvature):
- assert pm.rcurve_meridian(lat) == approx(curvature)
+ assert rcurve.meridian(lat) == approx(curvature)
def test_numpy_meridian():
pytest.importorskip("numpy")
- assert pm.rcurve_meridian([0, 90]) == approx([6335439.327, 6399593.6258])
+ assert rcurve.meridian([0, 90]) == approx([6335439.327, 6399593.6258])
def test_numpy_transverse():
pytest.importorskip("numpy")
- assert pm.rcurve_transverse([0, 90]) == approx([A, 6399593.626])
+ assert rcurve.transverse([0, 90]) == approx([A, 6399593.626])
=====================================
src/pymap3d/tests/test_rhumb.py
=====================================
@@ -1,11 +1,12 @@
import pytest
from pytest import approx
-import pymap3d as pm
+
+import pymap3d.lox as lox
@pytest.mark.parametrize("lat,dist", [(0, 0), (90, 10001965.729)])
def test_meridian_dist(lat, dist):
- assert pm.meridian_dist(lat) == approx(dist)
+ assert lox.meridian_dist(lat) == approx(dist)
@pytest.mark.parametrize(
@@ -23,7 +24,7 @@ def test_meridian_arc(lat1, lat2, arclen):
meridianarc(deg2rad(40), deg2rad(80), wgs84Ellipsoid)
"""
- assert pm.meridian_arc(lat1, lat2) == approx(arclen)
+ assert lox.meridian_arc(lat1, lat2) == approx(arclen)
@pytest.mark.parametrize(
@@ -37,7 +38,7 @@ def test_meridian_arc(lat1, lat2, arclen):
],
)
def test_departure(lon1, lon2, lat, dist):
- assert pm.departure(lon1, lon2, lat) == approx(dist)
+ assert lox.departure(lon1, lon2, lat) == approx(dist)
@pytest.mark.parametrize(
@@ -57,7 +58,7 @@ def test_loxodrome_inverse(lat1, lon1, lat2, lon2, arclen, az):
distance('rh', 40, -80, 65, -148, wgs84Ellipsoid)
azimuth('rh', 40, -80, 65, -148, wgs84Ellipsoid)
"""
- rhdist, rhaz = pm.loxodrome_inverse(lat1, lon1, lat2, lon2)
+ rhdist, rhaz = lox.loxodrome_inverse(lat1, lon1, lat2, lon2)
assert rhdist == approx(arclen)
assert rhaz == approx(az)
@@ -67,7 +68,7 @@ def test_loxodrome_inverse(lat1, lon1, lat2, lon2, arclen, az):
def test_numpy_loxodrome_inverse():
pytest.importorskip("numpy")
- d, a = pm.loxodrome_inverse([40, 40], [-80, -80], 65, -148)
+ d, a = lox.loxodrome_inverse([40, 40], [-80, -80], 65, -148)
assert d == approx(5248666.209)
assert a == approx(302.00567)
@@ -85,7 +86,7 @@ def test_numpy_loxodrome_inverse():
],
)
def test_loxodrome_direct(lat0, lon0, rng, az, lat1, lon1):
- lat2, lon2 = pm.loxodrome_direct(lat0, lon0, rng, az)
+ lat2, lon2 = lox.loxodrome_direct(lat0, lon0, rng, az)
assert lat2 == approx(lat1, abs=1e-6)
assert lon2 == approx(lon1)
assert isinstance(lat2, float)
@@ -94,7 +95,7 @@ def test_loxodrome_direct(lat0, lon0, rng, az, lat1, lon1):
def test_numpy_loxodrome_direct():
pytest.importorskip("numpy")
- lat, lon = pm.loxodrome_direct([40, 40], [-80, -80], [10000, 10000], [30, 30])
+ lat, lon = lox.loxodrome_direct([40, 40], [-80, -80], [10000, 10000], [30, 30])
assert lat == approx(40.077995)
assert lon == approx(-79.941414)
@@ -102,4 +103,4 @@ def test_numpy_loxodrome_direct():
@pytest.mark.parametrize("lat,lon", [([0, 45, 90], [0, 45, 90])])
def test_meanm(lat, lon):
pytest.importorskip("numpy")
- assert pm.meanm(lat, lon) == approx([47.26967, 18.460557])
+ assert lox.meanm(lat, lon) == approx([47.26967, 18.460557])
=====================================
src/pymap3d/tests/test_rsphere.py
=====================================
@@ -1,48 +1,51 @@
import pytest
from pytest import approx
+
import pymap3d as pm
+import pymap3d.rsphere as rsphere
+import pymap3d.rcurve as rcurve
ell = pm.Ellipsoid()
A = ell.semimajor_axis
def test_geocentric_radius():
- assert pm.geocentric_radius(0) == approx(ell.semimajor_axis)
- assert pm.geocentric_radius(90) == approx(ell.semiminor_axis)
- assert pm.geocentric_radius(45) == approx(6367490.0)
- assert pm.geocentric_radius(30) == approx(6372824.0)
+ assert rcurve.geocentric_radius(0) == approx(ell.semimajor_axis)
+ assert rcurve.geocentric_radius(90) == approx(ell.semiminor_axis)
+ assert rcurve.geocentric_radius(45) == approx(6367490.0)
+ assert rcurve.geocentric_radius(30) == approx(6372824.0)
@pytest.mark.parametrize("bad_lat", [-91, 91])
def test_geocentric_radius_badval(bad_lat):
with pytest.raises(ValueError):
- pm.geocentric_radius(bad_lat)
+ rcurve.geocentric_radius(bad_lat)
def test_rsphere_eqavol():
- assert pm.rsphere_eqavol() == approx(6371000.8049)
+ assert rsphere.eqavol() == approx(6371000.8049)
def test_rsphere_authalic():
- assert pm.rsphere_authalic() == approx(6371007.1809)
+ assert rsphere.authalic() == approx(6371007.1809)
def test_rsphere_rectifying():
- assert pm.rsphere_rectifying() == approx(6367449.1458)
+ assert rsphere.rectifying() == approx(6367449.1458)
def test_rsphere_biaxial():
- assert pm.rsphere_biaxial() == approx(6367444.657)
+ assert rsphere.biaxial() == approx(6367444.657)
def test_rsphere_triaxial():
- assert pm.rsphere_triaxial() == approx(6371008.77)
+ assert rsphere.triaxial() == approx(6371008.77)
def test_rsphere_euler():
- assert pm.rsphere_euler(42, 82, 44, 100) == approx(6386606.829131)
+ assert rsphere.euler(42, 82, 44, 100) == approx(6386606.829131)
def test_numpy_rsphere_euler():
pytest.importorskip("numpy")
- assert pm.rsphere_euler([42, 0], [82, 0], 44, 100) == approx([6386606.829131, 6363111.70923164])
+ assert rsphere.euler([42, 0], [82, 0], 44, 100) == approx([6386606.829131, 6363111.70923164])
=====================================
src/pymap3d/utils.py
=====================================
@@ -16,7 +16,7 @@ except ImportError:
ndarray = typing.Any # type: ignore
def sign(x: float) -> float: # type: ignore
- """ signum function """
+ """signum function"""
if x < 0:
y = -1.0
elif x > 0:
=====================================
src/pymap3d/vdist/__init__.py
=====================================
=====================================
src/pymap3d/vdist/__main__.py
=====================================
@@ -0,0 +1,14 @@
+import argparse
+
+from .. import vincenty
+
+p = argparse.ArgumentParser(description="Vincenty algorithms")
+p.add_argument("lat1", help="latitude1 WGS-84 [degrees]", type=float)
+p.add_argument("lon1", help="longitude1 WGS-84 [degrees]", type=float)
+p.add_argument("lat2", help="latitude2 WGS-84 [degrees]", type=float)
+p.add_argument("lon2", help="longitude2 WGS-84 [degrees]", type=float)
+P = p.parse_args()
+
+dist_m = vincenty.vdist(P.lat1, P.lon1, P.lat2, P.lon2)
+
+print("{:.3f} meters {:.3f} deg azimuth".format(*dist_m))
=====================================
src/pymap3d/vreckon/__init__.py
=====================================
=====================================
src/pymap3d/vreckon/__main__.py
=====================================
@@ -0,0 +1,16 @@
+from .. import vincenty
+import argparse
+
+
+p = argparse.ArgumentParser(
+ description="Given starting latitude, longitude: find final lat,lon for distance and azimuth"
+)
+p.add_argument("lat", help="latitude WGS-84 [degrees]", type=float)
+p.add_argument("lon", help="longitude WGS-84 [degrees]", type=float)
+p.add_argument("range", help="range from start point [meters]", type=float)
+p.add_argument("azimuth", help="clockwise from north: azimuth to start [degrees]", type=float)
+P = p.parse_args()
+
+lat2, lon2 = vincenty.vreckon(P.lat, P.lon, P.range, P.azimuth)
+
+print("lat, lon = ({:.4f}, {:.4f})".format(lat2.item(), lon2.item()))
View it on GitLab: https://salsa.debian.org/debian-gis-team/pymap3d/-/commit/2e27887770fee03a3dac29a4a1322f7967afd46b
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/pymap3d/-/commit/2e27887770fee03a3dac29a4a1322f7967afd46b
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20210817/b0d06afc/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list