pygeodesy 24.8.4__py2.py3-none-any.whl → 24.8.24__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 (50) hide show
  1. {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.8.24.dist-info}/METADATA +16 -15
  2. {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.8.24.dist-info}/RECORD +50 -50
  3. {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.8.24.dist-info}/WHEEL +1 -1
  4. pygeodesy/__init__.py +23 -23
  5. pygeodesy/auxilats/auxDST.py +2 -2
  6. pygeodesy/basics.py +3 -3
  7. pygeodesy/cartesianBase.py +5 -5
  8. pygeodesy/constants.py +11 -11
  9. pygeodesy/ellipsoidalBase.py +18 -15
  10. pygeodesy/ellipsoidalExact.py +2 -2
  11. pygeodesy/ellipsoidalGeodSolve.py +2 -2
  12. pygeodesy/ellipsoidalKarney.py +2 -2
  13. pygeodesy/ellipsoidalNvector.py +2 -2
  14. pygeodesy/ellipsoidalVincenty.py +7 -6
  15. pygeodesy/epsg.py +3 -3
  16. pygeodesy/fmath.py +2 -1
  17. pygeodesy/fsums.py +4 -4
  18. pygeodesy/gars.py +9 -8
  19. pygeodesy/geodesicx/gx.py +3 -3
  20. pygeodesy/geodesicx/gxarea.py +3 -3
  21. pygeodesy/geodsolve.py +3 -3
  22. pygeodesy/geohash.py +18 -11
  23. pygeodesy/geoids.py +293 -315
  24. pygeodesy/heights.py +150 -158
  25. pygeodesy/internals.py +21 -1
  26. pygeodesy/interns.py +2 -3
  27. pygeodesy/latlonBase.py +13 -7
  28. pygeodesy/lazily.py +6 -6
  29. pygeodesy/ltp.py +5 -6
  30. pygeodesy/ltpTuples.py +7 -1
  31. pygeodesy/named.py +5 -4
  32. pygeodesy/namedTuples.py +14 -1
  33. pygeodesy/osgr.py +7 -7
  34. pygeodesy/points.py +2 -2
  35. pygeodesy/resections.py +7 -7
  36. pygeodesy/rhumb/solve.py +3 -3
  37. pygeodesy/simplify.py +10 -10
  38. pygeodesy/sphericalBase.py +3 -3
  39. pygeodesy/sphericalTrigonometry.py +2 -2
  40. pygeodesy/streprs.py +3 -3
  41. pygeodesy/triaxials.py +207 -201
  42. pygeodesy/units.py +3 -3
  43. pygeodesy/unitsBase.py +4 -4
  44. pygeodesy/utmupsBase.py +3 -3
  45. pygeodesy/vector2d.py +158 -51
  46. pygeodesy/vector3d.py +13 -52
  47. pygeodesy/vector3dBase.py +81 -63
  48. pygeodesy/webmercator.py +3 -3
  49. pygeodesy/wgrs.py +20 -22
  50. {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.8.24.dist-info}/top_level.txt +0 -0
pygeodesy/vector3dBase.py CHANGED
@@ -8,11 +8,11 @@ A pure Python implementation of vector-based functions by I{(C) Chris Veness
8
8
  <https://www.Movable-Type.co.UK/scripts/latlong-vectors.html>}.
9
9
  '''
10
10
 
11
- from pygeodesy.basics import _copysign, islistuple, isscalar, map1, \
12
- map2, _signOf, _zip
11
+ from pygeodesy.basics import _copysign, islistuple, isscalar, map1, map2, \
12
+ _signOf, _zip
13
13
  from pygeodesy.constants import EPS, EPS0, INT0, PI, PI2, _copysignINF, \
14
14
  _float0, isnear0, isnear1, isneg0, \
15
- _pos_self, _0_0, _1_0
15
+ _pos_self, _1_0
16
16
  from pygeodesy.errors import CrossError, VectorError, _xcallable, _xError
17
17
  from pygeodesy.fmath import euclid_, fdot, hypot_, hypot2_
18
18
  from pygeodesy.interns import _coincident_, _colinear_, _COMMASPACE_, _xyz_
@@ -24,13 +24,12 @@ from pygeodesy.props import deprecated_method, Property, Property_RO, \
24
24
  property_doc_, property_RO, _update_all
25
25
  from pygeodesy.streprs import Fmt, strs, unstr
26
26
  from pygeodesy.units import Float, Scalar
27
- # from pygeodesy.utily import sincos2 # _MODS
27
+ from pygeodesy.utily import sincos2, atan2, fabs
28
28
 
29
- # from builtints import hash, int, isinstance, map, max, round, type, zip
30
- from math import atan2, ceil, fabs, floor, trunc
29
+ from math import ceil as _ceil, floor as _floor, trunc as _trunc
31
30
 
32
31
  __all__ = _ALL_LAZY.vector3dBase
33
- __version__ = '24.06.11'
32
+ __version__ = '24.08.18'
34
33
 
35
34
 
36
35
  class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
@@ -61,7 +60,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
61
60
  @kwarg ll: Optional latlon reference (C{LatLon}).
62
61
  @kwarg name: Optional C{B{name}=NN} (C{str}).
63
62
 
64
- @raise VectorError: Invalid B{C{x_xyz}}.
63
+ @raise VectorError: Invalid B{C{x_xyz}}, B{C{y}} or B{C{z}}.
65
64
  '''
66
65
  self._x, \
67
66
  self._y, \
@@ -90,6 +89,8 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
90
89
 
91
90
  def __bool__(self): # PYCHOK PyChecker
92
91
  '''Is this vector non-zero?
92
+
93
+ @see: Method C{bools}.
93
94
  '''
94
95
  return bool(self.x or self.y or self.z)
95
96
 
@@ -98,7 +99,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
98
99
 
99
100
  @return: Ceil-ed (L{Vector3d}).
100
101
  '''
101
- return self._mapped(ceil)
102
+ return self._mapped(_ceil)
102
103
 
103
104
  def __cmp__(self, other): # Python 2-
104
105
  '''Compare this and an other vector (L{Vector3d}).
@@ -127,15 +128,15 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
127
128
  return self.isequalTo(other, eps=EPS0)
128
129
 
129
130
  def __float__(self): # PYCHOK no cover
130
- '''Not implemented.'''
131
- return _NotImplemented(self)
131
+ '''Not implemented, see method C{float}.'''
132
+ return _NotImplemented(self) # must return C{float}
132
133
 
133
134
  def __floor__(self): # PYCHOK no cover
134
135
  '''Return a vector with the C{floor} of these components.
135
136
 
136
137
  @return: Floor-ed (L{Vector3d}).
137
138
  '''
138
- return self._mapped(floor)
139
+ return self._mapped(_floor)
139
140
 
140
141
  def __floordiv__(self, other): # PYCHOK no cover
141
142
  '''Not implemented.'''
@@ -215,13 +216,8 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
215
216
  return self._xyz(self.times(scalar))
216
217
 
217
218
  def __int__(self): # PYCHOK no cover
218
- '''Return a vector with the C{int} of these components.
219
-
220
- @return: Int-ed (L{Vector3d}).
221
- '''
222
- v = self.classof(_0_0)
223
- v._x, v._y, v._z = map2(int, self.xyz)
224
- return v
219
+ '''Not implemented, see method C{ints}.'''
220
+ return _NotImplemented(self) # must return C{int}
225
221
 
226
222
  def __ipow__(self, other, *mod): # PYCHOK no cover
227
223
  '''Not implemented.'''
@@ -239,7 +235,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
239
235
  # def __iter__(self):
240
236
  # '''Return an C{iter}ator over this vector's components.
241
237
  # '''
242
- # return iter(self.xyz)
238
+ # return iter(self.xyz3)
243
239
 
244
240
  def __itruediv__(self, scalar):
245
241
  '''Divide this vector by a scalar I{in-place}, C{this /= B{scalar}}.
@@ -315,9 +311,9 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
315
311
  def __neg__(self):
316
312
  '''Return the opposite of this vector.
317
313
 
318
- @return: This instance negated (L{Vector3d})
314
+ @return: A negated copy (L{Vector3d})
319
315
  '''
320
- return self.classof(-self.x, -self.y, -self.z)
316
+ return self.negate()
321
317
 
322
318
  def __pos__(self): # PYCHOK no cover
323
319
  '''Return this vector I{as-is} or a copy.
@@ -370,7 +366,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
370
366
  @return: Rounded (L{Vector3d}).
371
367
  '''
372
368
  # <https://docs.Python.org/3.12/reference/datamodel.html?#object.__round__>
373
- return self.classof(*(round(_, *ndigits) for _ in self.xyz))
369
+ return self.classof(*(round(_, *ndigits) for _ in self.xyz3))
374
370
 
375
371
  def __rpow__(self, other, *mod): # PYCHOK no cover
376
372
  '''Not implemented.'''
@@ -423,7 +419,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
423
419
 
424
420
  @return: Trunc-ed (L{Vector3d}).
425
421
  '''
426
- return self._mapped(trunc)
422
+ return self._mapped(_trunc)
427
423
 
428
424
  if _sys_version_info2 < (3, 0): # PYCHOK no cover
429
425
  # <https://docs.Python.org/2/library/operator.html#mapping-operators-to-functions>
@@ -484,9 +480,14 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
484
480
  _f2 = fun2
485
481
 
486
482
  xyz = _xyz3(self.apply, other_x, *y_z)
487
- xyz = (_f2(a, b) for a, b in _zip(self.xyz, xyz)) # strict=True
483
+ xyz = (_f2(a, b) for a, b in _zip(self.xyz3, xyz)) # strict=True
488
484
  return self.classof(*xyz)
489
485
 
486
+ def bools(self):
487
+ '''Return the vector with C{bool} components.
488
+ '''
489
+ return self._mapped(bool)
490
+
490
491
  def cross(self, other, raiser=None, eps0=EPS): # raiser=NN
491
492
  '''Compute the cross product of this and an other vector.
492
493
 
@@ -502,11 +503,11 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
502
503
 
503
504
  @raise TypeError: Incompatible B{C{other}} C{type}.
504
505
  '''
505
- X, Y, Z = self.others(other).xyz
506
- x, y, z = self.xyz
507
- xyz = ((y * Z - Y * z),
508
- (z * X - Z * x),
509
- (x * Y - X * y))
506
+ X, Y, Z = self.others(other).xyz3
507
+ x, y, z = self.xyz3
508
+ xyz = ((y * Z - z * Y),
509
+ (z * X - x * Z),
510
+ (x * Y - y * X))
510
511
 
511
512
  if raiser and self.crosserrors and eps0 > 0 \
512
513
  and max(map(fabs, xyz)) < eps0:
@@ -516,7 +517,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
516
517
  t = _coincident_ if t else _colinear_
517
518
  raise CrossError(raiser, s, other=r, txt=t)
518
519
 
519
- return self.classof(*xyz)
520
+ return self.classof(*xyz) # name__=self.cross
520
521
 
521
522
  @property_doc_('''raise or ignore L{CrossError} exceptions (C{bool}).''')
522
523
  def crosserrors(self):
@@ -556,8 +557,8 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
556
557
 
557
558
  @raise TypeError: Incompatible B{C{other}} C{type}.
558
559
  '''
559
- return self.length2 if other is self else \
560
- fdot(self.xyz, *self.others(other).xyz)
560
+ return self.length2 if other is self else fdot(
561
+ self.xyz3, *self.others(other).xyz3)
561
562
 
562
563
  @deprecated_method
563
564
  def equals(self, other, units=False): # PYCHOK no cover
@@ -572,21 +573,31 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
572
573
  @see: Properties C{length} and C{length2} and function
573
574
  L{pygeodesy.euclid_}.
574
575
  '''
575
- return Float(euclid=euclid_(self.x, self.y, self.z))
576
+ return Float(euclid=euclid_(*self.xyz3))
576
577
 
577
578
  def equirectangular(self, other):
578
- '''I{Approximate} the different between this and an other vector.
579
+ '''I{Approximate} the difference between this and an other vector.
579
580
 
580
581
  @arg other: Vector to subtract (C{Vector3dBase}).
581
582
 
582
- @return: The lenght I{squared} of the difference (C{Float}).
583
+ @return: The length I{squared} of the difference (C{Float}).
583
584
 
584
585
  @raise TypeError: Incompatible B{C{other}} C{type}.
585
586
 
586
587
  @see: Property C{length2}.
587
588
  '''
588
589
  d = self.minus(other)
589
- return Float(equirectangular=hypot2_(d.x, d.y, d.z))
590
+ return Float(equirectangular=hypot2_(*d.xyz3))
591
+
592
+ def fabs(self):
593
+ '''Return the vector with C{fabs} components.
594
+ '''
595
+ return self._mapped(fabs)
596
+
597
+ def floats(self):
598
+ '''Return the vector with C{float} components.
599
+ '''
600
+ return self._mapped(_float0)
590
601
 
591
602
  @Property
592
603
  def _fromll(self):
@@ -604,7 +615,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
604
615
  def homogeneous(self):
605
616
  '''Get this vector's homogeneous representation (L{Vector3d}).
606
617
  '''
607
- x, y, z = self.xyz
618
+ x, y, z = self.xyz3
608
619
  if z:
609
620
  x = x / z # /= chokes PyChecker
610
621
  y = y / z
@@ -639,6 +650,11 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
639
650
  r = self.plus(r.minus(self)._times(f))
640
651
  return r
641
652
 
653
+ def ints(self):
654
+ '''Return the vector with C{int} components.
655
+ '''
656
+ return self._mapped(int)
657
+
642
658
  def isconjugateTo(self, other, minum=1, eps=EPS):
643
659
  '''Determine whether this and an other vector are conjugates.
644
660
 
@@ -657,7 +673,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
657
673
  '''
658
674
  self.others(other)
659
675
  n = 0
660
- for a, b in zip(self.xyz, other.xyz):
676
+ for a, b in zip(self.xyz3, other.xyz3):
661
677
  if fabs(a + b) < eps and ((a < 0 and b > 0) or
662
678
  (a > 0 and b < 0)):
663
679
  n += 1 # conjugate
@@ -685,7 +701,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
685
701
  d = self.unit().minus(other.unit())
686
702
  else:
687
703
  d = self.minus(other)
688
- return max(map(fabs, d.xyz)) < eps
704
+ return max(map(fabs, d.xyz3)) < eps
689
705
 
690
706
  @Property_RO
691
707
  def length(self): # __dict__ value overwritten by Property_RO C{_united}
@@ -704,9 +720,9 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
704
720
  return Float(length2=hypot2_(self.x, self.y, self.z))
705
721
 
706
722
  def _mapped(self, func):
707
- '''(INTERNAL) Map these components.
723
+ '''(INTERNAL) Apply C{func} to all components.
708
724
  '''
709
- return self.classof(*map2(func, self.xyz))
725
+ return self.classof(*map2(func, self.xyz3))
710
726
 
711
727
  def minus(self, other):
712
728
  '''Subtract an other vector from this vector.
@@ -717,8 +733,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
717
733
 
718
734
  @raise TypeError: Incompatible B{C{other}} C{type}.
719
735
  '''
720
- xyz = self.others(other).xyz
721
- return self._minus(*xyz)
736
+ return self._minus(*self.others(other).xyz3)
722
737
 
723
738
  def _minus(self, x, y, z):
724
739
  '''(INTERNAL) Helper for methods C{.minus} and C{.minus_}.
@@ -742,19 +757,17 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
742
757
  return self._minus(*_xyz3(self.minus_, other_x, *y_z))
743
758
 
744
759
  def negate(self):
745
- '''Return this vector in opposite direction.
760
+ '''Return the opposite of this vector.
746
761
 
747
- @return: New, opposite vector (L{Vector3d}).
762
+ @return: A negated copy (L{Vector3d})
748
763
  '''
749
764
  return self.classof(-self.x, -self.y, -self.z)
750
765
 
751
- __neg__ = negate # PYCHOK no cover
752
-
753
766
  @Property_RO
754
767
  def _N_vector(self):
755
768
  '''(INTERNAL) Get the (C{nvectorBase._N_vector_})
756
769
  '''
757
- return _MODS.nvectorBase._N_vector_(*self.xyz, name=self.name)
770
+ return _MODS.nvectorBase._N_vector_(*self.xyz3, name=self.name)
758
771
 
759
772
  def _other_cmp(self, other):
760
773
  '''(INTERNAL) Return the value for comparison.
@@ -786,8 +799,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
786
799
 
787
800
  @raise TypeError: Incompatible B{C{other}} C{type}.
788
801
  '''
789
- xyz = self.others(other).xyz
790
- return self._plus(*xyz)
802
+ return self._plus(*self.others(other).xyz3)
791
803
 
792
804
  sum = plus # alternate name
793
805
 
@@ -825,21 +837,21 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
825
837
  U{Quaternion-derived rotation matrix<https://WikiPedia.org/wiki/
826
838
  Quaternions_and_spatial_rotation#Quaternion-derived_rotation_matrix>}.
827
839
  '''
828
- s, c = _MODS.utily.sincos2(theta) # rotation angle
840
+ s, c = sincos2(theta) # rotation angle
829
841
  d = _1_0 - c
830
842
  if d or s:
831
843
  p = self.unit().xyz # point being rotated
832
844
  r = self.others(axis=axis).unit() # axis being rotated around
833
845
 
834
- ax, ay, az = r.xyz # quaternion-derived rotation matrix
835
- bx, by, bz = r.times(d).xyz
836
- sx, sy, sz = r.times(s).xyz
846
+ ax, ay, az = r.xyz3 # quaternion-derived rotation matrix
847
+ bx, by, bz = r.times(d).xyz3
848
+ sx, sy, sz = r.times(s).xyz3
837
849
 
838
850
  x = fdot(p, ax * bx + c, ax * by - sz, ax * bz + sy)
839
851
  y = fdot(p, ay * bx + sz, ay * by + c, ay * bz - sx)
840
852
  z = fdot(p, az * bx - sy, az * by + sx, az * bz + c)
841
853
  else: # unrotated
842
- x, y, z = self.xyz
854
+ x, y, z = self.xyz3
843
855
  return self.classof(x, y, z)
844
856
 
845
857
  @deprecated_method
@@ -911,7 +923,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
911
923
 
912
924
  @return: Vector as "(x, y, z)" (C{str}).
913
925
  '''
914
- t = sep.join(strs(self.xyz, prec=prec))
926
+ t = sep.join(strs(self.xyz3, prec=prec))
915
927
  return (fmt % (t,)) if fmt else t
916
928
 
917
929
  def unit(self, ll=None):
@@ -960,7 +972,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
960
972
  def xyz(self):
961
973
  '''Get the X, Y and Z components (L{Vector3Tuple}C{(x, y, z)}).
962
974
  '''
963
- return _MODS.namedTuples.Vector3Tuple(self.x, self.y, self.z, name=self.name)
975
+ return _MODS.namedTuples.Vector3Tuple(*self.xyz3, name=self.name)
964
976
 
965
977
  @xyz.setter # PYCHOK setter!
966
978
  def xyz(self, xyz):
@@ -977,6 +989,12 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
977
989
  self._x, self._y, self._z = _xyz3(_xyz_, x_xyz, *y_z)
978
990
  return self
979
991
 
992
+ @property_RO
993
+ def xyz3(self):
994
+ '''Get the X, Y and Z components as C{3-tuple}.
995
+ '''
996
+ return self.x, self.y, self.z
997
+
980
998
  @property_RO
981
999
  def x2y2z2(self):
982
1000
  '''Get the X, Y and Z components I{squared} (3-tuple C{(x**2, y**2, z**2)}).
@@ -1015,15 +1033,15 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
1015
1033
 
1016
1034
 
1017
1035
  def _xyz3(where, x_xyz, *y_z): # in .cartesianBase._rtp3
1018
- '''(INTERNAL) Helper for C{Vector3dBase.__init__}, C{-.apply}, C{-.times_} and C{-._xyz}.
1036
+ '''(INTERNAL) Get , Y and Z as 3-tuple C{(x, y, z)}.
1019
1037
  '''
1020
1038
  try:
1021
- x_y_z = map1(_float0, x_xyz, *y_z) if y_z else ( # islistuple for VectorXTuple
1022
- map2(_float0, x_xyz[:3]) if islistuple(x_xyz, minum=3) else
1023
- x_xyz.xyz)
1039
+ xyz3 = map1(_float0, x_xyz, *y_z) if y_z else ( # islistuple for Vector*Tuple
1040
+ map2(_float0, x_xyz[:3]) if islistuple(x_xyz, minum=3) else
1041
+ x_xyz.xyz) # .xyz3
1024
1042
  except (AttributeError, TypeError, ValueError) as x:
1025
1043
  raise _xError(x, unstr(where, x_xyz, *y_z))
1026
- return x_y_z
1044
+ return xyz3
1027
1045
 
1028
1046
 
1029
1047
  __all__ += _ALL_DOCS(Vector3dBase)
pygeodesy/webmercator.py CHANGED
@@ -36,7 +36,7 @@ from pygeodesy.utily import degrees90, degrees180
36
36
  from math import atan, atanh, exp, radians, sin, tanh
37
37
 
38
38
  __all__ = _ALL_LAZY.webmercator
39
- __version__ = '24.06.11'
39
+ __version__ = '24.08.13'
40
40
 
41
41
  # _FalseEasting = 0 # false Easting (C{meter})
42
42
  # _FalseNorthing = 0 # false Northing (C{meter})
@@ -207,7 +207,7 @@ class Wm(_NamedBase):
207
207
  @kwarg prec: Number of (decimal) digits, unstripped (C{int}).
208
208
  @kwarg fmt: Enclosing backets format (C{str}).
209
209
  @kwarg sep: Optional separator between name:value pairs (C{str}).
210
- @kwarg radius: If C{True} include the radius (C{bool}) or
210
+ @kwarg radius: If C{True}, include the radius (C{bool}) or
211
211
  C{scalar} to override this WM's radius.
212
212
 
213
213
  @return: This WM as "[x:meter, y:meter]" (C{str}) or as "[x:meter,
@@ -227,7 +227,7 @@ class Wm(_NamedBase):
227
227
  @kwarg fmt: Optional C{float} format (C{letter}).
228
228
  @kwarg sep: Optional separator to join (C{str}) or C{None}
229
229
  to return an unjoined C{tuple} of C{str}s.
230
- @kwarg radius: If C{True} include the radius (C{bool}) or
230
+ @kwarg radius: If C{True}, include the radius (C{bool}) or
231
231
  C{scalar} to override this WM's radius.
232
232
 
233
233
  @return: This WM as "meter meter" (C{str}) or as "meter meter
pygeodesy/wgrs.py CHANGED
@@ -3,8 +3,8 @@
3
3
 
4
4
  u'''World Geographic Reference System (WGRS) en-/decoding, aka GEOREF.
5
5
 
6
- Class L{Georef} and several functions to encode, decode and inspect
7
- WGRS (or GEOREF) references.
6
+ Class L{Georef} and several functions to encode, decode and inspect WGRS
7
+ (or GEOREF) references.
8
8
 
9
9
  Transcoded from I{Charles Karney}'s C++ class U{Georef
10
10
  <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Georef.html>},
@@ -19,8 +19,8 @@ from pygeodesy.constants import INT0, _float, _off90, _0_001, \
19
19
  from pygeodesy.dms import parse3llh
20
20
  from pygeodesy.errors import _ValueError, _xattr, _xStrError
21
21
  from pygeodesy.interns import NN, _0to9_, _AtoZnoIO_, _COMMA_, \
22
- _height_, _radius_, _SPACE_
23
- from pygeodesy.lazily import _ALL_LAZY, _ALL_OTHER
22
+ _height_, _INV_, _radius_, _SPACE_
23
+ from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
24
24
  from pygeodesy.named import _name2__, nameof, isstr, Property_RO
25
25
  from pygeodesy.namedTuples import LatLon2Tuple, LatLonPrec3Tuple
26
26
  # from pygeodesy.props import Property_RO # from .named
@@ -32,13 +32,12 @@ from pygeodesy.utily import ft2m, m2ft, m2NM
32
32
  from math import floor
33
33
 
34
34
  __all__ = _ALL_LAZY.wgrs
35
- __version__ = '24.08.02'
35
+ __version__ = '24.08.15'
36
36
 
37
37
  _Base = 10
38
38
  _BaseLen = 4
39
39
  _DegChar = _AtoZnoIO_.tillQ
40
40
  _Digits = _0to9_
41
- _INV_ = 'INV' # INValid
42
41
  _LatOrig = -90
43
42
  _LatTile = _AtoZnoIO_.tillM
44
43
  _LonOrig = -180
@@ -79,13 +78,12 @@ def _2geostr2(georef):
79
78
  '''(INTERNAL) Check a georef string.
80
79
  '''
81
80
  try:
82
- n, geostr = len(georef), georef.upper()
81
+ n, g = len(georef), georef.upper()
83
82
  p, o = divmod(n, 2)
84
83
  if o or n < _MinLen or n > _MaxLen \
85
- or geostr[:3] == _INV_ \
86
- or not geostr.isalnum():
84
+ or g.startswith(_INV_) or not g.isalnum():
87
85
  raise ValueError()
88
- return geostr, _2Precision(p - 1)
86
+ return g, _2Precision(p - 1)
89
87
 
90
88
  except (AttributeError, TypeError, ValueError) as x:
91
89
  raise WGRSError(Georef.__name__, georef, cause=x)
@@ -234,8 +232,8 @@ def decode3(georef, center=True):
234
232
  '''Decode a C{georef} to lat-, longitude and precision.
235
233
 
236
234
  @arg georef: To be decoded (L{Georef} or C{str}).
237
- @kwarg center: If C{True} the center, otherwise the south-west,
238
- lower-left corner (C{bool}).
235
+ @kwarg center: If C{True}, use the georef's center, otherwise
236
+ the south-west, lower-left corner (C{bool}).
239
237
 
240
238
  @return: A L{LatLonPrec3Tuple}C{(lat, lon, precision)}.
241
239
 
@@ -287,8 +285,8 @@ def decode5(georef, center=True):
287
285
  '''Decode a C{georef} to lat-, longitude, precision, height and radius.
288
286
 
289
287
  @arg georef: To be decoded (L{Georef} or C{str}).
290
- @kwarg center: If C{True} the center, otherwise the south-west,
291
- lower-left corner (C{bool}).
288
+ @kwarg center: If C{True}, use the georef's center, otherwise the
289
+ south-west, lower-left corner (C{bool}).
292
290
 
293
291
  @return: A L{LatLonPrec5Tuple}C{(lat, lon, precision, height, radius)}
294
292
  where C{height} and/or C{radius} are C{None} if missing.
@@ -335,12 +333,11 @@ def encode(lat, lon, precision=3, height=None, radius=None): # MCCABE 14
335
333
 
336
334
  @raise WGRSError: Invalid B{C{precision}}, B{C{height}} or B{C{radius}}.
337
335
 
338
- @note: The B{C{precision}} value differs from U{Georef<https://
336
+ @note: The B{C{precision}} value differs from I{Karney}'s U{Georef<https://
339
337
  GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Georef.html>}.
340
- The C{georef} length is M{2 * (precision + 1)} and the
341
- C{georef} resolution is I{15°} for B{C{precision}} 0, I{1°}
342
- for 1, I{1′} for 2, I{0.1′} for 3, I{0.01′} for 4, ...
343
- M{10**(2 - precision)}.
338
+ The C{georef} length is M{2 * (precision + 1)} and the C{georef}
339
+ resolution is I{15°} for B{C{precision}} 0:, I{1°} for 1, I{1′} for 2,
340
+ I{0.1′} for 3, I{0.01′} for 4, ... up to I{10**(2 - precision)′}.
344
341
  '''
345
342
  def _option(name, m, m2_, K):
346
343
  f = Scalar_(m, name=name, Error=WGRSError)
@@ -413,7 +410,8 @@ def resolution(prec):
413
410
  '''
414
411
  p = Int(prec=prec, Error=WGRSError)
415
412
  if p > 1:
416
- r = _1_0 / (_60_0 * pow(_Base, min(p, _MaxPrec) - 1))
413
+ p = min(p, _MaxPrec) - 1
414
+ r = _1_0 / (pow(_Base, p) * _60_0)
417
415
  elif p < 1:
418
416
  r = _float_Tile
419
417
  else:
@@ -421,8 +419,8 @@ def resolution(prec):
421
419
  return r
422
420
 
423
421
 
424
- __all__ += _ALL_OTHER(decode3, decode5, # functions
425
- encode, precision, resolution)
422
+ __all__ += _ALL_DOCS(decode3, decode5, # functions
423
+ encode, precision, resolution)
426
424
 
427
425
  # **) MIT License
428
426
  #