pygeodesy 24.6.1__py2.py3-none-any.whl → 24.6.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 (89) hide show
  1. {PyGeodesy-24.6.1.dist-info → PyGeodesy-24.6.24.dist-info}/METADATA +2 -2
  2. PyGeodesy-24.6.24.dist-info/RECORD +117 -0
  3. pygeodesy/__init__.py +33 -32
  4. pygeodesy/albers.py +2 -2
  5. pygeodesy/auxilats/__init__.py +1 -1
  6. pygeodesy/auxilats/auxAngle.py +40 -39
  7. pygeodesy/auxilats/auxDLat.py +3 -2
  8. pygeodesy/auxilats/auxLat.py +16 -18
  9. pygeodesy/auxilats/auxily.py +1 -1
  10. pygeodesy/azimuthal.py +10 -10
  11. pygeodesy/basics.py +9 -1
  12. pygeodesy/booleans.py +53 -66
  13. pygeodesy/cartesianBase.py +143 -155
  14. pygeodesy/css.py +14 -18
  15. pygeodesy/datums.py +6 -6
  16. pygeodesy/deprecated/__init__.py +1 -1
  17. pygeodesy/deprecated/classes.py +16 -2
  18. pygeodesy/deprecated/datum.py +3 -3
  19. pygeodesy/deprecated/functions.py +6 -8
  20. pygeodesy/dms.py +23 -27
  21. pygeodesy/ecef.py +49 -55
  22. pygeodesy/elevations.py +4 -4
  23. pygeodesy/ellipsoidalBase.py +28 -70
  24. pygeodesy/ellipsoidalBaseDI.py +19 -23
  25. pygeodesy/ellipsoidalExact.py +3 -3
  26. pygeodesy/ellipsoidalGeodSolve.py +15 -23
  27. pygeodesy/ellipsoidalKarney.py +37 -60
  28. pygeodesy/ellipsoidalNvector.py +44 -50
  29. pygeodesy/ellipsoidalVincenty.py +11 -14
  30. pygeodesy/ellipsoids.py +107 -101
  31. pygeodesy/errors.py +101 -49
  32. pygeodesy/etm.py +32 -44
  33. pygeodesy/formy.py +55 -58
  34. pygeodesy/frechet.py +20 -23
  35. pygeodesy/fsums.py +4 -4
  36. pygeodesy/gars.py +3 -4
  37. pygeodesy/geodesici.py +909 -0
  38. pygeodesy/geodesicw.py +11 -13
  39. pygeodesy/geodesicx/__init__.py +4 -4
  40. pygeodesy/geodesicx/gx.py +18 -28
  41. pygeodesy/geodesicx/gxbases.py +20 -8
  42. pygeodesy/geodesicx/gxline.py +16 -22
  43. pygeodesy/geodsolve.py +102 -34
  44. pygeodesy/geohash.py +39 -60
  45. pygeodesy/geoids.py +28 -37
  46. pygeodesy/hausdorff.py +21 -23
  47. pygeodesy/heights.py +15 -28
  48. pygeodesy/internals.py +19 -12
  49. pygeodesy/interns.py +4 -10
  50. pygeodesy/iters.py +2 -2
  51. pygeodesy/karney.py +20 -4
  52. pygeodesy/ktm.py +13 -16
  53. pygeodesy/latlonBase.py +202 -191
  54. pygeodesy/lazily.py +96 -59
  55. pygeodesy/lcc.py +29 -32
  56. pygeodesy/ltp.py +43 -24
  57. pygeodesy/ltpTuples.py +190 -183
  58. pygeodesy/mgrs.py +35 -9
  59. pygeodesy/named.py +106 -72
  60. pygeodesy/namedTuples.py +43 -14
  61. pygeodesy/nvectorBase.py +23 -27
  62. pygeodesy/osgr.py +9 -9
  63. pygeodesy/points.py +7 -7
  64. pygeodesy/rhumb/__init__.py +1 -1
  65. pygeodesy/rhumb/aux_.py +5 -5
  66. pygeodesy/rhumb/bases.py +30 -31
  67. pygeodesy/rhumb/ekx.py +3 -4
  68. pygeodesy/rhumb/solve.py +8 -61
  69. pygeodesy/solveBase.py +22 -19
  70. pygeodesy/sphericalBase.py +26 -21
  71. pygeodesy/sphericalNvector.py +13 -13
  72. pygeodesy/sphericalTrigonometry.py +86 -97
  73. pygeodesy/streprs.py +8 -36
  74. pygeodesy/trf.py +3 -3
  75. pygeodesy/triaxials.py +117 -91
  76. pygeodesy/units.py +229 -321
  77. pygeodesy/unitsBase.py +116 -108
  78. pygeodesy/ups.py +26 -31
  79. pygeodesy/utily.py +12 -11
  80. pygeodesy/utm.py +35 -40
  81. pygeodesy/utmups.py +43 -46
  82. pygeodesy/utmupsBase.py +9 -10
  83. pygeodesy/vector3d.py +59 -62
  84. pygeodesy/vector3dBase.py +17 -15
  85. pygeodesy/webmercator.py +19 -21
  86. pygeodesy/wgrs.py +18 -20
  87. PyGeodesy-24.6.1.dist-info/RECORD +0 -116
  88. {PyGeodesy-24.6.1.dist-info → PyGeodesy-24.6.24.dist-info}/WHEEL +0 -0
  89. {PyGeodesy-24.6.1.dist-info → PyGeodesy-24.6.24.dist-info}/top_level.txt +0 -0
pygeodesy/osgr.py CHANGED
@@ -46,14 +46,14 @@ from pygeodesy.namedTuples import EasNor2Tuple, LatLon2Tuple, \
46
46
  from pygeodesy.props import Property_RO, property_RO
47
47
  from pygeodesy.streprs import _EN_WIDE, enstr2, _enstr2m3, Fmt, \
48
48
  _resolution10, unstr, _xzipairs
49
- from pygeodesy.units import Easting, Lam_, Lat, Lon, Northing, \
50
- Phi_, Scalar, _10um, _100km
49
+ from pygeodesy.units import Easting, Lamd, Lat, Lon, Northing, \
50
+ Phid, Scalar, _10um, _100km
51
51
  from pygeodesy.utily import degrees90, degrees180, sincostan3, truncate
52
52
 
53
53
  from math import cos, fabs, radians, sin, sqrt
54
54
 
55
55
  __all__ = _ALL_LAZY.osgr
56
- __version__ = '24.05.31'
56
+ __version__ = '24.06.15'
57
57
 
58
58
  _equivalent_ = 'equivalent'
59
59
  _OSGR_ = 'OSGR'
@@ -108,7 +108,7 @@ class _NG(object):
108
108
 
109
109
  @Property_RO
110
110
  def lam0(self): # True origin longitude C{radians}
111
- return Lam_(self.lon0)
111
+ return Lamd(self.lon0)
112
112
 
113
113
  @Property_RO
114
114
  def lat0(self): # True origin latitude, 49°N
@@ -160,7 +160,7 @@ class _NG(object):
160
160
 
161
161
  @Property_RO
162
162
  def phi0(self): # True origin latitude C{radians}
163
- return Phi_(self.lat0)
163
+ return Phid(self.lat0)
164
164
 
165
165
  def reverse(self, osgr): # convert C{osgr} to (ellipsoidal} LatLon, as I{Karney}'s
166
166
  # U{Reverse<https://GeographicLib.SourceForge.io/C++/doc/OSGB_8hpp_source.html>}
@@ -296,7 +296,7 @@ class Osgr(_NamedBase):
296
296
  @kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword
297
297
  arguments, ignored if C{B{LatLon} is None}.
298
298
 
299
- @return: A B{C{LatLon}} instance or if B{C{LatLon}} is C{None}
299
+ @return: A B{C{LatLon}} instance or if C{B{LatLon} is None}
300
300
  a L{LatLonDatum3Tuple}C{(lat, lon, datum)}.
301
301
 
302
302
  @note: While OS grid references are based on the OSGB36 datum,
@@ -520,8 +520,8 @@ def parseOSGR(strOSGR, Osgr=Osgr, **name_Osgr_kwds):
520
520
  optional, additional B{C{Osgr}} keyword arguments,
521
521
  ignored if C{B{Osgr} is None}.
522
522
 
523
- @return: An (B{C{Osgr}}) instance or if B{C{Osgr}} is
524
- C{None} an L{EasNor2Tuple}C{(easting, northing)}.
523
+ @return: An (B{C{Osgr}}) instance or if C{B{Osgr} is None}, an
524
+ L{EasNor2Tuple}C{(easting, northing)}.
525
525
 
526
526
  @raise OSGRError: Invalid B{C{strOSGR}}.
527
527
  '''
@@ -598,7 +598,7 @@ def toOsgr(latlon, lon=None, kTM=False, datum=_WGS84, Osgr=Osgr, # MCCABE 14
598
598
  and additional B{C{Osgr}} keyword arguments,
599
599
  ignored if C{B{Osgr} is None}.
600
600
 
601
- @return: An (B{C{Osgr}}) instance or if B{C{Osgr}} is C{None}
601
+ @return: An (B{C{Osgr}}) instance or if C{B{Osgr} is None}
602
602
  an L{EasNor2Tuple}C{(easting, northing)}.
603
603
 
604
604
  @note: If L{isint}C{(B{prec})} both easting and northing are
pygeodesy/points.py CHANGED
@@ -62,7 +62,7 @@ from pygeodesy.utily import atan2b, degrees90, degrees180, degrees2m, \
62
62
  from math import cos, fabs, fmod as _fmod, radians, sin
63
63
 
64
64
  __all__ = _ALL_LAZY.points
65
- __version__ = '24.05.25'
65
+ __version__ = '24.06.15'
66
66
 
67
67
  _ilat_ = 'ilat'
68
68
  _ilon_ = 'ilon'
@@ -391,7 +391,7 @@ class _Array2LatLon(_Basequence): # immutable, on purpose
391
391
  # check the attr indices
392
392
  for n, (ai, i) in enumerate(ais):
393
393
  if not isint(i):
394
- raise _IsnotError(int.__name__, **{ai: i})
394
+ raise _IsnotError(int, **{ai: i})
395
395
  i = int(i)
396
396
  if not 0 <= i < shape[1]:
397
397
  raise _ValueError(ai, i)
@@ -959,8 +959,8 @@ def areaOf(points, adjust=True, radius=R_M, wrap=True):
959
959
  the B{C{points}} (C{bool}).
960
960
 
961
961
  @return: Approximate area (I{square} C{meter}, same units as
962
- B{C{radius}} or C{radians} I{squared} if B{C{radius}}
963
- is C{None}).
962
+ B{C{radius}} or C{radians} I{squared} if C{B{radius}
963
+ is None}).
964
964
 
965
965
  @raise PointsError: Insufficient number of B{C{points}}
966
966
 
@@ -992,8 +992,8 @@ def boundsOf(points, wrap=False, LatLon=None): # was=True
992
992
  @kwarg LatLon: Optional class to return the C{bounds}
993
993
  corners (C{LatLon}) or C{None}.
994
994
 
995
- @return: A L{Bounds2Tuple}C{(latlonSW, latlonNE)} as
996
- B{C{LatLon}}s if B{C{LatLon}} is C{None} a
995
+ @return: A L{Bounds2Tuple}C{(latlonSW, latlonNE)}, each
996
+ a B{C{LatLon}} or if C{B{LatLon} is None}, a
997
997
  L{Bounds4Tuple}C{(latS, lonW, latN, lonE)}.
998
998
 
999
999
  @raise PointsError: Insufficient number of B{C{points}}
@@ -1479,7 +1479,7 @@ def nearestOn5(point, points, closed=False, wrap=False, adjust=True,
1479
1479
  spherical earth radius L{R_KM}).
1480
1480
  @kwarg LatLon_and_kwds: Optional, C{B{LatLon}=None} class to use for
1481
1481
  the closest point and additional B{C{LatLon}} keyword
1482
- arguments, ignored if C{B{LatLon}=None} or not given.
1482
+ arguments, ignored if C{B{LatLon} is None} or not given.
1483
1483
 
1484
1484
  @return: A L{NearestOn3Tuple}C{(closest, distance, angle)} with the
1485
1485
  {closest} point (B{C{LatLon}}) or if C{B{LatLon} is None},
@@ -9,7 +9,7 @@ u'''Package of lazily imported C{rhumb} modules L{rhumb.aux_}, L{rhumb.ekx} and
9
9
  from pygeodesy.lazily import _ALL_LAZY, _ALL_OTHER, _lazy_import_as, _unLazy0
10
10
 
11
11
  __all__ = _ALL_LAZY.rhumb
12
- __version__ = '24.05.24'
12
+ __version__ = '24.06.18'
13
13
 
14
14
  if _unLazy0: # or _isfrozen
15
15
  from pygeodesy.rhumb.aux_ import RhumbAux, RhumbLineAux
pygeodesy/rhumb/aux_.py CHANGED
@@ -47,7 +47,7 @@ from pygeodesy.rhumb.bases import RhumbBase, RhumbLineBase, \
47
47
  from math import ceil as _ceil, fabs, radians
48
48
 
49
49
  __all__ = _ALL_LAZY.rhumb_aux_
50
- __version__ = '24.05.29'
50
+ __version__ = '24.06.11'
51
51
 
52
52
  # DIGITS = (sizeof(real) * 8) bits
53
53
  # = (ctypes.sizeof(ctypes.c_double(1.0)) * 8) bits
@@ -74,14 +74,14 @@ class RhumbAux(RhumbBase):
74
74
  @kwarg a_earth: This rhumb's earth model (L{Datum}, L{Ellipsoid},
75
75
  L{Ellipsoid2}, L{a_f2Tuple}, 2-tuple C{(a, f)}) or
76
76
  the (equatorial) radius (C{meter}, conventionally).
77
- @kwarg f: The ellipsoid's flattening (C{scalar}), iff B{C{a_earth}} is
78
- C{scalar}, ignored otherwise.
77
+ @kwarg f: The ellipsoid's flattening (C{scalar}), required if B{C{a_earth}}
78
+ is C{scalar}, ignored otherwise.
79
79
  @kwarg exact: If C{True}, use the exact expressions for the I{Auxiliary
80
80
  Latitudes}, otherwise use the I{Fourier} series expansion
81
81
  (C{bool}), see also property C{exact}.
82
82
  @kwarg TMorder_name: Optional C{B{name}=NN} (C{str}) and optional
83
- keyword argument C{B{TMorder}=6} for the order of
84
- the L{KTransverseMercator}, see property C{TMorder}.
83
+ keyword argument C{B{TMorder}=6}, the order of the
84
+ L{KTransverseMercator}, see property C{TMorder}.
85
85
 
86
86
  @raise ImportError: Package C{numpy} not found or not installed, only
87
87
  required for area C{S12} when C{B{exact} is True}.
pygeodesy/rhumb/bases.py CHANGED
@@ -52,11 +52,11 @@ from pygeodesy.vector3d import _intersect3d3, Vector3d # in .Intersection below
52
52
  from math import cos, fabs
53
53
 
54
54
  __all__ = ()
55
- __version__ = '24.05.29'
55
+ __version__ = '24.06.18'
56
56
 
57
57
  _anti_ = _Dash('anti')
58
58
  _rls = [] # instances of C{RbumbLine...} to be updated
59
- _TRIPS = 65 # .Intersection, .PlumbTo, 19+
59
+ _TRIPS = 129 # .Intersection, .PlumbTo, 19+
60
60
 
61
61
 
62
62
  class _Lat(Lat):
@@ -716,7 +716,7 @@ class RhumbLineBase(_CapsBase):
716
716
  t = _xTMr(v.x, v.y, lon0=p.lon) # PYCHOK Reverse4Tuple
717
717
  d = _diff(t.lon - p.lon, t.lat) # PYCHOK t.lat + p.lat - p.lat
718
718
  p = _LL2T(t.lat + p.lat, t.lon) # PYCHOK t.lon + p.lon = lon0
719
- if d < tol: # 19 trips
719
+ if d < tol: # 19+ trips
720
720
  break
721
721
  else:
722
722
  raise ValueError(Fmt.no_convergence(d, tol))
@@ -724,7 +724,7 @@ class RhumbLineBase(_CapsBase):
724
724
  P = GDict(lat1=self.lat1, lat2=p.lat, lat0=other.lat1,
725
725
  lon1=self.lon1, lon2=p.lon, lon0=other.lon1,
726
726
  name=_dunder_nameof(self.Intersection, self.name))
727
- r = self.Inverse( p.lat, p.lon, outmask=Caps.DISTANCE)
727
+ r = self.Inverse(p.lat, p.lon, outmask=Caps.DISTANCE)
728
728
  t = other.Inverse(p.lat, p.lon, outmask=Caps.DISTANCE)
729
729
  P.set_(azi12= self.azi12, a12=r.a12, s12=r.s12,
730
730
  azi02=other.azi12, a02=t.a12, s02=t.s12,
@@ -824,9 +824,9 @@ class RhumbLineBase(_CapsBase):
824
824
  @kwarg exact: If C{None}, use a rhumb line perpendicular to this rhumb line,
825
825
  otherwise use an I{exact} C{Geodesic...} from the given point
826
826
  perpendicular to this rhumb line (C{bool} or C{Geodesic...}),
827
- see method L{Ellipsoid.geodesic_}.
828
- @kwarg eps: Optional tolerance for L{pygeodesy.intersection3d3} (C{EPS}),
829
- used only if C{B{exact} is None}.
827
+ see method L{geodesic_<pygeodesy.Ellipsoid.geodesic_>}.
828
+ @kwarg eps: Optional tolerance (C{EPS}), used only if C{B{exact} is None},
829
+ see function L{intersection3d3<pygeodesy.intersection3d3>}.
830
830
  @kwarg est: Optionally, an initial estimate for the distance C{s12} of the
831
831
  intersection I{along} this rhumb line (C{meter}), used only if
832
832
  C{B{exact} is not None}.
@@ -849,11 +849,11 @@ class RhumbLineBase(_CapsBase):
849
849
  <https://PyPI.org/project/geographiclib>}
850
850
  package not found or not installed.
851
851
 
852
- @raise IntersectionError: No convergence for this B{C{eps}} or no
853
- intersection for some other reason.
852
+ @raise IntersectionError: No convergence for this B{C{eps}} or B{C{tol}} or
853
+ no intersection for some other reason.
854
854
 
855
- @see: Methods C{distance2}, C{Intersecant2} and C{Intersection}
856
- and function L{pygeodesy.intersection3d3}.
855
+ @see: Methods C{distance2}, C{Intersecant2} and C{Intersection} and function
856
+ L{intersection3d3<pygeodesy.intersection3d3>}.
857
857
  '''
858
858
  Cs, tol = Caps, Float_(tol=tol, low=EPS, high=None)
859
859
 
@@ -899,7 +899,7 @@ class RhumbLineBase(_CapsBase):
899
899
  lat0=lat0, lon0=lon0, iteration=i, at=r.azi2 - self.azi12,
900
900
  name=_dunder_nameof(self.PlumbTo, self.name))
901
901
  except Exception as x: # Fsum(NAN) Value-, ZeroDivisionError
902
- raise IntersectionError(lat0, lon0, tol=tol, exact=exact,
902
+ raise IntersectionError(lat0=lat0, lon0=lon0, tol=tol, exact=exact,
903
903
  eps=eps, est=est, iteration=i, cause=x)
904
904
 
905
905
  return P
@@ -907,29 +907,28 @@ class RhumbLineBase(_CapsBase):
907
907
  def Position(self, s12, outmask=Caps.LATITUDE_LONGITUDE):
908
908
  '''Compute a point at a given distance on this rhumb line.
909
909
 
910
- @arg s12: The distance along this rhumb line from its origin to
911
- the point (C{meters}), can be negative.
912
- @kwarg outmask: Bit-or'ed combination of L{Caps} values specifying
913
- the quantities to be returned.
910
+ @arg s12: The distance along this rhumb line from its origin to the point
911
+ (C{meters}), can be negative.
912
+ @kwarg outmask: Bit-or'ed combination of L{Caps} values specifying the
913
+ quantities to be returned.
914
914
 
915
- @return: L{GDict} with 4 to 8 items C{azi12, a12, s12, S12, lat2,
916
- lat1, lon2, lon1} with latitude C{lat2} and longitude
917
- C{lon2} of the point in C{degrees}, the rhumb angle C{a12}
918
- in C{degrees} from the start point of and the area C{S12}
919
- under this rhumb line in C{meter} I{squared}.
915
+ @return: L{GDict} with 4 to 8 items C{azi12, a12, s12, S12, lat2, lat1,
916
+ lon2, lon1} with latitude C{lat2} and longitude C{lon2} of the
917
+ point in C{degrees}, the rhumb angle C{a12} in C{degrees} from
918
+ the start point of and the area C{S12} under this rhumb line
919
+ in C{meter} I{squared}.
920
920
 
921
- @raise ImportError: Package C{numpy} not found or not installed,
922
- only required for L{RhumbLineAux} area C{S12}
923
- when C{B{exact} is True}.
921
+ @raise ImportError: Package C{numpy} not found or not installed, required
922
+ only for L{RhumbLineAux} area C{S12} when C{B{exact}
923
+ is True}.
924
924
 
925
- @note: If B{C{s12}} is large enough that the rhumb line crosses a
926
- pole, the longitude of the second point is indeterminate and
927
- C{NAN} is returned for C{lon2} and area C{S12}.
925
+ @note: If B{C{s12}} is large enough that the rhumb line crosses a pole, the
926
+ longitude of the second point is indeterminate and C{NAN} is returned
927
+ for C{lon2} and area C{S12}.
928
928
 
929
- If the first point is a pole, the cosine of its latitude is
930
- taken to be C{sqrt(L{EPS})}. This position is extremely
931
- close to the actual pole and allows the calculation to be
932
- carried out in finite terms.
929
+ If the first point is a pole, the cosine of its latitude is taken to
930
+ be C{sqrt(L{EPS})}. This position is extremely close to the actual
931
+ pole and allows the calculation to be carried out in finite terms.
933
932
  '''
934
933
  return self._Position(self.m2degrees(s12), s12, outmask)
935
934
 
pygeodesy/rhumb/ekx.py CHANGED
@@ -43,7 +43,7 @@ from pygeodesy.utily import atan1, sincos2_
43
43
  from math import asinh, atan, cos, cosh, radians, sin, sinh, sqrt, tan
44
44
 
45
45
  __all__ = _ALL_LAZY.rhumb_ekx
46
- __version__ = '24.05.30'
46
+ __version__ = '24.06.11'
47
47
 
48
48
 
49
49
  class Rhumb(RhumbBase):
@@ -61,13 +61,12 @@ class Rhumb(RhumbBase):
61
61
  @kwarg a_earth: This rhumb's earth model (L{Datum}, L{Ellipsoid},
62
62
  L{Ellipsoid2}, L{a_f2Tuple}, 2-tuple C{(a, f)}) or
63
63
  the (equatorial) radius (C{meter}, conventionally).
64
- @kwarg f: The ellipsoid's flattening (C{scalar}), iff B{C{a_earth}} is
65
- C{scalar}, ignored otherwise.
64
+ @kwarg f: The ellipsoid's flattening (C{scalar}), required if B{C{a_earth}}
65
+ is C{scalar}, ignored otherwise.
66
66
  @kwarg exact: If C{True}, use an addition theorem for elliptic integrals
67
67
  to compute I{Divided differences}, otherwise use the I{Krüger}
68
68
  series expansion (C{bool} or C{None}), see also properties
69
69
  C{exact} and C{TMorder}.
70
- @kwarg name: Optional name (C{str}).
71
70
  @kwarg RA_TMorder_name: Optional C{B{name}=NN} (C{str}) and optional keyword
72
71
  arguments B{C{RAorder}=6} and B{C{TMorder}=6} to set the respective
73
72
  C{order}, see properties C{RAorder} and C{TMorder}.
pygeodesy/rhumb/solve.py CHANGED
@@ -21,7 +21,7 @@ from pygeodesy.solveBase import _SolveBase, _SolveLineBase
21
21
  from pygeodesy.utily import _unrollon, _Wrap, wrap360
22
22
 
23
23
  __all__ = _ALL_LAZY.rhumb_solve
24
- __version__ = '24.05.31'
24
+ __version__ = '24.06.04'
25
25
 
26
26
 
27
27
  class _RhumbSolveBase(_SolveBase):
@@ -37,9 +37,9 @@ class _RhumbSolveBase(_SolveBase):
37
37
  def _cmdBasic(self):
38
38
  '''(INTERNAL) Get the basic C{RhumbSolve} cmd (C{tuple}).
39
39
  '''
40
- return (self.RhumbSolve,) + self._e_option \
41
- + self._p_option \
42
- + self._s_option
40
+ return (self.RhumbSolve,) + (self._e_option +
41
+ self._p_option +
42
+ self._s_option)
43
43
 
44
44
  @Property
45
45
  def RhumbSolve(self):
@@ -423,59 +423,6 @@ if __name__ == '__main__':
423
423
  # p = rlS.ArcPosition(49.475527)
424
424
  # printf('ArcPosition: %s %r', p == r, p)
425
425
 
426
- # % python3 -m pygeodesy.rhumb.solve
427
-
428
- # version: /opt/local/bin/RhumbSolve: GeographicLib version 1.51
429
- #
430
- # Direct: GDict(S12=44095641862956.148438, azi12=51, lat1=40.6, lat2=71.6889, lon1=-73.8, lon2=0.25552, s12=5500000.0)
431
- # Direct3: Destination3Tuple(lat=71.6889, lon=0.25552, final=51.0)
432
- #
433
- # Inverse: GDict(S12=37395209100030.367188, a12=51.929543, azi12=77.76839, lat1=40.6, lat2=51.6, lon1=-73.8, lon2=-0.5, s12=5771083.383328)
434
- # Inverse1: 51.92954250756195
435
- # Inverse3: Distance3Tuple(distance=5771083.383328, initial=77.76839, final=77.76839)
436
- #
437
- # Inverse: GDict(S12=-63760642939072.492188, a12=115.02062, azi12=-92.388888, lat1=40.6, lat2=35.8, lon1=-73.8, lon2=140.3, s12=12782581.067684)
438
- # Inverse1: 115.02061966879258
439
- # Inverse3: Distance3Tuple(distance=12782581.067684, initial=267.611112, final=267.611112)
440
- #
441
- # Position: True GDict(S12=44095641862956.148438, azi12=51, lat1=40.6, lat2=71.6889, lon1=-73.8, lon2=0.25552, s12=5500000.0)
442
-
443
-
444
- # % python3 -m pygeodesy.rhumb.solve --verbose
445
-
446
- # RhumbSolve 'Test' 1: /opt/local/bin/RhumbSolve --version (invoke)
447
- # RhumbSolve 'Test' 1: /opt/local/bin/RhumbSolve: GeographicLib version 1.51 (0)
448
- # version: /opt/local/bin/RhumbSolve: GeographicLib version 1.51
449
- # RhumbSolve 'Test' 2: /opt/local/bin/RhumbSolve -p 10 \ 40.600000000000001 -73.799999999999997 51.0 5500000.0 (Direct)
450
- # RhumbSolve 'Test' 2: lat2=71.688899882813047, lon2=0.255519824423445, S12=44095641862956.148 (0)
451
-
452
- # Direct: GDict(S12=44095641862956.148438, azi12=51, lat1=40.6, lat2=71.6889, lon1=-73.8, lon2=0.25552, s12=5500000.0)
453
- # RhumbSolve 'Test' 3: /opt/local/bin/RhumbSolve -p 10 \ 40.600000000000001 -73.799999999999997 51.0 5500000.0 (Direct3)
454
- # RhumbSolve 'Test' 3: lat2=71.688899882813047, lon2=0.255519824423445, S12=44095641862956.148 (0)
455
- # Direct3: Destination3Tuple(lat=71.6889, lon=0.25552, final=51.0)
456
- # RhumbSolve 'Test' 4: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 51.600000000000001 -0.5 (Inverse)
457
- # RhumbSolve 'Test' 4: azi12=77.768389710255661, s12=5771083.3833280317, S12=37395209100030.367 (0)
458
-
459
- # Inverse: GDict(S12=37395209100030.367188, a12=51.929543, azi12=77.76839, lat1=40.6, lat2=51.6, lon1=-73.8, lon2=-0.5, s12=5771083.383328)
460
- # RhumbSolve 'Test' 5: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 51.600000000000001 -0.5 (Inverse1)
461
- # RhumbSolve 'Test' 5: azi12=77.768389710255661, s12=5771083.3833280317, S12=37395209100030.367 (0)
462
- # Inverse1: 51.92954250756195
463
- # RhumbSolve 'Test' 6: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 51.600000000000001 -0.5 (Inverse3)
464
- # RhumbSolve 'Test' 6: azi12=77.768389710255661, s12=5771083.3833280317, S12=37395209100030.367 (0)
465
- # Inverse3: Distance3Tuple(distance=5771083.383328, initial=77.76839, final=77.76839)
466
- # RhumbSolve 'Test' 7: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 35.799999999999997 140.300000000000011 (Inverse)
467
- # RhumbSolve 'Test' 7: azi12=-92.388887981699639, s12=12782581.0676841792, S12=-63760642939072.492 (0)
468
-
469
- # Inverse: GDict(S12=-63760642939072.492188, a12=115.02062, azi12=-92.388888, lat1=40.6, lat2=35.8, lon1=-73.8, lon2=140.3, s12=12782581.067684)
470
- # RhumbSolve 'Test' 8: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 35.799999999999997 140.300000000000011 (Inverse1)
471
- # RhumbSolve 'Test' 8: azi12=-92.388887981699639, s12=12782581.0676841792, S12=-63760642939072.492 (0)
472
- # Inverse1: 115.02061966879258
473
- # RhumbSolve 'Test' 9: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 35.799999999999997 140.300000000000011 (Inverse3)
474
- # RhumbSolve 'Test' 9: azi12=-92.388887981699639, s12=12782581.0676841792, S12=-63760642939072.492 (0)
475
- # Inverse3: Distance3Tuple(distance=12782581.067684, initial=267.611112, final=267.611112)
476
-
477
- # Position: True GDict(S12=44095641862956.148438, azi12=51, lat1=40.6, lat2=71.6889, lon1=-73.8, lon2=0.25552, s12=5500000.0)
478
-
479
426
 
480
427
  # % python3 -m pygeodesy.rhumb.solve
481
428
 
@@ -485,11 +432,11 @@ if __name__ == '__main__':
485
432
  # Direct3: Destination3Tuple(lat=71.6889, lon=0.25552, final=51.0)
486
433
 
487
434
  # Inverse: GDict(a12=51.929543, azi12=77.76839, lat1=40.6, lat2=51.6, lon1=-73.8, lon2=-0.5, s12=5771083.383328, S12=37395209100030.390625)
488
- # Inverse1: 51.92954250756191
435
+ # Inverse1: 51.929542507561905
489
436
  # Inverse3: Distance3Tuple(distance=5771083.383328, initial=77.76839, final=77.76839)
490
437
 
491
438
  # Inverse: GDict(a12=115.02062, azi12=-92.388888, lat1=40.6, lat2=35.8, lon1=-73.8, lon2=140.3, s12=12782581.067684, S12=-63760642939072.5)
492
- # Inverse1: 115.02061966879249
439
+ # Inverse1: 115.02061966879248
493
440
  # Inverse3: Distance3Tuple(distance=12782581.067684, initial=267.611112, final=267.611112)
494
441
 
495
442
  # Position: True GDict(azi12=51, lat1=40.6, lat2=71.6889, lon1=-73.8, lon2=0.25552, s12=5500000.0, S12=44095641862956.109375)
@@ -513,7 +460,7 @@ if __name__ == '__main__':
513
460
  # Inverse: GDict(a12=51.929543, azi12=77.76839, lat1=40.6, lat2=51.6, lon1=-73.8, lon2=-0.5, s12=5771083.383328, S12=37395209100030.390625)
514
461
  # RhumbSolve 'Test' 5: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 51.600000000000001 -0.5 (Inverse1)
515
462
  # RhumbSolve 'Test' 5: azi12=77.768389710255661, s12=5771083.383328028, S12=37395209100030.391 (0)
516
- # Inverse1: 51.92954250756191
463
+ # Inverse1: 51.929542507561905
517
464
  # RhumbSolve 'Test' 6: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 51.600000000000001 -0.5 (Inverse3)
518
465
  # RhumbSolve 'Test' 6: azi12=77.768389710255661, s12=5771083.383328028, S12=37395209100030.391 (0)
519
466
  # Inverse3: Distance3Tuple(distance=5771083.383328, initial=77.76839, final=77.76839)
@@ -523,7 +470,7 @@ if __name__ == '__main__':
523
470
  # Inverse: GDict(a12=115.02062, azi12=-92.388888, lat1=40.6, lat2=35.8, lon1=-73.8, lon2=140.3, s12=12782581.067684, S12=-63760642939072.5)
524
471
  # RhumbSolve 'Test' 8: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 35.799999999999997 140.300000000000011 (Inverse1)
525
472
  # RhumbSolve 'Test' 8: azi12=-92.388887981699654, s12=12782581.0676841699, S12=-63760642939072.5 (0)
526
- # Inverse1: 115.02061966879249
473
+ # Inverse1: 115.02061966879248
527
474
  # RhumbSolve 'Test' 9: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 35.799999999999997 140.300000000000011 (Inverse3)
528
475
  # RhumbSolve 'Test' 9: azi12=-92.388887981699654, s12=12782581.0676841699, S12=-63760642939072.5 (0)
529
476
  # Inverse3: Distance3Tuple(distance=12782581.067684, initial=267.611112, final=267.611112)
pygeodesy/solveBase.py CHANGED
@@ -13,7 +13,7 @@ from pygeodesy.internals import _enquote, printf
13
13
  from pygeodesy.interns import NN, _0_, _BACKSLASH_, _COMMASPACE_, \
14
14
  _EQUAL_, _Error_, _SPACE_, _UNUSED_
15
15
  from pygeodesy.karney import Caps, _CapsBase, GDict
16
- from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _unlazy
16
+ from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _sys_version_info2
17
17
  from pygeodesy.named import callername, _name2__, notOverloaded
18
18
  from pygeodesy.props import Property, Property_RO, property_RO, _update_all
19
19
  from pygeodesy.streprs import Fmt, fstr, fstrzs, pairs, strs
@@ -23,34 +23,37 @@ from pygeodesy.utily import unroll180, wrap360 # PYCHOK shared
23
23
  from subprocess import PIPE as _PIPE, Popen as _Popen, STDOUT as _STDOUT
24
24
 
25
25
  __all__ = _ALL_LAZY.solveBase
26
- __version__ = '24.05.31'
26
+ __version__ = '24.06.05'
27
27
 
28
- _ERROR_ = 'ERROR'
29
- _text_True = dict() if _unlazy else dict(text=True)
28
+ _ERROR_ = 'ERROR'
29
+ _Popen_kwds = dict(creationflags=0,
30
+ # executable=sys.executable, shell=True,
31
+ stdin=_PIPE, stdout=_PIPE, stderr=_STDOUT)
32
+ if _sys_version_info2 > (3, 6):
33
+ _Popen_kwds.update(text=True)
34
+ del _PIPE, _STDOUT, _sys_version_info2 # _ALL_LAZY
30
35
 
31
36
 
32
37
  def _cmd_stdin_(cmd, stdin): # PYCHOK no cover
33
38
  '''(INTERNAL) Cmd line, stdin and caller as sC{str}.
34
39
  '''
35
- c = Fmt.PAREN(callername(up=3))
36
- t = (c,) if stdin is None else (_BACKSLASH_, str(stdin), c)
37
- return _SPACE_.join(cmd + t)
40
+ if stdin is not None:
41
+ cmd += _BACKSLASH_, str(stdin)
42
+ cmd += Fmt.PAREN(callername(up=3)),
43
+ return _SPACE_.join(cmd)
38
44
 
39
45
 
40
- def _popen2(cmd, stdin=None): # in .mgrs, .test.base, .test.testMgrs
46
+ def _popen2(cmd, stdin=None): # in .mgrs, test.bases, .testMgrs
41
47
  '''(INTERNAL) Invoke C{B{cmd} tuple} and return C{exitcode}
42
48
  and all output to C{stdout/-err}.
43
49
  '''
44
- p = _Popen(cmd, creationflags=0,
45
- # executable=sys.executable, shell=True,
46
- stdin=_PIPE, stdout=_PIPE, stderr=_STDOUT,
47
- **_text_True) # PYCHOK kwArgs
48
- r = p.communicate(stdin)[0]
50
+ p = _Popen(cmd, **_Popen_kwds) # PYCHOK kwArgs
51
+ r = p.communicate(stdin)[0]
49
52
  return p.returncode, ub2str(r).strip()
50
53
 
51
54
 
52
- class _SolveLineSolveBase(_CapsBase):
53
- '''(NTERNAL) Base class for C{_Solve} and C{_LineSolve}.
55
+ class _SolveCapsBase(_CapsBase):
56
+ '''(NTERNAL) Base class for C{_SolveBase} and C{_LineSolveBase}.
54
57
  '''
55
58
  _Error = None
56
59
  _Exact = True
@@ -131,7 +134,7 @@ class _SolveLineSolveBase(_CapsBase):
131
134
 
132
135
  @note: The C{Solve} return code is in property L{status}.
133
136
  '''
134
- c = (self._Solve_path,) + map2(str, options)
137
+ c = (self._Solve_path,) + map2(str, options) # map2(_enquote, options)
135
138
  i = _xkwds_get1(stdin, stdin=None)
136
139
  r = self._invoke(c, stdin=i)
137
140
  s = self.status
@@ -270,7 +273,7 @@ class _SolveLineSolveBase(_CapsBase):
270
273
  return self.invoke('--version')
271
274
 
272
275
 
273
- class _SolveBase(_SolveLineSolveBase):
276
+ class _SolveBase(_SolveCapsBase):
274
277
  '''(NTERNAL) Base class for C{_GeodesicSolveBase} and C{_RhumbSolveBase}.
275
278
  '''
276
279
  _datum = _WGS84
@@ -387,7 +390,7 @@ class _SolveBase(_SolveLineSolveBase):
387
390
  return sep.join(pairs(d, prec=prec))
388
391
 
389
392
 
390
- class _SolveLineBase(_SolveLineSolveBase):
393
+ class _SolveLineBase(_SolveCapsBase):
391
394
  '''(NTERNAL) Base class for C{GeodesicLineSolve} and C{RhumbLineSolve}.
392
395
  '''
393
396
  # _caps = 0
@@ -448,7 +451,7 @@ class _SolveLineBase(_SolveLineSolveBase):
448
451
  return sep.join(pairs(d, prec=prec))
449
452
 
450
453
 
451
- __all__ += _ALL_DOCS(_SolveBase, _SolveLineBase, _SolveLineSolveBase)
454
+ __all__ += _ALL_DOCS(_SolveBase, _SolveLineBase, _SolveCapsBase)
452
455
 
453
456
  # **) MIT License
454
457
  #
@@ -19,7 +19,7 @@ from pygeodesy.constants import EPS, EPS0, PI, PI2, PI_2, R_M, \
19
19
  _over, isnear0, isnon0
20
20
  from pygeodesy.datums import Datums, _earth_ellipsoid, _spherical_datum
21
21
  from pygeodesy.errors import IntersectionError, _ValueError, \
22
- _xattr, _xError
22
+ _xattr, _xattrs, _xError
23
23
  from pygeodesy.fmath import favg, fdot, hypot, sqrt_a
24
24
  from pygeodesy.interns import _COMMA_, _concentric_, _datum_, _distant_, \
25
25
  _exceed_PI_radians_, _name_, _near_, \
@@ -27,10 +27,10 @@ from pygeodesy.interns import _COMMA_, _concentric_, _datum_, _distant_, \
27
27
  from pygeodesy.latlonBase import LatLonBase, _trilaterate5 # PYCHOK passed
28
28
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
29
29
  # from pygeodesy.namedTuples import Bearing2Tuple # from .cartesianBase
30
- from pygeodesy.nvectorBase import NvectorBase, Fmt, _xattrs
30
+ from pygeodesy.nvectorBase import NvectorBase, Fmt
31
31
  from pygeodesy.props import deprecated_method, property_doc_, property_RO, \
32
32
  _update_all
33
- # from pygeodesy.streprs import Fmt, _xattrs # from .nvectorBase
33
+ # from pygeodesy.streprs import Fmt # from .nvectorBase
34
34
  from pygeodesy.units import Bearing, Bearing_, _isRadius, Radians_, Radius, \
35
35
  Radius_, Scalar_, _100km
36
36
  from pygeodesy.utily import acos1, asin1, atan2b, atan2d, degrees90, \
@@ -40,7 +40,7 @@ from pygeodesy.utily import acos1, asin1, atan2b, atan2d, degrees90, \
40
40
  from math import cos, fabs, log, sin, sqrt
41
41
 
42
42
  __all__ = _ALL_LAZY.sphericalBase
43
- __version__ = '24.05.31'
43
+ __version__ = '24.06.12'
44
44
 
45
45
 
46
46
  class CartesianSphericalBase(CartesianBase):
@@ -380,7 +380,8 @@ class LatLonSphericalBase(LatLonBase):
380
380
  '''DEPRECATED, use method C{.rhumbAzimuthTo}.'''
381
381
  return self.rhumbAzimuthTo(other, b360=True) # [0..360)
382
382
 
383
- def rhumbDestination(self, distance, azimuth, radius=R_M, height=None, exact=False):
383
+ def rhumbDestination(self, distance, azimuth, radius=R_M, height=None,
384
+ exact=False, **name):
384
385
  '''Return the destination point having travelled the given distance from
385
386
  this point along a rhumb line (loxodrome) of the given azimuth.
386
387
 
@@ -393,6 +394,7 @@ class LatLonSphericalBase(LatLonBase):
393
394
  @kwarg height: Optional height, overriding the default height (C{meter}.
394
395
  @kwarg exact: If C{True}, use I{Elliptic, Krüger} L{Rhumb} (C{bool}),
395
396
  default C{False} for backward compatibility.
397
+ @kwarg name: Optional C{B{name}=NN} (C{str}).
396
398
 
397
399
  @return: The destination point (spherical C{LatLon}).
398
400
 
@@ -401,7 +403,7 @@ class LatLonSphericalBase(LatLonBase):
401
403
  '''
402
404
  if exact: # use series, always
403
405
  r = LatLonBase.rhumbDestination(self, distance, azimuth, exact=False, # Krüger
404
- radius=radius, height=height)
406
+ radius=radius, height=height, **name)
405
407
  else: # radius=None from .rhumbMidpointTo
406
408
  if radius in (None, self._radius):
407
409
  d, r = self.datum, radius
@@ -425,7 +427,7 @@ class LatLonSphericalBase(LatLonBase):
425
427
  b2 = b1 if isnear0(q) else (b1 + r * sb / q)
426
428
 
427
429
  h = self._heigHt(height)
428
- r = self.classof(degrees90(a2), degrees180(b2), datum=d, height=h)
430
+ r = self.classof(degrees90(a2), degrees180(b2), datum=d, height=h, **name)
429
431
  return r
430
432
 
431
433
  def rhumbDistanceTo(self, other, radius=R_M, exact=False, wrap=False):
@@ -441,8 +443,8 @@ class LatLonSphericalBase(LatLonBase):
441
443
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
442
444
  B{C{other}} point (C{bool}).
443
445
 
444
- @return: Distance (C{meter}, the same units as B{C{radius}}
445
- or C{radians} if B{C{radius}} is C{None}).
446
+ @return: Distance (C{meter}, the same units as B{C{radius}} or
447
+ C{radians} if C{B{radius} is None}).
446
448
 
447
449
  @raise TypeError: The B{C{other}} point is incompatible.
448
450
 
@@ -499,7 +501,7 @@ class LatLonSphericalBase(LatLonBase):
499
501
  height=height, wrap=wrap)
500
502
 
501
503
  def rhumbMidpointTo(self, other, height=None, radius=R_M, exact=False,
502
- fraction=_0_5, wrap=False):
504
+ fraction=_0_5, **wrap_name):
503
505
  '''Return the (loxodromic) midpoint on the rhumb line between
504
506
  this and an other point.
505
507
 
@@ -511,8 +513,9 @@ class LatLonSphericalBase(LatLonBase):
511
513
  default C{False} for backward compatibility.
512
514
  @kwarg fraction: Midpoint location from this point (C{scalar}), may
513
515
  be negative if C{B{exact}=True}.
514
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{other}}
515
- point (C{bool}).
516
+ @kwarg wrap_name: Optional C{B{name}=NN} (C{str}) and optional keyword
517
+ argument C{B{wrap}=False}, if C{True}, wrap or I{normalize}
518
+ and unroll the B{C{other}} point (C{bool}).
516
519
 
517
520
  @return: The (mid)point at the given B{C{fraction}} along the rhumb
518
521
  line (spherical C{LatLon}).
@@ -524,18 +527,21 @@ class LatLonSphericalBase(LatLonBase):
524
527
  if exact: # use series, always
525
528
  r = LatLonBase.rhumbMidpointTo(self, other, exact=False, # Krüger
526
529
  radius=radius, height=height,
527
- fraction=fraction, wrap=wrap)
530
+ fraction=fraction, **wrap_name)
528
531
  elif fraction is not _0_5:
529
532
  f = Scalar_(fraction=fraction) # low=_0_0
530
- r, db, dp = self._rhumbs3(other, wrap, r=True) # radians
533
+ w, n = self._wrap_name2(**wrap_name)
534
+ r, db, dp = self._rhumbs3(other, w, r=True) # radians
531
535
  z = atan2b(db, dp)
532
536
  h = self._havg(other, f=f, h=height)
533
- r = self.rhumbDestination(r * f, z, radius=None, height=h)
537
+ r = self.rhumbDestination(r * f, z, radius=None, height=h, name=n)
534
538
 
535
539
  else: # for backward compatibility, unwrapped
540
+ _, n = self._wrap_name2(**wrap_name)
536
541
  # see <https://MathForum.org/library/drmath/view/51822.html>
537
542
  a1, b1 = self.philam
538
543
  a2, b2 = self.others(other).philam
544
+ _, n = self._wrap_name2(**wrap_name)
539
545
 
540
546
  if fabs(b2 - b1) > PI:
541
547
  b1 += PI2 # crossing anti-meridian
@@ -557,7 +563,7 @@ class LatLonSphericalBase(LatLonBase):
557
563
  d = self.datum if radius in (None, self._radius) else \
558
564
  _spherical_datum(radius, name=self.name, raiser=_radius_)
559
565
  h = self._havg(other, h=height)
560
- r = self.classof(degrees90(a3), degrees180(b3), datum=d, height=h)
566
+ r = self.classof(degrees90(a3), degrees180(b3), datum=d, height=h, name=n)
561
567
  return r
562
568
 
563
569
  @property_RO
@@ -570,12 +576,11 @@ class LatLonSphericalBase(LatLonBase):
570
576
  '''Convert this point to C{Nvector} components, I{including
571
577
  height}.
572
578
 
573
- @kwarg Nvector_kwds: Optional, additional B{C{Nvector}}
574
- keyword arguments, ignored if
575
- C{B{Nvector} is None}.
579
+ @kwarg Nvector_kwds: Optional, additional B{C{Nvector}} keyword
580
+ arguments, ignored if C{B{Nvector} is None}.
576
581
 
577
- @return: An B{C{Nvector}} or a L{Vector4Tuple}C{(x, y, z, h)}
578
- if B{C{Nvector}} is C{None}.
582
+ @return: An B{C{Nvector}} or a L{Vector4Tuple}C{(x, y, z, h)} if
583
+ B{C{Nvector} is None}.
579
584
 
580
585
  @raise TypeError: Invalid B{C{Nvector}} or B{C{Nvector_kwds}}.
581
586
  '''