pygeodesy 25.5.25__py2.py3-none-any.whl → 25.7.25__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pygeodesy/__init__.py +8 -8
- pygeodesy/__main__.py +2 -1
- pygeodesy/booleans.py +10 -10
- pygeodesy/constants.py +6 -6
- pygeodesy/css.py +1 -1
- pygeodesy/ellipsoidalBase.py +52 -58
- pygeodesy/ellipsoidalExact.py +22 -27
- pygeodesy/ellipsoidalGeodSolve.py +19 -19
- pygeodesy/ellipsoidalKarney.py +22 -27
- pygeodesy/ellipsoidalVincenty.py +12 -11
- pygeodesy/elliptic.py +258 -232
- pygeodesy/fmath.py +6 -4
- pygeodesy/frechet.py +2 -2
- pygeodesy/fsums.py +40 -18
- pygeodesy/geodesici.py +3 -3
- pygeodesy/geodesicw.py +27 -8
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +2 -2
- pygeodesy/geodesicx/gx.py +53 -48
- pygeodesy/geodesicx/gxarea.py +56 -68
- pygeodesy/geodesicx/gxbases.py +14 -3
- pygeodesy/geodesicx/gxline.py +9 -6
- pygeodesy/geoids.py +1 -1
- pygeodesy/hausdorff.py +2 -2
- pygeodesy/heights.py +4 -4
- pygeodesy/internals.py +2 -2
- pygeodesy/interns.py +5 -5
- pygeodesy/karney.py +27 -11
- pygeodesy/lcc.py +2 -2
- pygeodesy/props.py +3 -3
- pygeodesy/sphericalBase.py +3 -3
- pygeodesy/sphericalNvector.py +18 -15
- pygeodesy/sphericalTrigonometry.py +19 -20
- pygeodesy/vector2d.py +2 -2
- {pygeodesy-25.5.25.dist-info → pygeodesy-25.7.25.dist-info}/METADATA +8 -8
- {pygeodesy-25.5.25.dist-info → pygeodesy-25.7.25.dist-info}/RECORD +38 -38
- {pygeodesy-25.5.25.dist-info → pygeodesy-25.7.25.dist-info}/WHEEL +0 -0
- {pygeodesy-25.5.25.dist-info → pygeodesy-25.7.25.dist-info}/top_level.txt +0 -0
pygeodesy/__init__.py
CHANGED
|
@@ -125,7 +125,7 @@ C{epydoc --html --no-private --no-source --name=pygeodesy --url=... -v pygeodesy
|
|
|
125
125
|
Tests
|
|
126
126
|
=====
|
|
127
127
|
|
|
128
|
-
The tests ran with Python 3.13.
|
|
128
|
+
The tests ran with Python 3.13.5 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 2.0),
|
|
129
129
|
Python 3.12.7 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 2.0,
|
|
130
130
|
U{numpy<https://PyPI.org/project/numpy>} 2.1.0, U{scipy<https://PyPI.org/project/scipy>} 1.14.1,
|
|
131
131
|
U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.5,
|
|
@@ -150,13 +150,13 @@ env variable C{PYGEODESY_WARNINGS=on} for all Python versions. The results of t
|
|
|
150
150
|
the distribution files.
|
|
151
151
|
|
|
152
152
|
Test coverage has been measured with U{coverage<https://PyPI.org/project/coverage>} 7.6.1 using Python
|
|
153
|
-
3.13.
|
|
153
|
+
3.13.4, 3.12.7, 3.11.5 and 3.10.8. The complete coverage report in HTML and a PDF summary are included in
|
|
154
154
|
the distribution files.
|
|
155
155
|
|
|
156
|
-
Python 3.13.
|
|
156
|
+
Python 3.13.5, 3.12.7, 3.11.5 and 3.10.8 run on Apple M4 Si (C{arm64}), I{natively}. Python 2.7.18 runs
|
|
157
157
|
on Intel (C{x86_64}) or Intel I{emulation} ("C{arm64_x86_64}", see function L{machine<pygeodesy.machine>}).
|
|
158
158
|
|
|
159
|
-
The tests also ran with Python 3.13.
|
|
159
|
+
The tests also ran with Python 3.13.5 (and U{geographiclib<https://PyPI.org/project/geographiclib>} 2.0) on
|
|
160
160
|
U{Debian 12<https://Cirrus-CI.com/github/mrJean1/PyGeodesy/master>} in 64-bit only, with Python 3.12.8 (and
|
|
161
161
|
U{geographiclib<https://PyPI.org/project/geographiclib>} 2.0) on U{Windows 2019Server
|
|
162
162
|
<https://CI.AppVeyor.com/project/mrJean1/pygeodesy>} in 64-bit only and with Python 2.7.18 (and U{geographiclib
|
|
@@ -166,7 +166,7 @@ in 64- and 32-bit.
|
|
|
166
166
|
A single-File and single-Directory application with C{pygeodesy} has been bundled using U{PyInstaller
|
|
167
167
|
<https://PyPI.org/project/pyinstaller>} 3.4 and 64-bit Python 3.7.3 on macOS 10.13.6 High Sierra.
|
|
168
168
|
|
|
169
|
-
Previously, the tests were run with Python 3.13.0-
|
|
169
|
+
Previously, the tests were run with Python 3.13.0-4, 3.12.0-6, 3.11.2-4, 3.10.1-7, 3.9.6, 3.9.1, 3.8.7, 3.7.1, 2.7.15,
|
|
170
170
|
U{PyPy<https://PyPy.org>} 7.3.12 (Python 3.10.12), 7.3.1 (Python 3.6.9) and U{PyPy<https://PyPy.org>} 7.1.1 (Python
|
|
171
171
|
2.7.13) (and U{geographiclib <https://PyPI.org/project/geographiclib>} 1.52, U{numpy<https://PyPI.org/project/numpy>}
|
|
172
172
|
1.16.3, 1.16.4, 1.16.6, 1.19.0, 1.19.4, 1.19.5 or 1.22.4 and U{scipy<https://PyPI.org/project/scipy>} 1.2.1, 1.4.1,
|
|
@@ -187,10 +187,10 @@ Notes
|
|
|
187
187
|
=====
|
|
188
188
|
|
|
189
189
|
All Python source code has been statically U{checked<https://GitHub.com/ActiveState/code/tree/master/recipes/Python/
|
|
190
|
-
546532_PyChecker_postprocessor>} with U{Ruff<https://GitHub.com/astral-sh/ruff>} using Python 3.13.
|
|
190
|
+
546532_PyChecker_postprocessor>} with U{Ruff<https://GitHub.com/astral-sh/ruff>} using Python 3.13.5 and with
|
|
191
191
|
U{PyChecker<https://PyPI.org/project/pychecker>}, U{PyFlakes<https://PyPI.org/project/pyflakes>}, U{PyCodeStyle
|
|
192
192
|
<https://PyPI.org/project/pycodestyle>} (formerly Pep8) and U{McCabe<https://PyPI.org/project/mccabe>} using Python
|
|
193
|
-
2.7.18, both in 64-bit on macOS 15.5 Sequoia
|
|
193
|
+
2.7.18, both in 64-bit on macOS 15.5 Sequoia.
|
|
194
194
|
|
|
195
195
|
For a summary of all I{Karney}-based functionality in C{pygeodesy}, see module U{karney
|
|
196
196
|
<https://mrJean1.GitHub.io/PyGeodesy/docs/pygeodesy.karney-module.html>}.
|
|
@@ -604,7 +604,7 @@ else:
|
|
|
604
604
|
|
|
605
605
|
from pygeodesy.internals import _version2, _DOT_ # noqa: E402
|
|
606
606
|
# from pygeodesy.interns import _DOT_ # from .internals
|
|
607
|
-
__version__ = '25.
|
|
607
|
+
__version__ = '25.07.25'
|
|
608
608
|
# see setup.py for similar logic
|
|
609
609
|
version = _DOT_(*_version2(__version__, n=3))
|
|
610
610
|
|
pygeodesy/__main__.py
CHANGED
|
@@ -5,7 +5,7 @@ u'''Print L{pygeodesy} version, etc. using C{python -m pygeodesy}.
|
|
|
5
5
|
'''
|
|
6
6
|
|
|
7
7
|
__all__ = ()
|
|
8
|
-
__version__ = '25.
|
|
8
|
+
__version__ = '25.06.26'
|
|
9
9
|
|
|
10
10
|
from os.path import basename, dirname
|
|
11
11
|
|
|
@@ -28,6 +28,7 @@ def _main(): # PYCHOK no cover
|
|
|
28
28
|
('isLazy', isLazy),
|
|
29
29
|
('_isfrozen', _isfrozen),
|
|
30
30
|
('_floats', len(constants._floats)),
|
|
31
|
+
# ('_interns', len(interns.__dict__) - 22),
|
|
31
32
|
(_DALL_, len(_all_imports())),
|
|
32
33
|
(_DEPRECATED_, len(_all_deprecates()))))
|
|
33
34
|
|
pygeodesy/booleans.py
CHANGED
|
@@ -45,7 +45,7 @@ from pygeodesy.utily import fabs, _unrollon, _Wrap
|
|
|
45
45
|
# from math import fabs # from .utily
|
|
46
46
|
|
|
47
47
|
__all__ = _ALL_LAZY.booleans
|
|
48
|
-
__version__ = '25.05.
|
|
48
|
+
__version__ = '25.05.26'
|
|
49
49
|
|
|
50
50
|
_0EPS = EPS # near-zero, positive
|
|
51
51
|
_EPS0 = -EPS # near-zero, negative
|
|
@@ -199,8 +199,8 @@ class _LatLonBool(_Named):
|
|
|
199
199
|
|
|
200
200
|
def __sub__(self, other):
|
|
201
201
|
_other(self, other)
|
|
202
|
-
return self
|
|
203
|
-
|
|
202
|
+
return type(self)(self.y - other.y, # classof
|
|
203
|
+
self.x - other.x)
|
|
204
204
|
|
|
205
205
|
def _2A(self, p2, p3):
|
|
206
206
|
# I{Signed} area of a triangle, I{doubled}.
|
|
@@ -314,7 +314,7 @@ class LatLonFHP(_LatLonBool):
|
|
|
314
314
|
|
|
315
315
|
def __add__(self, other):
|
|
316
316
|
_other(self, other)
|
|
317
|
-
return self
|
|
317
|
+
return type(self)(self.y + other.y, self.x + other.x)
|
|
318
318
|
|
|
319
319
|
def __mod__(self, other): # cross product
|
|
320
320
|
_other(self, other)
|
|
@@ -326,7 +326,7 @@ class LatLonFHP(_LatLonBool):
|
|
|
326
326
|
|
|
327
327
|
def __rmul__(self, other): # scalar product
|
|
328
328
|
_xscalar(other=other)
|
|
329
|
-
return self
|
|
329
|
+
return type(self)(self.y * other, self.x * other)
|
|
330
330
|
|
|
331
331
|
# def _edge2(self):
|
|
332
332
|
# # Return the start and end point of the
|
|
@@ -959,7 +959,7 @@ class _CompositeBase(_Named):
|
|
|
959
959
|
# Return a new instance
|
|
960
960
|
_g = kwds.get
|
|
961
961
|
kwds = dict((n, _g(n, v)) for n, v in dflts.items())
|
|
962
|
-
return self
|
|
962
|
+
return type(self)(corners or (), **kwds)
|
|
963
963
|
|
|
964
964
|
@property_RO
|
|
965
965
|
def _clipids(self): # PYCHOK no cover
|
|
@@ -1549,7 +1549,7 @@ class _EdgeFHP(object):
|
|
|
1549
1549
|
dq = q2 - q1
|
|
1550
1550
|
dq2 = dq * dq # dot product, hypot2
|
|
1551
1551
|
if dq2 > EPS2: # like ._clip
|
|
1552
|
-
T, _E = None, _EdgeFHP # self
|
|
1552
|
+
T, _E = None, _EdgeFHP # type(self)
|
|
1553
1553
|
p1, p2 = self._p1_p2
|
|
1554
1554
|
ap1 = p1._2A(q1, q2)
|
|
1555
1555
|
ap2_1 = p2._2A(q1, q2) - ap1
|
|
@@ -1750,8 +1750,8 @@ class _BooleanBase(object):
|
|
|
1750
1750
|
|
|
1751
1751
|
def _boolean4(self, other, op):
|
|
1752
1752
|
# Set up a new C{Boolean[FHP|GH]}.
|
|
1753
|
-
C = self
|
|
1754
|
-
kwds = C._kwds(self, op)
|
|
1753
|
+
C = type(self)
|
|
1754
|
+
kwds = C._kwds(self, op) # PYCHOK in _Composite[FHP|GH]
|
|
1755
1755
|
a = C(self, **kwds)
|
|
1756
1756
|
b = _other(self, other)
|
|
1757
1757
|
return a, b, C, kwds
|
|
@@ -1964,7 +1964,7 @@ def _min_max_eps2(*xs):
|
|
|
1964
1964
|
def _other(this, other):
|
|
1965
1965
|
'''(INTERNAL) Check for compatible C{type}s.
|
|
1966
1966
|
'''
|
|
1967
|
-
C = this
|
|
1967
|
+
C = type(this)
|
|
1968
1968
|
if isinstance(other, C):
|
|
1969
1969
|
return other
|
|
1970
1970
|
raise _IsnotError(C, other=other)
|
pygeodesy/constants.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
|
-
u'''Single-instance C{float} and C{int} constants across C{pygeodesy} modules and
|
|
5
|
-
|
|
4
|
+
u'''Single-instance C{float} and C{int} constants across C{pygeodesy} modules and related
|
|
5
|
+
functions L{pygeodesy.float_}, L{pygeodesy.float0_}, L{pygeodesy.isclose}, L{pygeodesy.isfinite},
|
|
6
6
|
L{pygeodesy.isinf}, L{pygeodesy.isint0}, L{pygeodesy.isnan}, L{pygeodesy.isnear0},
|
|
7
7
|
L{pygeodesy.isnear1}, L{pygeodesy.isnear90}, L{pygeodesy.isneg0}, L{pygeodesy.isninf},
|
|
8
8
|
L{pygeodesy.isnon0} and L{pygeodesy.remainder}.
|
|
@@ -26,7 +26,7 @@ except ImportError: # Python 2-
|
|
|
26
26
|
_inf, _nan = float(_INF_), float(_NAN_)
|
|
27
27
|
|
|
28
28
|
__all__ = _ALL_LAZY.constants
|
|
29
|
-
__version__ = '25.05.
|
|
29
|
+
__version__ = '25.05.26'
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def _copysign_0_0(y):
|
|
@@ -495,12 +495,12 @@ def _umod_PI2(rad):
|
|
|
495
495
|
|
|
496
496
|
if __name__ == _DMAIN_:
|
|
497
497
|
|
|
498
|
-
def _main(
|
|
498
|
+
def _main(globalocals):
|
|
499
499
|
from pygeodesy import itemsorted, printf
|
|
500
500
|
from pygeodesy.interns import _DALL_, _UNDER_
|
|
501
501
|
|
|
502
502
|
t = n = v = []
|
|
503
|
-
for n, v in itemsorted(
|
|
503
|
+
for n, v in itemsorted(globalocals):
|
|
504
504
|
if isinstance(v, (Float, Int, Radius)):
|
|
505
505
|
printf('%9s: %r', n, v.toRepr(std=False))
|
|
506
506
|
if v.name != n:
|
|
@@ -512,7 +512,7 @@ if __name__ == _DMAIN_:
|
|
|
512
512
|
t.append(typename(float_))
|
|
513
513
|
printf('%s = %r', _DALL_, tuple(t))
|
|
514
514
|
|
|
515
|
-
_main(locals()
|
|
515
|
+
_main(globals()) # or locals()
|
|
516
516
|
|
|
517
517
|
# **) MIT License
|
|
518
518
|
#
|
pygeodesy/css.py
CHANGED
|
@@ -470,7 +470,7 @@ class Css(_NamedBase):
|
|
|
470
470
|
# h=self.height, cs0=self.cs0,
|
|
471
471
|
# name=_name__(name, _or_nameof(self)))
|
|
472
472
|
# args, kwds = _args_kwds(**kwds)
|
|
473
|
-
# return self
|
|
473
|
+
# return type(self)(*args, **kwds) # .classof
|
|
474
474
|
|
|
475
475
|
@Property_RO
|
|
476
476
|
def easting(self):
|
pygeodesy/ellipsoidalBase.py
CHANGED
|
@@ -46,7 +46,7 @@ from pygeodesy.units import Epoch, _isDegrees, Radius_, _1mm as _TOL_M
|
|
|
46
46
|
# from math import fabs # from .latlonBase
|
|
47
47
|
|
|
48
48
|
__all__ = _ALL_LAZY.ellipsoidalBase
|
|
49
|
-
__version__ = '25.
|
|
49
|
+
__version__ = '25.07.21'
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
class CartesianEllipsoidalBase(CartesianBase):
|
|
@@ -136,7 +136,7 @@ class CartesianEllipsoidalBase(CartesianBase):
|
|
|
136
136
|
|
|
137
137
|
If C{B{sphere} is False}, a 2-tuple with the two intersection points
|
|
138
138
|
of the I{circles}. For abutting circles, both points are the same
|
|
139
|
-
instance
|
|
139
|
+
instance (aka the I{radical center}).
|
|
140
140
|
|
|
141
141
|
@raise IntersectionError: Concentric, invalid or non-intersecting spheres or circles.
|
|
142
142
|
|
|
@@ -449,8 +449,7 @@ class LatLonEllipsoidalBase(LatLonBase):
|
|
|
449
449
|
def _etm(self):
|
|
450
450
|
'''(INTERNAL) Get this C{LatLon} point as an ETM coordinate (L{pygeodesy.toEtm8}).
|
|
451
451
|
'''
|
|
452
|
-
|
|
453
|
-
return etm.toEtm8(self, datum=self.datum, Etm=etm.Etm)
|
|
452
|
+
return self._toX8(_MODS.etm.toEtm8)
|
|
454
453
|
|
|
455
454
|
@property_RO
|
|
456
455
|
def gamma(self):
|
|
@@ -523,8 +522,8 @@ class LatLonEllipsoidalBase(LatLonBase):
|
|
|
523
522
|
a C{LatLon} instance.
|
|
524
523
|
|
|
525
524
|
@raise ImportError: Package U{geographiclib
|
|
526
|
-
<https://PyPI.org/project/geographiclib>}
|
|
527
|
-
installed or not found, but only
|
|
525
|
+
<https://PyPI.org/project/geographiclib>}
|
|
526
|
+
not installed or not found, but only if
|
|
528
527
|
C{B{equidistant}=}L{EquidistantKarney}.
|
|
529
528
|
|
|
530
529
|
@raise IntersectionError: Skew, colinear, parallel or otherwise non-intersecting
|
|
@@ -676,8 +675,8 @@ class LatLonEllipsoidalBase(LatLonBase):
|
|
|
676
675
|
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll both B{C{point1}} and
|
|
677
676
|
B{C{point2}} (C{bool}).
|
|
678
677
|
@kwarg equidistant: An azimuthal equidistant projection (I{class} or function
|
|
679
|
-
L{pygeodesy.equidistant}) or C{None} for this point's
|
|
680
|
-
C{Equidistant}, like L{Equidistant
|
|
678
|
+
L{pygeodesy.equidistant}) or C{None} for this point's
|
|
679
|
+
preferred C{Equidistant}, like L{Equidistant}.
|
|
681
680
|
@kwarg tol: Convergence tolerance (C{meter}, conventionally).
|
|
682
681
|
|
|
683
682
|
@return: Closest point (C{LatLon}).
|
|
@@ -778,6 +777,11 @@ class LatLonEllipsoidalBase(LatLonBase):
|
|
|
778
777
|
'''
|
|
779
778
|
return self._scale
|
|
780
779
|
|
|
780
|
+
def _toX8(self, toX8, **kwds):
|
|
781
|
+
'''(INTERNAL) Return toX8(self, ...).
|
|
782
|
+
'''
|
|
783
|
+
return toX8(self, **_xkwds(kwds, datum=self.datum, name=self.name))
|
|
784
|
+
|
|
781
785
|
def toCartesian(self, height=None, **Cartesian_and_kwds): # PYCHOK signature
|
|
782
786
|
'''Convert this point to cartesian, I{geocentric} coordinates,
|
|
783
787
|
also known as I{Earth-Centered, Earth-Fixed} (ECEF).
|
|
@@ -793,11 +797,10 @@ class LatLonEllipsoidalBase(LatLonBase):
|
|
|
793
797
|
def toCss(self, **toCss_kwds):
|
|
794
798
|
'''Convert this C{LatLon} point to a Cassini-Soldner location.
|
|
795
799
|
|
|
796
|
-
@kwarg toCss_kwds: Optional
|
|
800
|
+
@kwarg toCss_kwds: Optional keyword arguments for function
|
|
801
|
+
L{pygeodesy.toCss}.
|
|
797
802
|
|
|
798
803
|
@return: The Cassini-Soldner location (L{Css}).
|
|
799
|
-
|
|
800
|
-
@see: Function L{pygeodesy.toCss}.
|
|
801
804
|
'''
|
|
802
805
|
return _MODS.css.toCss(self, **self._name1__(toCss_kwds))
|
|
803
806
|
|
|
@@ -829,39 +832,38 @@ class LatLonEllipsoidalBase(LatLonBase):
|
|
|
829
832
|
def toEtm(self, **toEtm8_kwds):
|
|
830
833
|
'''Convert this C{LatLon} point to an ETM coordinate.
|
|
831
834
|
|
|
832
|
-
@kwarg toEtm8_kwds: Optional
|
|
835
|
+
@kwarg toEtm8_kwds: Optional keyword arguments for
|
|
836
|
+
function L{pygeodesy.toEtm8}.
|
|
833
837
|
|
|
834
838
|
@return: The ETM coordinate (L{Etm}).
|
|
835
|
-
|
|
836
|
-
@see: Function L{pygeodesy.toEtm8}.
|
|
837
839
|
'''
|
|
838
|
-
return
|
|
840
|
+
return self._etm if not toEtm8_kwds else \
|
|
841
|
+
self._toX8(_MODS.etm.toEtm8, **toEtm8_kwds)
|
|
839
842
|
|
|
840
843
|
def toLcc(self, **toLcc_kwds):
|
|
841
844
|
'''Convert this C{LatLon} point to a Lambert location.
|
|
842
845
|
|
|
843
|
-
@kwarg toLcc_kwds: Optional
|
|
846
|
+
@kwarg toLcc_kwds: Optional keyword arguments for
|
|
847
|
+
function L{pygeodesy.toLcc}.
|
|
844
848
|
|
|
845
849
|
@return: The Lambert location (L{Lcc}).
|
|
846
|
-
|
|
847
|
-
@see: Function L{pygeodesy.toLcc}.
|
|
848
850
|
'''
|
|
849
851
|
return _MODS.lcc.toLcc(self, **self._name1__(toLcc_kwds))
|
|
850
852
|
|
|
851
|
-
def toMgrs(self, center=False,
|
|
853
|
+
def toMgrs(self, center=False, **toUtmUps_kwds):
|
|
852
854
|
'''Convert this C{LatLon} point to an MGRS coordinate.
|
|
853
855
|
|
|
854
856
|
@kwarg center: If C{True}, try to I{un}-center MGRS
|
|
855
857
|
to its C{lowerleft} (C{bool}) or by
|
|
856
858
|
C{B{center} meter} (C{scalar}).
|
|
857
|
-
@kwarg
|
|
858
|
-
|
|
859
|
+
@kwarg toUtmUps_kwds: Optional keyword arguments for
|
|
860
|
+
method L{toUtmUps}.
|
|
859
861
|
|
|
860
862
|
@return: The MGRS coordinate (L{Mgrs}).
|
|
861
863
|
|
|
862
|
-
@see:
|
|
864
|
+
@see: Methods L{toUtmUps} and L{toMgrs<pygeodesy.utmupsBase.UtmUpsBase.toMgrs>}.
|
|
863
865
|
'''
|
|
864
|
-
return self.toUtmUps(center=center,
|
|
866
|
+
return self.toUtmUps(center=center, **toUtmUps_kwds).toMgrs(center=False)
|
|
865
867
|
|
|
866
868
|
def toOsgr(self, kTM=False, **toOsgr_kwds):
|
|
867
869
|
'''Convert this C{LatLon} point to an OSGR coordinate.
|
|
@@ -869,11 +871,10 @@ class LatLonEllipsoidalBase(LatLonBase):
|
|
|
869
871
|
@kwarg kTM: If C{True}, use I{Karney}'s Krüger method from module
|
|
870
872
|
L{ktm}, otherwise I{Ordinance Survery}'s recommended
|
|
871
873
|
formulation (C{bool}).
|
|
872
|
-
@kwarg toOsgr_kwds: Optional
|
|
874
|
+
@kwarg toOsgr_kwds: Optional keyword arguments for function
|
|
875
|
+
L{pygeodesy.toOsgr}.
|
|
873
876
|
|
|
874
877
|
@return: The OSGR coordinate (L{Osgr}).
|
|
875
|
-
|
|
876
|
-
@see: Function L{pygeodesy.toOsgr}.
|
|
877
878
|
'''
|
|
878
879
|
return _MODS.osgr.toOsgr(self, kTM=kTM, **self._name1__(toOsgr_kwds))
|
|
879
880
|
|
|
@@ -928,42 +929,40 @@ class LatLonEllipsoidalBase(LatLonBase):
|
|
|
928
929
|
r = c.toLatLon(LatLon=self.classof, **_xkwds(LatLon_kwds, height=self.height))
|
|
929
930
|
return r
|
|
930
931
|
|
|
931
|
-
def toUps(self,
|
|
932
|
+
def toUps(self, center=False, **toUps8_kwds):
|
|
932
933
|
'''Convert this C{LatLon} point to a UPS coordinate.
|
|
933
934
|
|
|
934
|
-
@kwarg pole: Optional top/center of (stereographic)
|
|
935
|
-
projection (C{str}, 'N[orth]' or 'S[outh]').
|
|
936
|
-
@kwarg falsed: False easting and northing (C{bool}).
|
|
937
935
|
@kwarg center: If C{True}, I{un}-center the UPS to its
|
|
938
936
|
C{lowerleft} (C{bool}) or by C{B{center}
|
|
939
937
|
meter} (C{scalar}).
|
|
938
|
+
@kwarg toUps8_kwds: Optional keyword arguments for
|
|
939
|
+
function L{pygeodesy.toUps8}.
|
|
940
940
|
|
|
941
941
|
@return: The UPS coordinate (L{Ups}).
|
|
942
|
-
|
|
943
|
-
@see: Function L{pygeodesy.toUps8}.
|
|
944
942
|
'''
|
|
945
|
-
if self._upsOK(
|
|
946
|
-
|
|
947
|
-
else:
|
|
948
|
-
ups = _MODS.ups
|
|
949
|
-
u = ups.toUps8(self, datum=self.datum, Ups=ups.Ups,
|
|
950
|
-
pole=pole, falsed=falsed)
|
|
943
|
+
u = self._ups if (not toUps8_kwds) and self._upsOK() else \
|
|
944
|
+
self._toX8(_MODS.ups.toUps8, **toUps8_kwds)
|
|
951
945
|
return _lowerleft(u, center)
|
|
952
946
|
|
|
953
|
-
def toUtm(self, center=False):
|
|
947
|
+
def toUtm(self, center=False, **toUtm8_kwds):
|
|
954
948
|
'''Convert this C{LatLon} point to a UTM coordinate.
|
|
955
949
|
|
|
956
950
|
@kwarg center: If C{True}, I{un}-center the UTM to its
|
|
957
951
|
C{lowerleft} (C{bool}) or by C{B{center}
|
|
958
952
|
meter} (C{scalar}).
|
|
953
|
+
@kwarg toUtm8_kwds: Optional keyword arguments for function
|
|
954
|
+
L{pygeodesy.toUtm8}.
|
|
959
955
|
|
|
960
956
|
@return: The UTM coordinate (L{Utm}).
|
|
961
957
|
|
|
962
|
-
@
|
|
958
|
+
@note: For the highest accuracy, use method L{toEtm} and
|
|
959
|
+
class L{pygeodesy.Etm} instead of L{pygeodesy.Utm}.
|
|
963
960
|
'''
|
|
964
|
-
|
|
961
|
+
u = self._utm if not toUtm8_kwds else \
|
|
962
|
+
self._toX8(_MODS.utm.toUtm8, **toUtm8_kwds)
|
|
963
|
+
return _lowerleft(u, center)
|
|
965
964
|
|
|
966
|
-
def toUtmUps(self, pole=NN, center=False):
|
|
965
|
+
def toUtmUps(self, pole=NN, center=False, **toUtmUps8_kwds):
|
|
967
966
|
'''Convert this C{LatLon} point to a UTM or UPS coordinate.
|
|
968
967
|
|
|
969
968
|
@kwarg pole: Optional top/center of UPS (stereographic)
|
|
@@ -971,19 +970,19 @@ class LatLonEllipsoidalBase(LatLonBase):
|
|
|
971
970
|
@kwarg center: If C{True}, I{un}-center the UTM or UPS to
|
|
972
971
|
its C{lowerleft} (C{bool}) or by C{B{center}
|
|
973
972
|
meter} (C{scalar}).
|
|
973
|
+
@kwarg toUtmUps8_kwds: Optional keyword arguments for
|
|
974
|
+
function L{pygeodesy.toUtmUps8}.
|
|
974
975
|
|
|
975
976
|
@return: The UTM or UPS coordinate (L{Utm} or L{Ups}).
|
|
976
|
-
|
|
977
|
-
@see: Function L{pygeodesy.toUtmUps8}.
|
|
978
977
|
'''
|
|
979
|
-
|
|
978
|
+
x = not toUtmUps8_kwds
|
|
979
|
+
if x and self._utmOK():
|
|
980
980
|
u = self._utm
|
|
981
|
-
elif self._upsOK(pole):
|
|
981
|
+
elif x and self._upsOK(pole):
|
|
982
982
|
u = self._ups
|
|
983
983
|
else: # no cover
|
|
984
984
|
utmups = _MODS.utmups
|
|
985
|
-
u = utmups.toUtmUps8
|
|
986
|
-
Utm=utmups.Utm, Ups=utmups.Ups)
|
|
985
|
+
u = self._toX8(utmups.toUtmUps8, pole=pole, **toUtmUps8_kwds)
|
|
987
986
|
if isinstance(u, utmups.Utm):
|
|
988
987
|
self._update(False, _utm=u) # PYCHOK kwds
|
|
989
988
|
elif isinstance(u, utmups.Ups):
|
|
@@ -1011,13 +1010,11 @@ class LatLonEllipsoidalBase(LatLonBase):
|
|
|
1011
1010
|
@arg other: The other point (C{LatLon}).
|
|
1012
1011
|
@arg bearing2: Bearing at the B{C{other}} point (compass C{degrees360}).
|
|
1013
1012
|
@kwarg height_wrap_tol: Optional keyword arguments C{B{height}=None},
|
|
1014
|
-
C{B{wrap}=False} and C{B{tol}}, see method L{intersection3
|
|
1015
|
-
<pygeodesy.ellipsoidalBase.LatLonEllipsoidalBase>}.
|
|
1013
|
+
C{B{wrap}=False} and C{B{tol}}, see method L{intersection3}.
|
|
1016
1014
|
|
|
1017
1015
|
@return: Triangulated point (C{LatLon}).
|
|
1018
1016
|
|
|
1019
|
-
@see: Method L{intersection3
|
|
1020
|
-
for further details.
|
|
1017
|
+
@see: Method L{intersection3} for further details.
|
|
1021
1018
|
'''
|
|
1022
1019
|
if _isDegrees(bearing1) and _isDegrees(bearing2):
|
|
1023
1020
|
r = self.intersection3(bearing1, other, bearing2, **height_wrap_tol)
|
|
@@ -1086,11 +1083,9 @@ class LatLonEllipsoidalBase(LatLonBase):
|
|
|
1086
1083
|
'''(INTERNAL) Get this C{LatLon} point as UPS coordinate (L{Ups}),
|
|
1087
1084
|
see L{pygeodesy.toUps8}.
|
|
1088
1085
|
'''
|
|
1089
|
-
ups =
|
|
1090
|
-
return ups.toUps8(self, datum=self.datum, Ups=ups.Ups,
|
|
1091
|
-
pole=NN, falsed=True, name=self.name)
|
|
1086
|
+
return self._toX8(_MODS.ups.toUps8) # pole=NN, falsed=True
|
|
1092
1087
|
|
|
1093
|
-
def _upsOK(self, pole=NN, falsed=True):
|
|
1088
|
+
def _upsOK(self, pole=NN, falsed=True, **unused):
|
|
1094
1089
|
'''(INTERNAL) Check matching C{Ups}.
|
|
1095
1090
|
'''
|
|
1096
1091
|
try:
|
|
@@ -1104,8 +1099,7 @@ class LatLonEllipsoidalBase(LatLonBase):
|
|
|
1104
1099
|
'''(INTERNAL) Get this C{LatLon} point as UTM coordinate (L{Utm}),
|
|
1105
1100
|
see L{pygeodesy.toUtm8}.
|
|
1106
1101
|
'''
|
|
1107
|
-
|
|
1108
|
-
return utm.toUtm8(self, datum=self.datum, Utm=utm.Utm, name=self.name)
|
|
1102
|
+
return self._toX8(_MODS.utm.toUtm8)
|
|
1109
1103
|
|
|
1110
1104
|
def _utmOK(self):
|
|
1111
1105
|
'''(INTERNAL) Check C{Utm}.
|
pygeodesy/ellipsoidalExact.py
CHANGED
|
@@ -24,7 +24,7 @@ from pygeodesy.points import _areaError, ispolar # PYCHOK exported
|
|
|
24
24
|
# from math import fabs # from .karney
|
|
25
25
|
|
|
26
26
|
__all__ = _ALL_LAZY.ellipsoidalExact
|
|
27
|
-
__version__ = '25.05.
|
|
27
|
+
__version__ = '25.05.28'
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class Cartesian(CartesianEllipsoidalBase):
|
|
@@ -88,17 +88,19 @@ class LatLon(LatLonEllipsoidalBaseDI):
|
|
|
88
88
|
return LatLonEllipsoidalBaseDI.toCartesian(self, **kwds)
|
|
89
89
|
|
|
90
90
|
|
|
91
|
-
def areaOf(points, datum=_WGS84, wrap=True):
|
|
91
|
+
def areaOf(points, datum=_WGS84, wrap=True, polar=False):
|
|
92
92
|
'''Compute the area of an (ellipsoidal) polygon or composite.
|
|
93
93
|
|
|
94
|
-
@arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or
|
|
95
|
-
L{BooleanGH}).
|
|
94
|
+
@arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or L{BooleanGH}).
|
|
96
95
|
@kwarg datum: Optional datum (L{Datum}).
|
|
97
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
|
|
98
|
-
|
|
96
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}}
|
|
97
|
+
(C{bool}).
|
|
98
|
+
@kwarg polar: Use C{B{polar}=True} if the polygon encloses a pole (C{bool}), see
|
|
99
|
+
function L{ispolar<pygeodesy.points.ispolar>} and U{area of a polygon
|
|
100
|
+
enclosing a pole<https://GeographicLib.SourceForge.io/C++/doc/
|
|
101
|
+
classGeographicLib_1_1GeodesicExact.html#a3d7a9155e838a09a48dc14d0c3fac525>}.
|
|
99
102
|
|
|
100
|
-
@return: Area (C{meter} I{squared}, same units as the B{C{datum}}'s
|
|
101
|
-
ellipsoid axes).
|
|
103
|
+
@return: Area (C{meter} I{squared}, same units as the B{C{datum}}'s ellipsoid axes).
|
|
102
104
|
|
|
103
105
|
@raise PointsError: Insufficient number of B{C{points}}.
|
|
104
106
|
|
|
@@ -110,12 +112,8 @@ def areaOf(points, datum=_WGS84, wrap=True):
|
|
|
110
112
|
@see: Functions L{pygeodesy.areaOf}, L{ellipsoidalGeodSolve.areaOf},
|
|
111
113
|
L{ellipsoidalKarney.areaOf}, L{sphericalNvector.areaOf} and
|
|
112
114
|
L{sphericalTrigonometry.areaOf}.
|
|
113
|
-
|
|
114
|
-
@note: The U{area of a polygon enclosing a pole<https://GeographicLib.SourceForge.io/
|
|
115
|
-
C++/doc/classGeographicLib_1_1GeodesicExact.html#a3d7a9155e838a09a48dc14d0c3fac525>}
|
|
116
|
-
can be found by adding half the datum's ellipsoid surface area to the polygon's area.
|
|
117
115
|
'''
|
|
118
|
-
return fabs(_polygon(datum.ellipsoid.geodesicx, points, True, False, wrap))
|
|
116
|
+
return fabs(_polygon(datum.ellipsoid.geodesicx, points, True, False, wrap, polar))
|
|
119
117
|
|
|
120
118
|
|
|
121
119
|
def intersection3(start1, end1, start2, end2, height=None, wrap=False, # was=True
|
|
@@ -216,13 +214,14 @@ def intersections2(center1, radius1, center2, radius2, height=None, wrap=False,
|
|
|
216
214
|
equidistant=equidistant, tol=tol, **kwds)
|
|
217
215
|
|
|
218
216
|
|
|
219
|
-
def isclockwise(points, datum=_WGS84, wrap=True):
|
|
217
|
+
def isclockwise(points, datum=_WGS84, wrap=True, polar=False):
|
|
220
218
|
'''Determine the direction of a path or polygon.
|
|
221
219
|
|
|
222
220
|
@arg points: The path or polygon points (C{LatLon}[]).
|
|
223
221
|
@kwarg datum: Optional datum (L{Datum}).
|
|
224
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
|
|
225
|
-
|
|
222
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}} (C{bool}).
|
|
223
|
+
@kwarg polar: Use C{B{polar}=True} if the C{B{points}} enclose a pole (C{bool}),
|
|
224
|
+
see function U{ispolar<pygeodeys.points.ispolar>}.
|
|
226
225
|
|
|
227
226
|
@return: C{True} if B{C{points}} are clockwise, C{False} otherwise.
|
|
228
227
|
|
|
@@ -234,7 +233,7 @@ def isclockwise(points, datum=_WGS84, wrap=True):
|
|
|
234
233
|
|
|
235
234
|
@see: L{pygeodesy.isclockwise}.
|
|
236
235
|
'''
|
|
237
|
-
a = _polygon(datum.ellipsoid.geodesicx, points, True, False, wrap)
|
|
236
|
+
a = _polygon(datum.ellipsoid.geodesicx, points, True, False, wrap, polar)
|
|
238
237
|
if a < 0:
|
|
239
238
|
return True
|
|
240
239
|
elif a > 0:
|
|
@@ -288,29 +287,25 @@ def nearestOn(point, point1, point2, within=True, height=None, wrap=False,
|
|
|
288
287
|
def perimeterOf(points, closed=False, datum=_WGS84, wrap=True):
|
|
289
288
|
'''Compute the perimeter of an (ellipsoidal) polygon or composite.
|
|
290
289
|
|
|
291
|
-
@arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or
|
|
292
|
-
L{BooleanGH}).
|
|
290
|
+
@arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or L{BooleanGH}).
|
|
293
291
|
@kwarg closed: Optionally, close the polygon (C{bool}).
|
|
294
292
|
@kwarg datum: Optional datum (L{Datum}).
|
|
295
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
|
|
296
|
-
B{C{points}} (C{bool}).
|
|
293
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}} (C{bool}).
|
|
297
294
|
|
|
298
|
-
@return: Perimeter (C{meter}, same units as the B{C{datum}}'s
|
|
299
|
-
ellipsoid axes).
|
|
295
|
+
@return: Perimeter (C{meter}, same units as the B{C{datum}}'s ellipsoid axes).
|
|
300
296
|
|
|
301
297
|
@raise PointsError: Insufficient number of B{C{points}}.
|
|
302
298
|
|
|
303
299
|
@raise TypeError: Some B{C{points}} are not L{LatLon}.
|
|
304
300
|
|
|
305
|
-
@raise ValueError: Invalid C{B{wrap}=False}, unwrapped, unrolled
|
|
306
|
-
|
|
307
|
-
with C{B{points}} a composite.
|
|
301
|
+
@raise ValueError: Invalid C{B{wrap}=False}, unwrapped, unrolled longitudes not
|
|
302
|
+
supported or C{B{closed}=False} with C{B{points}} a composite.
|
|
308
303
|
|
|
309
304
|
@see: Functions L{pygeodesy.perimeterOf}, L{ellipsoidalGeodSolve.perimeterOf},
|
|
310
305
|
L{ellipsoidalKarney.perimeterOf}, L{sphericalNvector.perimeterOf} and
|
|
311
306
|
L{sphericalTrigonometry.perimeterOf}.
|
|
312
307
|
'''
|
|
313
|
-
return _polygon(datum.ellipsoid.geodesicx, points, closed, True, wrap)
|
|
308
|
+
return _polygon(datum.ellipsoid.geodesicx, points, closed, True, wrap, False)
|
|
314
309
|
|
|
315
310
|
|
|
316
311
|
__all__ += _ALL_OTHER(Cartesian, LatLon, # classes
|