pygeodesy 24.8.4__py2.py3-none-any.whl → 24.9.9__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.
Files changed (76) hide show
  1. {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.9.9.dist-info}/METADATA +17 -16
  2. PyGeodesy-24.9.9.dist-info/RECORD +118 -0
  3. {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.9.9.dist-info}/WHEEL +1 -1
  4. pygeodesy/__init__.py +23 -23
  5. pygeodesy/__main__.py +46 -47
  6. pygeodesy/auxilats/_CX_4.py +104 -181
  7. pygeodesy/auxilats/_CX_6.py +152 -277
  8. pygeodesy/auxilats/_CX_8.py +211 -438
  9. pygeodesy/auxilats/_CX_Rs.py +222 -0
  10. pygeodesy/auxilats/__init__.py +2 -2
  11. pygeodesy/auxilats/__main__.py +30 -38
  12. pygeodesy/auxilats/auxDST.py +2 -2
  13. pygeodesy/auxilats/auxLat.py +28 -36
  14. pygeodesy/auxilats/auxily.py +30 -50
  15. pygeodesy/basics.py +18 -7
  16. pygeodesy/booleans.py +10 -11
  17. pygeodesy/cartesianBase.py +5 -5
  18. pygeodesy/constants.py +35 -34
  19. pygeodesy/ellipsoidalBase.py +18 -15
  20. pygeodesy/ellipsoidalExact.py +2 -2
  21. pygeodesy/ellipsoidalGeodSolve.py +2 -2
  22. pygeodesy/ellipsoidalKarney.py +2 -2
  23. pygeodesy/ellipsoidalNvector.py +2 -2
  24. pygeodesy/ellipsoidalVincenty.py +7 -6
  25. pygeodesy/elliptic.py +154 -88
  26. pygeodesy/epsg.py +3 -3
  27. pygeodesy/etm.py +71 -59
  28. pygeodesy/fmath.py +99 -90
  29. pygeodesy/fsums.py +201 -14
  30. pygeodesy/gars.py +9 -8
  31. pygeodesy/geodesici.py +6 -5
  32. pygeodesy/geodesicx/_C4_24.py +1 -3
  33. pygeodesy/geodesicx/_C4_27.py +1 -3
  34. pygeodesy/geodesicx/_C4_30.py +1 -3
  35. pygeodesy/geodesicx/__init__.py +1 -1
  36. pygeodesy/geodesicx/__main__.py +44 -46
  37. pygeodesy/geodesicx/gx.py +3 -3
  38. pygeodesy/geodesicx/gxarea.py +5 -5
  39. pygeodesy/geodesicx/gxbases.py +32 -18
  40. pygeodesy/geodsolve.py +3 -3
  41. pygeodesy/geohash.py +18 -11
  42. pygeodesy/geoids.py +293 -315
  43. pygeodesy/heights.py +150 -158
  44. pygeodesy/internals.py +70 -9
  45. pygeodesy/interns.py +4 -4
  46. pygeodesy/karney.py +83 -60
  47. pygeodesy/ktm.py +4 -4
  48. pygeodesy/latlonBase.py +13 -7
  49. pygeodesy/lazily.py +13 -8
  50. pygeodesy/ltp.py +5 -6
  51. pygeodesy/ltpTuples.py +7 -1
  52. pygeodesy/mgrs.py +47 -42
  53. pygeodesy/named.py +8 -4
  54. pygeodesy/namedTuples.py +14 -1
  55. pygeodesy/osgr.py +7 -7
  56. pygeodesy/points.py +2 -2
  57. pygeodesy/props.py +7 -6
  58. pygeodesy/resections.py +7 -7
  59. pygeodesy/rhumb/__init__.py +1 -1
  60. pygeodesy/rhumb/aux_.py +42 -60
  61. pygeodesy/rhumb/solve.py +3 -3
  62. pygeodesy/simplify.py +10 -10
  63. pygeodesy/sphericalBase.py +3 -3
  64. pygeodesy/sphericalTrigonometry.py +2 -2
  65. pygeodesy/streprs.py +3 -3
  66. pygeodesy/triaxials.py +207 -201
  67. pygeodesy/units.py +3 -3
  68. pygeodesy/unitsBase.py +4 -4
  69. pygeodesy/utmupsBase.py +3 -3
  70. pygeodesy/vector2d.py +158 -51
  71. pygeodesy/vector3d.py +13 -52
  72. pygeodesy/vector3dBase.py +81 -63
  73. pygeodesy/webmercator.py +3 -3
  74. pygeodesy/wgrs.py +20 -22
  75. PyGeodesy-24.8.4.dist-info/RECORD +0 -117
  76. {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.9.9.dist-info}/top_level.txt +0 -0
pygeodesy/interns.py CHANGED
@@ -184,7 +184,6 @@ _concentric_ = 'concentric' # PYCHOK OK
184
184
  _convergence_ = _Prefix('convergence') # PYCHOK OK
185
185
  _conversion_ = 'conversion' # PYCHOK OK
186
186
  _convex_ = 'convex' # PYCHOK OK
187
- _cubic_ = 'cubic' # PYCHOK OK
188
187
  _d_ = 'd' # PYCHOK OK
189
188
  _D_ = 'D' # PYCHOK OK
190
189
  _DASH_ = Str_('-') # PYCHOK == _MINUS_
@@ -201,6 +200,7 @@ _distant_ = _Prefix('distant') # PYCHOK OK
201
200
  _doesn_t_exist_ = "doesn't exist" # PYCHOK OK
202
201
  _DOT_ = Str_('.') # PYCHOK OK
203
202
  _dunder_name_ = '__name__' # PYCHOK _DUNDER_(NN, _name_, NN)
203
+ _duplicate_ = 'duplicate' # PYCHOK OK
204
204
  _e_ = 'e' # PYCHOK OK
205
205
  _E_ = 'E' # PYCHOK OK
206
206
  _earth_ = 'earth' # PYCHOK OK
@@ -250,6 +250,7 @@ _inside_ = 'inside' # PYCHOK OK
250
250
  _insufficient_ = 'insufficient' # PYCHOK OK
251
251
  _intersection_ = 'intersection' # PYCHOK OK
252
252
  _Intl1924_ = 'Intl1924' # PYCHOK OK
253
+ _INV_ = 'INV' # PYCHOK INValid
253
254
  _invalid_ = 'invalid' # PYCHOK OK
254
255
  _invokation_ = 'invokation' # PYCHOK OK
255
256
  _j_ = 'j' # PYCHOK OK
@@ -270,7 +271,6 @@ _LCURLY_ = '{' # PYCHOK LBRACE
270
271
  _len_ = 'len' # PYCHOK OK
271
272
  _limit_ = 'limit' # PYCHOK OK
272
273
  _line_ = 'line' # PYCHOK OK
273
- _linear_ = 'linear' # PYCHOK OK
274
274
  _LPAREN_ = '(' # PYCHOK OK
275
275
  _lon_ = 'lon' # PYCHOK OK
276
276
  _lon0_ = 'lon0' # PYCHOK OK
@@ -348,7 +348,7 @@ _Python_ = _Python_('Python') # PYCHOK singleton
348
348
  _python_ = 'python' # PYCHOK OK
349
349
  _QUOTE1_ = "'" # PYCHOK OK
350
350
  _QUOTE2_ = '"' # PYCHOK OK
351
- # _QUOTE3_ = "'''" # PYCHOK OK
351
+ _QUOTE3_ = "'''" # PYCHOK OK
352
352
  # _QUOTE6_ = '"""' # PYCHOK OK
353
353
  _R_ = 'R' # PYCHOK OK
354
354
  _radians_ = 'radians' # PYCHOK OK
@@ -441,7 +441,7 @@ _LR_PAIRS = {_LANGLE_: _RANGLE_,
441
441
 
442
442
  __all__ = (_NN_, # NOT MISSING!
443
443
  Str_.__name__) # classes
444
- __version__ = '24.06.14'
444
+ __version__ = '24.08.30'
445
445
 
446
446
  if __name__ == '__main__':
447
447
 
pygeodesy/karney.py CHANGED
@@ -10,7 +10,9 @@ C{attribute} name.
10
10
 
11
11
  With env variable C{PYGEODESY_GEOGRAPHICLIB} left undefined or set to C{"2"}, modules L{geodesicw},
12
12
  L{geodesicx} and this module will use U{GeographicLib 2.0+<https://GeographicLib.SourceForge.io/C++/doc/>}
13
- and newer transcoding, otherwise C{1.52} or older.
13
+ and newer transcoding, otherwise C{1.52} or older. Set C{PYGEODESY_GEOGRAPHICLIB=2.4} to default to the
14
+ C{Jacobi amplitude} instead of C{Bulirsch}' function in methods L{ExactTransverseMercator.forward
15
+ <pygeodesy.ExactTransverseMercator.forward>} and L{reverse <pygeodesy.ExactTransverseMercator.reverse>}.
14
16
 
15
17
  Karney-based functionality
16
18
  ==========================
@@ -145,8 +147,8 @@ from pygeodesy.basics import _copysign, isint, neg, unsigned0, _xgeographiclib,
145
147
  _zip, _version_info
146
148
  from pygeodesy.constants import NAN, _isfinite as _math_isfinite, _0_0, \
147
149
  _1_16th, _1_0, _2_0, _180_0, _N_180_0, _360_0
148
- from pygeodesy.errors import GeodesicError, _ValueError, _xkwds, _xkwds_get1
149
- from pygeodesy.fmath import cbrt, fremainder, norm2
150
+ from pygeodesy.errors import GeodesicError, _ValueError, _xkwds
151
+ from pygeodesy.fmath import cbrt, fremainder, norm2 # Fhorner, Fsum
150
152
  # from pygeodesy.internals import _version_info # from .basics
151
153
  from pygeodesy.interns import NN, _2_, _a12_, _area_, _azi1_, _azi2_, _azi12_, \
152
154
  _composite_, _lat1_, _lat2_, _lon1_, _lon2_, \
@@ -154,7 +156,8 @@ from pygeodesy.interns import NN, _2_, _a12_, _area_, _azi1_, _azi2_, _azi12_, \
154
156
  _UNDER_, _X_, _BAR_ # PYCHOK used!
155
157
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _getenv
156
158
  from pygeodesy.named import ADict, _NamedBase, _NamedTuple, notImplemented, _Pass
157
- from pygeodesy.props import deprecated_method, Property_RO, property_ROnce
159
+ from pygeodesy.props import deprecated_method, Property_RO, property_RO, \
160
+ property_ROnce
158
161
  from pygeodesy.units import Azimuth as _Azi, Degrees as _Deg, Lat, Lon, \
159
162
  Meter as _M, Meter2 as _M2, Number_
160
163
  from pygeodesy.utily import atan2d, sincos2d, tand, _unrollon, fabs
@@ -162,9 +165,11 @@ from pygeodesy.utily import atan2d, sincos2d, tand, _unrollon, fabs
162
165
  # from math import fabs # from .utily
163
166
 
164
167
  __all__ = _ALL_LAZY.karney
165
- __version__ = '24.07.25'
168
+ __version__ = '24.09.10'
166
169
 
167
- _K_2_0 = _getenv('PYGEODESY_GEOGRAPHICLIB', _2_) == _2_
170
+ _K_2_0 = _getenv('PYGEODESY_GEOGRAPHICLIB', _2_)
171
+ _K_2_4 = _K_2_0 == '2.4'
172
+ _K_2_0 = _K_2_0 == _2_ or _K_2_4
168
173
  _perimeter_ = 'perimeter'
169
174
 
170
175
 
@@ -285,7 +290,7 @@ class Caps(object):
285
290
 
286
291
  Caps = Caps() # PYCHOK singleton
287
292
  '''I{Enum}-style masks to be bit-C{or}'ed to specify geodesic or
288
- rhumb capabilities (C{caps}) and expected results (C{outmask}).
293
+ rhumb capabilities (C{caps}) and results (C{outmask}).
289
294
 
290
295
  C{AREA} - compute area C{S12},
291
296
 
@@ -569,6 +574,11 @@ class _kWrapped(object): # in .geodesicw
569
574
  M = None
570
575
  return M
571
576
 
577
+ @property_RO
578
+ def Math_K_2(self):
579
+ return ('_K_2_4' if _K_2_4 else
580
+ ('_K_2_0' if _K_2_0 else '_K_1_0')) if self.Math else NN
581
+
572
582
  _wrapped = _kWrapped() # PYCHOK singleton, .datum, .test/base.py
573
583
 
574
584
 
@@ -805,25 +815,44 @@ def _polygon(geodesic, points, closed, line, wrap):
805
815
  return gP.Compute(False, True)[1 if line else 2]
806
816
 
807
817
 
818
+ try:
819
+ from math import fma as _fma # since 3.13
820
+
821
+ def _poly_fma(x, s, *cs):
822
+ for c in cs:
823
+ s = _fma(s, x, c)
824
+ return s
825
+
826
+ except ImportError: # Python 3.12-
827
+
828
+ def _poly_fma(x, s, *cs): # PYCHOK redef
829
+ t = _0_0
830
+ for c in cs:
831
+ s, t, _ = _sum3(s * x, t * x, c)
832
+ return s + t
833
+
834
+ # def _poly_fma(x, *cs):
835
+ # S = Fhorner(x, *cs, incx=False)
836
+ # return float(S)
837
+
838
+ # def _poly_fma(x, s, *cs): # scalar x, s, cs
839
+ # S = Fsum(s)._fma_scalar(None, x, *cs)
840
+ # return float(S)
841
+
808
842
  def _polynomial(x, cs, i, j): # PYCHOK shared
809
843
  '''(INTERNAL) Like C++ C{GeographicLib.Math.hpp.polyval} but with a
810
- different signature and cascaded summation as C{karney._sum2_}.
844
+ signature and cascaded summation different from C{karney._sum3}.
811
845
 
812
- @return: M{sum(cs[k] * x**(j - k - 1) for k in range(i, j)}
846
+ @return: M{sum(x**(j - k - 1) * cs[k] for k in range(i, j)}
813
847
  '''
814
- # assert 0 <= i <= j <= len(cs)
815
- # try:
816
- # return _wrapped.Math.polyval(j - i - 1, cs, i, x)
817
- # except AttributeError:
818
- # s, t = cs[i], _0_0
819
- # for c in cs[i+1:j]:
820
- # s, t = _sum2_(s * x, t * x, c)
821
- # return s # + t
822
- s = cs[i]
823
- i += 1
824
- if x and i < j:
825
- s, _ = _sum2_(s, _0_0, x=x, *cs[i:j])
826
- return s # + t
848
+ if (i + 1) < j <= len(cs): # load _Rtuple._tuple
849
+ try:
850
+ r = _wrapped.Math.polyval(j - i - 1, cs, i, x)
851
+ except AttributeError:
852
+ r = _poly_fma(x, *cs[i:j])
853
+ else:
854
+ r = cs[i]
855
+ return float(r)
827
856
 
828
857
 
829
858
  def _remainder(x, y):
@@ -875,67 +904,60 @@ def _sincos2de(deg, t):
875
904
  return sincos2d(deg, adeg=t)
876
905
 
877
906
 
878
- def _sum2(u, v): # mimick geomath.Math.sum, actually sum2
907
+ def _sum2(a, b): # mimick geomath.Math.sum, actually sum2
879
908
  '''Error-free summation like C{geomath.Math.sum}.
880
909
 
881
- @return: 2-Tuple C{(B{u} + B{v}, residual)}.
910
+ @return: 2-Tuple C{(B{a} + B{b}, residual)}.
882
911
 
883
- @note: The C{residual} can be the same as B{C{u}} or B{C{v}}.
912
+ @note: The C{residual} can be the same as B{C{a}} or B{C{b}}.
884
913
 
885
- @see: U{Algorithm 3.1<https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}.
914
+ @see: U{TwoSum<https://accurate-algorithms.readthedocs.io/en/latest/ch04summation.html>}
915
+ and I{Knuth}'s U{Algorithm 3.1<https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}.
886
916
  '''
887
917
  try:
888
- return _wrapped.Math.sum(u, v)
918
+ return _wrapped.Math.sum(a, b)
889
919
  except AttributeError:
890
- s = u + v
891
- r = s - v
892
- t = s - r
893
920
  # if Algorithm_3_1:
894
- # t = (u - t) + (v + r)
921
+ s = a + b
922
+ r = s - b
923
+ t = s - r
895
924
  # elif C_CPP: # Math::sum C/C++
896
- # r -= u
897
- # t -= v
898
- # t += r
899
- # t = -t
925
+ # r -= a; t -= b; t += r; t = -t
900
926
  # else:
901
- t = (u - r) + (v - t)
927
+ t = (a - r) + (b - t)
928
+ # assert fabs(s) >= fabs(t)
902
929
  return s, t
903
930
 
904
931
 
905
- def _sum2_(s, t, *vs, **x):
906
- '''Accumulate any B{C{vs}} into a previous C{_sum2(s, t)}.
907
-
908
- @kwarg x: Optional polynomial C{B{x}=1} (C{scalar}).
932
+ def _sum3(s, t, *xs):
933
+ '''Accumulate any B{C{xs}} into a previous C{_sum2(s, t)}.
909
934
 
910
- @return: 2-Tuple C{(B{s} + B{t} + sum(B{vs}), residual)}.
935
+ @return: 3-Tuple C{(s, t, n)} where C{s} is the sum of B{s}, B{t} and all
936
+ B{xs}, C{t} the residual and C{n} the number of zero C{xs}.
911
937
 
912
938
  @see: I{Karney's} C++ U{Accumulator<https://GeographicLib.SourceForge.io/
913
939
  C++/doc/Accumulator_8hpp_source.html>} comments for more details and
914
940
  function C{_sum2} above.
915
941
 
916
- @note: NOT "error-free", see C{pygeodesy.test/testKarney.py}.
942
+ @note: Not "error-free", see C{pygeodesy.test/testKarney.py}.
917
943
  '''
918
- x = _xkwds_get1(x, x=_1_0)
919
- p = x != _1_0
920
-
921
- _s2, _u0 = _sum2, unsigned0
922
- for v in vs:
923
- if p:
924
- s *= x
925
- t *= x
926
- if v:
927
- t, u = _s2(t, v) # start at the least-
944
+ z = 0
945
+ for x in xs:
946
+ if x:
947
+ t, r = _sum2(t, x) # start at the least-
928
948
  if s:
929
- s, t = _s2(s, t) # significant end
949
+ s, t = _sum2(s, t) # -significant end
930
950
  if s:
931
- t += u # accumulate u into t
932
- # elif t: # s == 0 implies t == 0
933
- # raise _AssertionError(t=t, txt_not_=_0_)
951
+ t += r # accumulate r into t
934
952
  else:
935
- s = _u0(u) # result is u, t = 0
953
+ # assert t == 0 # s == 0 implies t == 0
954
+ s = unsigned0(r) # result is r, t = 0
936
955
  else:
937
- s, t = _u0(t), u
938
- return s, t
956
+ s, t = unsigned0(t), r
957
+ else:
958
+ z += 1
959
+ # assert fabs(s) >= fabs(t)
960
+ return s, t, z
939
961
 
940
962
 
941
963
  def _tand(x):
@@ -955,7 +977,8 @@ def _unroll2(lon1, lon2, wrap=False): # see .ellipsoidalBaseDI._intersects2
955
977
  '''
956
978
  if wrap:
957
979
  d, t = _diff182(lon1, lon2)
958
- lon2, _ = _sum2_(d, t, lon1) # (lon1 + d) + t
980
+ lon2, t, _ = _sum3(d, t, lon1) # (lon1 + d) + t
981
+ lon2 += t
959
982
  else:
960
983
  lon2 = _norm180(lon2)
961
984
  return (lon2 - lon1), lon2
pygeodesy/ktm.py CHANGED
@@ -67,7 +67,7 @@ from cmath import polar
67
67
  from math import atan2, asinh, cos, cosh, degrees, fabs, sin, sinh, sqrt, tanh
68
68
 
69
69
  __all__ = _ALL_LAZY.ktm
70
- __version__ = '24.07.16'
70
+ __version__ = '24.08.31'
71
71
 
72
72
 
73
73
  class KTMError(_ValueError):
@@ -505,11 +505,11 @@ def _Xs(_Coeffs, m, E, RA=False): # in .rhumb.ekx
505
505
  # constant, it cancels when evaluating a definite
506
506
  # integral. Don't bother computing it, it is unused
507
507
  # in C{_Cyxgk4} above and C{rhumb.ekx._sincosSeries}.
508
- _X, _p = X.append, _polynomial
509
- i = (m + 2) if RA else 0
508
+ i = (m + 2) if RA else 0
509
+ _p = _polynomial
510
510
  for r in _reverange(m): # [m-1 ... 0]
511
511
  j = i + r + 1
512
- _X(_p(n, Cs, i, j) * n_ / Cs[j])
512
+ X.append(_p(n, Cs, i, j) * n_ / Cs[j])
513
513
  i = j + 1
514
514
  n_ *= n
515
515
  X = tuple(X)
pygeodesy/latlonBase.py CHANGED
@@ -54,7 +54,7 @@ from contextlib import contextmanager
54
54
  from math import asin, cos, degrees, fabs, radians
55
55
 
56
56
  __all__ = _ALL_LAZY.latlonBase
57
- __version__ = '24.07.29'
57
+ __version__ = '24.08.18'
58
58
 
59
59
  _formy = _MODS.into(formy=__name__)
60
60
 
@@ -247,7 +247,7 @@ class LatLonBase(_NamedBase):
247
247
 
248
248
  @arg point2: Second point (C{LatLon}).
249
249
  @arg point3: Third point (C{LatLon}).
250
- @kwarg circum: If C{True} return the C{circumradius} and C{circumcenter},
250
+ @kwarg circum: If C{True}, return the C{circumradius} and C{circumcenter},
251
251
  always, ignoring the I{Meeus}' Type I case (C{bool}).
252
252
  @kwarg eps: Tolerance for function L{pygeodesy.trilaterate3d2}.
253
253
  @kwarg wrap_name: Optional C{B{name}=NN} (C{str}) and optional keyword
@@ -699,9 +699,9 @@ class LatLonBase(_NamedBase):
699
699
  I{overriding} this datum (L{Datum}, L{Ellipsoid},
700
700
  L{Ellipsoid2}, L{a_f2Tuple}, L{Triaxial}, L{Triaxial_},
701
701
  L{JacobiConformal} or C{meter}, conventionally).
702
- @kwarg normal: If C{True} the projection is the normal to this
703
- ellipsoid's surface, otherwise the intersection of the
704
- I{radial} line to this ellipsoid's center (C{bool}).
702
+ @kwarg normal: If C{True}, the projection is the normal to this ellipsoid's
703
+ surface, otherwise the intersection of the I{radial} line to
704
+ this ellipsoid's center (C{bool}).
705
705
  @kwarg LatLon: Optional class to return the projection, height and
706
706
  datum (C{LatLon}) or C{None}.
707
707
  @kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword arguments,
@@ -1483,8 +1483,8 @@ class LatLonBase(_NamedBase):
1483
1483
  '''Get this point I{normalized} to C{abs(lat) <= 90}
1484
1484
  and C{abs(lon) <= 180}.
1485
1485
 
1486
- @kwarg deep: If C{True} make a deep, otherwise a
1487
- shallow copy (C{bool}).
1486
+ @kwarg deep: If C{True}, make a deep, otherwise a shallow
1487
+ copy (C{bool}).
1488
1488
  @kwarg name: Optional C{B{name}=NN} (C{str}).
1489
1489
 
1490
1490
  @return: A copy of this point, I{normalized} (C{LatLon}),
@@ -1650,6 +1650,12 @@ class LatLonBase(_NamedBase):
1650
1650
  '''
1651
1651
  return self._ecef9.xyz
1652
1652
 
1653
+ @property_RO
1654
+ def xyz3(self):
1655
+ '''Get the I{geocentric} C{(x, y, z)} coordinates as C{3-tuple}.
1656
+ '''
1657
+ return tuple(self.xyz)
1658
+
1653
1659
  @Property_RO
1654
1660
  def xyzh(self):
1655
1661
  '''Get the I{geocentric} C{(x, y, z)} coordinates and height (L{Vector4Tuple}C{(x, y, z, h)})
pygeodesy/lazily.py CHANGED
@@ -255,7 +255,7 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
255
255
  fmath=_i('Fdot', 'Fhorner', 'Fhypot', 'Fpolynomial', 'Fpowers', 'Fcbrt', 'Froot', 'Fsqrt',
256
256
  'bqrt', 'cbrt', 'cbrt2', 'euclid', 'euclid_',
257
257
  'facos1', 'fasin1', 'fatan', 'fatan1', 'fatan2', 'favg',
258
- 'fdot', 'fdot3', 'fmean', 'fmean_', 'fhorner', 'fidw', 'fpolynomial',
258
+ 'fdot', 'fdot3', 'fma', 'fmean', 'fmean_', 'fhorner', 'fidw', 'fpolynomial',
259
259
  'fpowers', 'fprod', 'frandoms', 'frange', 'freduce', 'fremainder',
260
260
  'hypot', 'hypot_', 'hypot1', 'hypot2', 'hypot2_',
261
261
  'norm2', 'norm_', 'sqrt0', 'sqrt3', 'sqrt_a', 'zcrt', 'zqrt'),
@@ -280,7 +280,7 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
280
280
  'FrechetVincentys', 'Frechet6Tuple',
281
281
  'frechet_'),
282
282
  fstats=_i('Fcook', 'Flinear', 'Fwelford'),
283
- fsums=_i('Fsum', 'DivMod2Tuple', 'Fsum2Tuple', 'ResidualError',
283
+ fsums=_i('Fsum', 'Fsum2product', 'DivMod2Tuple', 'Fsum2Tuple', 'ResidualError',
284
284
  'fsum', 'fsum_', 'fsumf_', 'fsum1', 'fsum1_', 'fsum1f_'),
285
285
  gars=_i('Garef', 'GARSError'),
286
286
  geodesici=_i('Intersectool', 'Intersectool5Tuple', 'Intersect7Tuple',
@@ -395,10 +395,10 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
395
395
  utmups=_i('UtmUps', 'UTMUPSError', 'parseUTMUPS5', 'toUtmUps8',
396
396
  'utmupsValidate', 'utmupsValidateOK', 'utmupsZoneBand5'),
397
397
  utmupsBase=_i(), # module only
398
- vector2d=_i('Circin6Tuple', 'Circum3Tuple', 'Circum4Tuple', 'Meeus2Tuple', 'Radii11Tuple', 'Soddy4Tuple',
399
- 'circin6', 'circum3', 'circum4_', 'meeus2', 'radii11', 'soddy4'),
398
+ vector2d=_i('Circin6Tuple', 'Circum3Tuple', 'Circum4Tuple', 'Meeus2Tuple', 'Radii11Tuple', 'Soddy4Tuple', 'Triaxum5Tuple',
399
+ 'circin6', 'circum3', 'circum4', 'circum4_', 'meeus2', 'radii11', 'soddy4', 'triaxum5', 'trilaterate2d2'),
400
400
  vector3d=_i('Vector3d', 'intersection3d3', 'iscolinearWith', 'nearestOn', 'nearestOn6', 'parse3d',
401
- 'trilaterate2d2', 'trilaterate3d2'),
401
+ 'trilaterate3d2'),
402
402
  vector3dBase=_i(), # module only
403
403
  webmercator=_i('Wm', 'WebMercatorError', 'parseWM', 'toWm', 'EasNorRadius3Tuple'),
404
404
  wgrs=_i('Georef', 'WGRSError'),)
@@ -416,8 +416,8 @@ _ALL_DEPRECATED = _NamedEnum_RO(_name='_ALL_DEPRECATED',
416
416
  deprecated_datum=_i('Curvature2Tuple', 'Datum', 'Ellipsoid', 'Transform', # assert
417
417
  'Datums', 'Ellipsoids', 'Transforms',
418
418
  'R_FM', 'R_KM', 'R_M', 'R_MA', 'R_MB', 'R_NM', 'R_SM', 'R_VM'),
419
- deprecated_functions=_i('anStr', 'areaof', 'atand', 'bounds', # most of the DEPRECATED functions, except ...
420
- 'clipCS3', 'clipDMS', 'clipStr', 'collins', 'copysign', # ... ellipsoidal, spherical flavors
419
+ deprecated_functions=_i('anStr', 'areaof', 'atand', 'bounds', # most of the DEPRECATED functions, except ellipsoidal ...
420
+ 'clipCS3', 'clipDMS', 'clipStr', 'collins', 'copysign', # ... and spherical flavors
421
421
  'decodeEPSG2', 'encodeEPSG', 'enStr2', 'equirectangular_', 'equirectangular3',
422
422
  'excessAbc', 'excessGirard', 'excessLHuilier',
423
423
  'false2f', 'falsed2f', 'float0', 'fStr', 'fStrzs', 'hypot3',
@@ -486,6 +486,11 @@ class _ALL_MODS(_internals._MODS_Base):
486
486
  except KeyError:
487
487
  return _getmodule(name, parent)
488
488
 
489
+ def imported(self, name):
490
+ '''Return module or package C{name} if already imported.
491
+ '''
492
+ return _sys.modules.get(name, None)
493
+
489
494
  def into(self, **mod_dunder_name_):
490
495
  '''Lazily import module C{mod} into module C{_dunder_name_}
491
496
  and set C{_dunder_name_._mod} to module C{mod}, I{once}.
@@ -521,7 +526,7 @@ class _ALL_MODS(_internals._MODS_Base):
521
526
  _internals._MODS = _ALL_MODS = _ALL_MODS() # PYCHOK singleton
522
527
 
523
528
  __all__ = _ALL_LAZY.lazily
524
- __version__ = '24.08.01'
529
+ __version__ = '24.09.09'
525
530
 
526
531
 
527
532
  def _ALL_OTHER(*objs):
pygeodesy/ltp.py CHANGED
@@ -44,7 +44,7 @@ from pygeodesy.vector3d import _ALL_LAZY, Vector3d
44
44
  # from math import fabs, floor as _floor # from .fmath, .fsums
45
45
 
46
46
  __all__ = _ALL_LAZY.ltp
47
- __version__ = '24.07.25'
47
+ __version__ = '24.08.18'
48
48
 
49
49
  _height0_ = _height_ + _0_
50
50
  _narrow_ = 'narrow'
@@ -165,7 +165,7 @@ class Attitude(_NamedBase):
165
165
  '''
166
166
  try:
167
167
  try:
168
- xyz = map2(float, x_xyz.xyz)
168
+ xyz = map2(float, x_xyz.xyz3)
169
169
  except AttributeError:
170
170
  xyz = map1(float, x_xyz, y, z)
171
171
  except (TypeError, ValueError) as x:
@@ -876,7 +876,7 @@ class ChLV(_ChLV, Ltp):
876
876
 
877
877
  @arg Y: Unfalsed I{Swiss Y} easting (C{meter}).
878
878
  @arg X: Unfalsed I{Swiss X} northing (C{meter}).
879
- @kwarg LV95: If C{True} add C{LV95} falsing, if C{False} add
879
+ @kwarg LV95: If C{True}, add C{LV95} falsing, if C{False} add
880
880
  C{LV03} falsing, otherwise leave unfalsed.
881
881
  @kwarg name: Optional C{B{name}=NN} (C{str}).
882
882
 
@@ -928,9 +928,8 @@ class ChLV(_ChLV, Ltp):
928
928
 
929
929
  @arg e: Falsed I{Swiss E_LV95} or I{y_LV03} easting (C{meter}).
930
930
  @arg n: Falsed I{Swiss N_LV95} or I{x_LV03} northing (C{meter}).
931
- @kwarg LV95: If C{True} remove I{LV95} falsing, if C{False} remove
932
- I{LV03} falsing, otherwise use method C{isLV95(B{e},
933
- B{n})}.
931
+ @kwarg LV95: If C{True}, remove I{LV95} falsing, if C{False} remove
932
+ I{LV03} falsing, otherwise use method C{isLV95(B{e}, B{n})}.
934
933
  @kwarg name: Optional C{B{name}=NN} (C{str}).
935
934
 
936
935
  @return: A L{ChLVYX2Tuple}C{(Y, X)} with the unfalsed B{C{e}}
pygeodesy/ltpTuples.py CHANGED
@@ -36,7 +36,7 @@ from pygeodesy.vector3d import Vector3d
36
36
  # from math import cos, radians # from .utily
37
37
 
38
38
  __all__ = _ALL_LAZY.ltpTuples
39
- __version__ = '24.07.25'
39
+ __version__ = '24.08.18'
40
40
 
41
41
  _aer_ = 'aer'
42
42
  _alt_ = 'alt'
@@ -189,6 +189,12 @@ class _AbcBase(_NamedBase):
189
189
  '''
190
190
  return Vector3Tuple(self.x, self.y, self.z, name=self.name) # like Ecef9Tuple.xyz, Local6tuple.xyz
191
191
 
192
+ @property_RO
193
+ def xyz3(self):
194
+ '''Get the I{local} C{(X, Y, Z)} coordinates as C{3-tuple}.
195
+ '''
196
+ return tuple(self.xyz)
197
+
192
198
  @property_RO
193
199
  def xyz4(self): # PYCHOK no cover
194
200
  '''I{Must be overloaded}.'''
pygeodesy/mgrs.py CHANGED
@@ -43,7 +43,7 @@ from pygeodesy.errors import _AssertionError, MGRSError, _parseX, \
43
43
  from pygeodesy.interns import NN, _0_, _A_, _AtoZnoIO_, _band_, _B_, \
44
44
  _COMMASPACE_, _datum_, _easting_, _invalid_, \
45
45
  _northing_, _SPACE_, _W_, _Y_, _Z_, _zone_
46
- from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _PYGEODESY_GEOCONVERT_
46
+ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
47
47
  from pygeodesy.named import _name2__, _NamedBase, _NamedTuple, _Pass
48
48
  from pygeodesy.namedTuples import EasNor2Tuple, UtmUps5Tuple
49
49
  from pygeodesy.props import deprecated_property_RO, property_RO, Property_RO
@@ -55,7 +55,7 @@ from pygeodesy.utm import toUtm8, _to3zBlat, Utm, _UTM_ZONE_MAX, _UTM_ZONE_MIN
55
55
  # from pygeodesy.utmupsBase import _UTM_ZONE_MAX, _UTM_ZONE_MIN # from .utm
56
56
 
57
57
  __all__ = _ALL_LAZY.mgrs
58
- __version__ = '24.06.11'
58
+ __version__ = '24.09.04'
59
59
 
60
60
  _AN_ = 'AN' # default south pole grid tile and band B
61
61
  _AtoPx_ = _AtoZnoIO_.tillP
@@ -652,51 +652,56 @@ def _um100km2(m):
652
652
 
653
653
  if __name__ == '__main__':
654
654
 
655
- from pygeodesy.ellipsoidalVincenty import fabs, LatLon
656
- # from pygeodesy.internals import printf # from .lazily
657
- from pygeodesy.lazily import _getenv, printf
655
+ def _main():
658
656
 
659
- # from math import fabs # from .ellipsoidalVincenty
660
- from os import access as _access, linesep as _NL, X_OK as _X_OK
657
+ from pygeodesy.ellipsoidalVincenty import fabs, LatLon
658
+ from pygeodesy.internals import _fper, printf
659
+ from pygeodesy.lazily import _getenv, _PYGEODESY_GEOCONVERT_
661
660
 
662
- # <https://GeographicLib.sourceforge.io/C++/doc/GeoConvert.1.html>
663
- _GeoConvert = _getenv(_PYGEODESY_GEOCONVERT_, '/opt/local/bin/GeoConvert')
664
- if _access(_GeoConvert, _X_OK):
665
- GC_m = _GeoConvert, '-m' # -m converts latlon to MGRS
666
- printf(' using: %s ...', _SPACE_.join(GC_m))
667
- from pygeodesy.solveBase import _popen2
668
- else:
669
- GC_m = _popen2 = None
661
+ # from math import fabs # from .ellipsoidalVincenty
662
+ from os import access as _access, linesep as _NL, X_OK as _X_OK
670
663
 
671
- e = n = 0
672
- try:
673
- for lat in range(-90, 91, 1):
674
- printf('%6s: lat %s ...', n, lat, end=NN, flush=True)
675
- nl = _NL
676
- for lon in range(-180, 181, 1):
677
- m = LatLon(lat, lon).toMgrs()
678
- if _popen2:
679
- t = '%s %s' % (lat, lon)
680
- g = _popen2(GC_m, stdin=t)[1]
681
- t = m.toStr() # sep=NN
682
- if t != g:
664
+ # <https://GeographicLib.sourceforge.io/C++/doc/GeoConvert.1.html>
665
+ _GeoConvert = _getenv(_PYGEODESY_GEOCONVERT_, '/opt/local/bin/GeoConvert')
666
+ if _access(_GeoConvert, _X_OK):
667
+ GC_m = _GeoConvert, '-m' # -m converts latlon to MGRS
668
+ printf(' using: %s ...', _SPACE_.join(GC_m))
669
+ from pygeodesy.solveBase import _popen2
670
+ else:
671
+ GC_m = _popen2 = None
672
+
673
+ e = n = 0
674
+ try:
675
+ for lat in range(-90, 91, 1):
676
+ printf('%6s: lat %s ...', n, lat, end=NN, flush=True)
677
+ nl = _NL
678
+ for lon in range(-180, 181, 1):
679
+ m = LatLon(lat, lon).toMgrs()
680
+ if _popen2:
681
+ t = '%s %s' % (lat, lon)
682
+ g = _popen2(GC_m, stdin=t)[1]
683
+ t = m.toStr() # sep=NN
684
+ if t != g:
685
+ e += 1
686
+ printf('%s%6s: %s: %r vs %r (lon %s)', nl, -e, m, t, g, lon)
687
+ nl = NN
688
+ t = m.toLatLon(LatLon=LatLon)
689
+ d = max(fabs(t.lat - lat), fabs(t.lon - lon))
690
+ if d > 1e-9 and -90 < lat < 90 and -180 < lon < 180:
683
691
  e += 1
684
- printf('%s%6s: %s: %r vs %r (lon %s)', nl, -e, m, t, g, lon)
692
+ printf('%s%6s: %s: %s vs %s %.6e', nl, -e, m, t.latlon,
693
+ (float(lat), float(lon)), d)
685
694
  nl = NN
686
- t = m.toLatLon(LatLon=LatLon)
687
- d = max(fabs(t.lat - lat), fabs(t.lon - lon))
688
- if d > 1e-9 and -90 < lat < 90 and -180 < lon < 180:
689
- e += 1
690
- printf('%s%6s: %s: %s vs %s %.6e', nl, -e, m, t.latlon, (float(lat), float(lon)), d)
691
- nl = NN
692
- n += 1
693
- if nl:
694
- printf(' OK')
695
- except KeyboardInterrupt:
696
- printf(nl)
697
-
698
- p = e * 100.0 / n
699
- printf('%6s: %s errors (%.2f%%)', n, (e if e else 'no'), p)
695
+ n += 1
696
+ if nl:
697
+ printf(' OK')
698
+ except KeyboardInterrupt:
699
+ printf(nl)
700
+
701
+ printf('%6s: %s errors (%s)', n, (e if e else 'no'), _fper(e, n, prec=2))
702
+
703
+ _main()
704
+
700
705
 
701
706
  # % python3 -m pygeodesy.mgrs
702
707
  # using: /opt/local/bin/GeoConvert -m ...
pygeodesy/named.py CHANGED
@@ -34,7 +34,7 @@ from pygeodesy.streprs import attrs, Fmt, lrstrip, pairs, reprs, unstr
34
34
  # from pygeodesy.units import _toUnit # _MODS
35
35
 
36
36
  __all__ = _ALL_LAZY.named
37
- __version__ = '24.07.12'
37
+ __version__ = '24.09.02'
38
38
 
39
39
  _COMMANL_ = _COMMA_ + _NL_
40
40
  _COMMASPACEDOT_ = _COMMASPACE_ + _DOT_
@@ -214,8 +214,8 @@ class _Named(object):
214
214
  def copy(self, deep=False, **name):
215
215
  '''Make a shallow or deep copy of this instance.
216
216
 
217
- @kwarg deep: If C{True} make a deep, otherwise
218
- a shallow copy (C{bool}).
217
+ @kwarg deep: If C{True}, make a deep, otherwise a shallow
218
+ copy (C{bool}).
219
219
  @kwarg name: Optional, non-empty C{B{name}=NN} (C{str}).
220
220
 
221
221
  @return: The copy (C{This class}).
@@ -233,7 +233,8 @@ class _Named(object):
233
233
  def dup(self, deep=False, **items):
234
234
  '''Duplicate this instance, replacing some attributes.
235
235
 
236
- @kwarg deep: If C{True} duplicate deep, otherwise shallow.
236
+ @kwarg deep: If C{True}, duplicate deep, otherwise shallow
237
+ (C{bool}).
237
238
  @kwarg items: Attributes to be changed (C{any}), including
238
239
  optional C{B{name}} (C{str}).
239
240
 
@@ -890,6 +891,9 @@ class _NamedEnumItem(_NamedBase):
890
891
  raise _AssertionError(t)
891
892
 
892
893
 
894
+ # from pygeodesy.props import _NamedProperty
895
+
896
+
893
897
  class _NamedTuple(tuple, _Named):
894
898
  '''(INTERNAL) Base for named C{tuple}s with both index I{and}
895
899
  attribute name access to the items.