pygeodesy 24.5.24__py2.py3-none-any.whl → 24.6.1__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 (57) hide show
  1. {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.1.dist-info}/METADATA +6 -5
  2. {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.1.dist-info}/RECORD +57 -57
  3. pygeodesy/__init__.py +4 -4
  4. pygeodesy/auxilats/__init__.py +1 -1
  5. pygeodesy/auxilats/__main__.py +2 -2
  6. pygeodesy/auxilats/auxAngle.py +4 -4
  7. pygeodesy/basics.py +39 -5
  8. pygeodesy/booleans.py +3 -3
  9. pygeodesy/constants.py +3 -3
  10. pygeodesy/deprecated/functions.py +9 -3
  11. pygeodesy/ecef.py +22 -21
  12. pygeodesy/ellipsoidalBase.py +15 -16
  13. pygeodesy/ellipsoidalGeodSolve.py +2 -2
  14. pygeodesy/ellipsoidalKarney.py +3 -3
  15. pygeodesy/ellipsoids.py +6 -5
  16. pygeodesy/errors.py +19 -9
  17. pygeodesy/etm.py +16 -21
  18. pygeodesy/fmath.py +9 -20
  19. pygeodesy/formy.py +60 -74
  20. pygeodesy/frechet.py +11 -11
  21. pygeodesy/fsums.py +59 -25
  22. pygeodesy/geodesicx/__init__.py +1 -1
  23. pygeodesy/geodesicx/__main__.py +2 -2
  24. pygeodesy/geodesicx/gx.py +3 -5
  25. pygeodesy/geodsolve.py +2 -2
  26. pygeodesy/geohash.py +14 -14
  27. pygeodesy/hausdorff.py +12 -12
  28. pygeodesy/heights.py +5 -5
  29. pygeodesy/internals.py +3 -3
  30. pygeodesy/karney.py +8 -7
  31. pygeodesy/lazily.py +2 -2
  32. pygeodesy/ltp.py +62 -44
  33. pygeodesy/ltpTuples.py +202 -147
  34. pygeodesy/mgrs.py +24 -24
  35. pygeodesy/named.py +68 -70
  36. pygeodesy/nvectorBase.py +2 -2
  37. pygeodesy/osgr.py +40 -48
  38. pygeodesy/points.py +10 -10
  39. pygeodesy/props.py +29 -16
  40. pygeodesy/rhumb/aux_.py +13 -15
  41. pygeodesy/rhumb/bases.py +12 -5
  42. pygeodesy/rhumb/ekx.py +24 -18
  43. pygeodesy/rhumb/solve.py +13 -10
  44. pygeodesy/simplify.py +16 -16
  45. pygeodesy/solveBase.py +14 -14
  46. pygeodesy/sphericalBase.py +17 -21
  47. pygeodesy/sphericalTrigonometry.py +17 -17
  48. pygeodesy/trf.py +9 -7
  49. pygeodesy/triaxials.py +2 -2
  50. pygeodesy/ups.py +66 -70
  51. pygeodesy/utily.py +3 -3
  52. pygeodesy/utm.py +152 -156
  53. pygeodesy/utmups.py +38 -38
  54. pygeodesy/utmupsBase.py +102 -106
  55. pygeodesy/webmercator.py +43 -51
  56. {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.1.dist-info}/WHEEL +0 -0
  57. {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.1.dist-info}/top_level.txt +0 -0
@@ -21,18 +21,18 @@ from pygeodesy.datums import Datums, _earth_ellipsoid, _spherical_datum
21
21
  from pygeodesy.errors import IntersectionError, _ValueError, \
22
22
  _xattr, _xError
23
23
  from pygeodesy.fmath import favg, fdot, hypot, sqrt_a
24
- from pygeodesy.interns import NN, _COMMA_, _concentric_, _datum_, \
25
- _distant_, _exceed_PI_radians_, _name_, \
26
- _near_, _radius_, _too_
24
+ from pygeodesy.interns import _COMMA_, _concentric_, _datum_, _distant_, \
25
+ _exceed_PI_radians_, _name_, _near_, \
26
+ _radius_, _too_
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
30
  from pygeodesy.nvectorBase import NvectorBase, Fmt, _xattrs
31
- from pygeodesy.props import deprecated_method, property_doc_, \
32
- property_RO, _update_all
31
+ from pygeodesy.props import deprecated_method, property_doc_, property_RO, \
32
+ _update_all
33
33
  # from pygeodesy.streprs import Fmt, _xattrs # from .nvectorBase
34
- from pygeodesy.units import _isRadius, Bearing, Bearing_, Radians_, \
35
- Radius, Radius_, Scalar_, _100km
34
+ from pygeodesy.units import Bearing, Bearing_, _isRadius, Radians_, Radius, \
35
+ Radius_, Scalar_, _100km
36
36
  from pygeodesy.utily import acos1, asin1, atan2b, atan2d, degrees90, \
37
37
  degrees180, sincos2, sincos2d, _unrollon, \
38
38
  tanPI_2_2, wrapPI
@@ -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__ = '23.12.18'
43
+ __version__ = '24.05.31'
44
44
 
45
45
 
46
46
  class CartesianSphericalBase(CartesianBase):
@@ -117,7 +117,7 @@ class LatLonSphericalBase(LatLonBase):
117
117
  _datum = Datums.Sphere # spherical L{Datum}
118
118
  _napieradius = _100km
119
119
 
120
- def __init__(self, latlonh, lon=None, height=0, datum=None, wrap=False, name=NN):
120
+ def __init__(self, latlonh, lon=None, height=0, datum=None, wrap=False, **name):
121
121
  '''Create a spherical C{LatLon} point frome the given lat-, longitude and
122
122
  height on the given datum.
123
123
 
@@ -132,12 +132,12 @@ class LatLonSphericalBase(LatLonBase):
132
132
  conventionally).
133
133
  @kwarg wrap: If C{True}, wrap or I{normalize} B{C{lat}} and B{C{lon}}
134
134
  (C{bool}).
135
- @kwarg name: Optional name (C{str}).
135
+ @kwarg name: Optional C{B{name}=NN} (C{str}).
136
136
 
137
137
  @raise TypeError: If B{C{latlonh}} is not a C{LatLon} or B{C{datum}} not
138
138
  spherical.
139
139
  '''
140
- LatLonBase.__init__(self, latlonh, lon=lon, height=height, wrap=wrap, name=name)
140
+ LatLonBase.__init__(self, latlonh, lon=lon, height=height, wrap=wrap, **name)
141
141
  if datum not in (None, self.datum):
142
142
  self.datum = datum
143
143
 
@@ -302,26 +302,22 @@ class LatLonSphericalBase(LatLonBase):
302
302
  # raise _xError(x, this=self, point=point, other=other, **radius_exact_height_wrap)
303
303
  # return p.midpointTo(q)
304
304
 
305
- def parse(self, strllh, height=0, sep=_COMMA_, name=NN):
305
+ def parse(self, strllh, height=0, sep=_COMMA_, **name):
306
306
  '''Parse a string representing a similar, spherical C{LatLon}
307
307
  point, consisting of C{"lat, lon[, height]"}.
308
308
 
309
- @arg strllh: Lat, lon and optional height (C{str}),
310
- see function L{pygeodesy.parse3llh}.
309
+ @arg strllh: Lat, lon and optional height (C{str}), see function
310
+ L{pygeodesy.parse3llh}.
311
311
  @kwarg height: Optional, default height (C{meter}).
312
312
  @kwarg sep: Optional separator (C{str}).
313
- @kwarg name: Optional instance name (C{str}),
314
- overriding this name.
313
+ @kwarg name: Optional C{B{name}=NN} (C{str}), overriding this name.
315
314
 
316
315
  @return: The similar point (spherical C{LatLon}).
317
316
 
318
317
  @raise ParseError: Invalid B{C{strllh}}.
319
318
  '''
320
- t = _MODS.dms.parse3llh(strllh, height=height, sep=sep)
321
- r = self.classof(*t)
322
- if name:
323
- r.rename(name)
324
- return r
319
+ llh = _MODS.dms.parse3llh(strllh, height=height, sep=sep)
320
+ return self.classof(*llh, **name)
325
321
 
326
322
  @property_RO
327
323
  def _radius(self):
@@ -54,7 +54,7 @@ from pygeodesy.vector3d import sumOf, Vector3d
54
54
  from math import asin, atan2, cos, degrees, fabs, radians, sin
55
55
 
56
56
  __all__ = _ALL_LAZY.sphericalTrigonometry
57
- __version__ = '24.045.19'
57
+ __version__ = '24.05.25'
58
58
 
59
59
  _PI_EPS4 = PI - EPS4
60
60
  if _PI_EPS4 >= PI:
@@ -538,7 +538,7 @@ class LatLon(LatLonSphericalBase):
538
538
  def nearestOn(self, point1, point2, radius=R_M, **wrap_adjust_limit):
539
539
  '''Locate the point between two points closest to this point.
540
540
 
541
- Distances are approximated by function L{pygeodesy.equirectangular_},
541
+ Distances are approximated by function L{pygeodesy.equirectangular4},
542
542
  subject to the supplied B{C{options}}.
543
543
 
544
544
  @arg point1: Start point (L{LatLon}).
@@ -546,12 +546,12 @@ class LatLon(LatLonSphericalBase):
546
546
  @kwarg radius: Mean earth radius (C{meter}).
547
547
  @kwarg wrap_adjust_limit: Optional keyword arguments for functions
548
548
  L{sphericalTrigonometry.nearestOn3} and
549
- L{pygeodesy.equirectangular_},
549
+ L{pygeodesy.equirectangular4},
550
550
 
551
551
  @return: Closest point on the great circle line (L{LatLon}).
552
552
 
553
553
  @raise LimitError: Lat- and/or longitudinal delta exceeds B{C{limit}},
554
- see function L{pygeodesy.equirectangular_}.
554
+ see function L{pygeodesy.equirectangular4}.
555
555
 
556
556
  @raise NotImplementedError: Keyword argument C{B{within}=False}
557
557
  is not (yet) supported.
@@ -560,7 +560,7 @@ class LatLon(LatLonSphericalBase):
560
560
 
561
561
  @raise ValueError: Invalid B{C{radius}} or B{C{options}}.
562
562
 
563
- @see: Functions L{pygeodesy.equirectangular_} and L{pygeodesy.nearestOn5}
563
+ @see: Functions L{pygeodesy.equirectangular4} and L{pygeodesy.nearestOn5}
564
564
  and method L{sphericalTrigonometry.LatLon.nearestOn3}.
565
565
  '''
566
566
  # remove kwarg B{C{within}} if present
@@ -605,7 +605,7 @@ class LatLon(LatLonSphericalBase):
605
605
  def nearestOn3(self, points, closed=False, radius=R_M, **wrap_adjust_limit):
606
606
  '''Locate the point on a polygon closest to this point.
607
607
 
608
- Distances are approximated by function L{pygeodesy.equirectangular_},
608
+ Distances are approximated by function L{pygeodesy.equirectangular4},
609
609
  subject to the supplied B{C{options}}.
610
610
 
611
611
  @arg points: The polygon points (L{LatLon}[]).
@@ -613,17 +613,17 @@ class LatLon(LatLonSphericalBase):
613
613
  @kwarg radius: Mean earth radius (C{meter}).
614
614
  @kwarg wrap_adjust_limit: Optional keyword arguments for function
615
615
  L{sphericalTrigonometry.nearestOn3} and
616
- L{pygeodesy.equirectangular_},
616
+ L{pygeodesy.equirectangular4},
617
617
 
618
618
  @return: A L{NearestOn3Tuple}C{(closest, distance, angle)} of the
619
- C{closest} point (L{LatLon}), the L{pygeodesy.equirectangular_}
619
+ C{closest} point (L{LatLon}), the L{pygeodesy.equirectangular4}
620
620
  C{distance} between this and the C{closest} point converted to
621
621
  C{meter}, same units as B{C{radius}}. The C{angle} from this
622
622
  to the C{closest} point is in compass C{degrees360}, like
623
623
  function L{pygeodesy.compassAngle}.
624
624
 
625
625
  @raise LimitError: Lat- and/or longitudinal delta exceeds B{C{limit}},
626
- see function L{pygeodesy.equirectangular_}.
626
+ see function L{pygeodesy.equirectangular4}.
627
627
 
628
628
  @raise PointsError: Insufficient number of B{C{points}}.
629
629
 
@@ -631,7 +631,7 @@ class LatLon(LatLonSphericalBase):
631
631
 
632
632
  @raise ValueError: Invalid B{C{radius}} or B{C{options}}.
633
633
 
634
- @see: Functions L{pygeodesy.compassAngle}, L{pygeodesy.equirectangular_}
634
+ @see: Functions L{pygeodesy.compassAngle}, L{pygeodesy.equirectangular4}
635
635
  and L{pygeodesy.nearestOn5}.
636
636
  '''
637
637
  return nearestOn3(self, points, closed=closed, radius=radius,
@@ -1222,7 +1222,7 @@ def nearestOn3(point, points, closed=False, radius=R_M, wrap=False, adjust=True,
1222
1222
  limit=9, **LatLon_and_kwds):
1223
1223
  '''Locate the point on a path or polygon closest to a reference point.
1224
1224
 
1225
- Distances are I{approximated} using function L{pygeodesy.equirectangular_},
1225
+ Distances are I{approximated} using function L{pygeodesy.equirectangular4},
1226
1226
  subject to the supplied B{C{options}}.
1227
1227
 
1228
1228
  @arg point: The reference point (L{LatLon}).
@@ -1231,19 +1231,19 @@ def nearestOn3(point, points, closed=False, radius=R_M, wrap=False, adjust=True,
1231
1231
  @kwarg radius: Mean earth radius (C{meter}).
1232
1232
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
1233
1233
  B{C{points}} (C{bool}).
1234
- @kwarg adjust: See function L{pygeodesy.equirectangular_} (C{bool}).
1235
- @kwarg limit: See function L{pygeodesy.equirectangular_} (C{degrees}),
1234
+ @kwarg adjust: See function L{pygeodesy.equirectangular4} (C{bool}).
1235
+ @kwarg limit: See function L{pygeodesy.equirectangular4} (C{degrees}),
1236
1236
  default C{9 degrees} is about C{1,000 Kmeter} (for mean
1237
1237
  spherical earth radius L{R_KM}).
1238
1238
  @kwarg LatLon: Optional class to return the closest point (L{LatLon})
1239
1239
  or C{None}.
1240
1240
  @kwarg options: Optional keyword arguments for function
1241
- L{pygeodesy.equirectangular_}.
1241
+ L{pygeodesy.equirectangular4}.
1242
1242
 
1243
1243
  @return: A L{NearestOn3Tuple}C{(closest, distance, angle)} with the
1244
1244
  C{closest} point as B{C{LatLon}} or L{LatLon3Tuple}C{(lat,
1245
1245
  lon, height)} if B{C{LatLon}} is C{None}. The C{distance}
1246
- is the L{pygeodesy.equirectangular_} distance between the
1246
+ is the L{pygeodesy.equirectangular4} distance between the
1247
1247
  C{closest} and the given B{C{point}} converted to C{meter},
1248
1248
  same units as B{C{radius}}. The C{angle} from the given
1249
1249
  B{C{point}} to the C{closest} is in compass C{degrees360},
@@ -1251,7 +1251,7 @@ def nearestOn3(point, points, closed=False, radius=R_M, wrap=False, adjust=True,
1251
1251
  the (interpolated) height at the C{closest} point.
1252
1252
 
1253
1253
  @raise LimitError: Lat- and/or longitudinal delta exceeds the B{C{limit}},
1254
- see function L{pygeodesy.equirectangular_}.
1254
+ see function L{pygeodesy.equirectangular4}.
1255
1255
 
1256
1256
  @raise PointsError: Insufficient number of B{C{points}}.
1257
1257
 
@@ -1259,7 +1259,7 @@ def nearestOn3(point, points, closed=False, radius=R_M, wrap=False, adjust=True,
1259
1259
 
1260
1260
  @raise ValueError: Invalid B{C{radius}}.
1261
1261
 
1262
- @see: Functions L{pygeodesy.equirectangular_} and L{pygeodesy.nearestOn5}.
1262
+ @see: Functions L{pygeodesy.equirectangular4} and L{pygeodesy.nearestOn5}.
1263
1263
  '''
1264
1264
  t = _nearestOn5(point, points, closed=closed, wrap=wrap,
1265
1265
  adjust=adjust, limit=limit)
pygeodesy/trf.py CHANGED
@@ -80,8 +80,8 @@ from pygeodesy.interns import MISSING, NN, _AT_, _COMMASPACE_, _conversion_, \
80
80
  _NAD83_, _no_, _PLUS_, _reframe_, _s_, _SPACE_, \
81
81
  _STAR_, _to_, _vs_, _WGS84_, _x_, _intern as _i
82
82
  # from pygeodesy.lazily import _ALL_LAZY # from .units
83
- from pygeodesy.named import ADict, classname, _lazyNamedEnumItem as _lazy, _Named, \
84
- _NamedEnum, _NamedEnumItem, _NamedTuple, Fmt, unstr
83
+ from pygeodesy.named import ADict, classname, _lazyNamedEnumItem as _lazy, _name2__, \
84
+ _Named, _NamedEnum, _NamedEnumItem, _NamedTuple, Fmt, unstr
85
85
  from pygeodesy.props import deprecated_method, property_doc_, Property_RO, property_RO
86
86
  # from pygeodesy.streprs import Fmt, unstr # from .named
87
87
  from pygeodesy.units import Epoch, Float, _ALL_LAZY
@@ -91,7 +91,7 @@ from math import ceil as _ceil, fabs
91
91
  # import operator as _operator # from .datums
92
92
 
93
93
  __all__ = _ALL_LAZY.trf
94
- __version__ = '24.05.21'
94
+ __version__ = '24.05.31'
95
95
 
96
96
  _EP0CH = Epoch(0, low=0)
97
97
  _Es = {_EP0CH: _EP0CH} # L{Epoch}s, deleted below
@@ -405,10 +405,11 @@ class TransformXform(Transform):
405
405
  n = name or (X.toStr() if X else NN)
406
406
  return Transform.rename(self, n)
407
407
 
408
- def toRefFrame(self, point, name=NN): # PYCHOK signature
408
+ def toRefFrame(self, point, **name): # PYCHOK signature
409
409
  '''Convert an ellipsoidal point using this transform and Xform.
410
410
 
411
411
  @arg point: The point to convert (C{Cartesian} or C{LatLon}).
412
+ @kwarg name: Optional C{B{name}=NN} (C{str}).
412
413
 
413
414
  @return: A copy of the B{C{point}}, converted I{directly} to
414
415
  this transform's Xform's C{refName2} and C{epoch}.
@@ -423,7 +424,7 @@ class TransformXform(Transform):
423
424
  if X: # see _toRefFrame below
424
425
  p._reframe = X.reframe2
425
426
  p._epoch = X.epoch
426
- p.rename(name or self.name)
427
+ p.rename(self._name__(name))
427
428
  return p
428
429
 
429
430
  def toTransform(self, epoch1, **epoch2_inverse):
@@ -1043,7 +1044,7 @@ def _sumstr(name1, name2, p_):
1043
1044
 
1044
1045
 
1045
1046
  def _toRefFrame(point, reframe2, reframe=None, epoch=None,
1046
- epoch2=None, name=NN, **LatLon_kwds):
1047
+ epoch2=None, **name_LatLon_kwds):
1047
1048
  '''(INTERNAL) Convert an ellipsoidal point to C{reframe2}
1048
1049
  and C{epoch2 or epoch or pont.epoch or reframe.epoch}.
1049
1050
  '''
@@ -1063,6 +1064,7 @@ def _toRefFrame(point, reframe2, reframe=None, epoch=None,
1063
1064
  _to_, _AT_(reframe2.name, e2))
1064
1065
  raise TRFError(_no_(_conversion_), txt=t)
1065
1066
 
1067
+ name, LatLon_kwds = _name2__(name_LatLon_kwds)
1066
1068
  if t0: # is not ()
1067
1069
  if t0.isunity:
1068
1070
  p = point.dup()
@@ -1078,7 +1080,7 @@ def _toRefFrame(point, reframe2, reframe=None, epoch=None,
1078
1080
  p = point.toTransform(t0)
1079
1081
  p._reframe = reframe2 # see TRFXform.toRefFrame above
1080
1082
  p._epoch = _xattr(t0.Xform, epoch=e2)
1081
- p.rename(name or reframe2.name)
1083
+ p.rename(reframe2._name__(name))
1082
1084
  else:
1083
1085
  p = point.dup(_reframe=reframe2, # ditto
1084
1086
  _epoch=e2, name=name) if name else point
pygeodesy/triaxials.py CHANGED
@@ -59,7 +59,7 @@ from pygeodesy.vector3d import _otherV3d, Vector3d, _ALL_LAZY, _MODS
59
59
  from math import atan2, fabs, sqrt
60
60
 
61
61
  __all__ = _ALL_LAZY.triaxials
62
- __version__ = '24.05.21'
62
+ __version__ = '24.05.28'
63
63
 
64
64
  _not_ordered_ = _not_('ordered')
65
65
  _omega_ = 'omega'
@@ -1158,7 +1158,7 @@ def _getitems(items, *indices):
1158
1158
  return type(items)(map(items.__getitem__, indices))
1159
1159
 
1160
1160
 
1161
- def _hartzell3(pov, los, Tun): # in .ellipsoids.hartzell4, .formy.hartzell
1161
+ def _hartzell3(pov, los, Tun): # in .Ellipsoid.hartzell4, .formy.hartzell
1162
1162
  '''(INTERNAL) Hartzell's "Satellite Line-of-Sight Intersection ...",
1163
1163
  formula from a Point-Of-View to an I{un-/ordered} Triaxial.
1164
1164
  '''
pygeodesy/ups.py CHANGED
@@ -26,14 +26,14 @@ from pygeodesy.constants import EPS, EPS0, _EPSmin as _Tol90, \
26
26
  isnear90, _0_0, _0_5, _1_0, _2_0
27
27
  from pygeodesy.datums import _ellipsoidal_datum, _WGS84
28
28
  from pygeodesy.dms import degDMS, _neg, parseDMS2
29
- from pygeodesy.errors import RangeError, _ValueError
29
+ from pygeodesy.errors import RangeError, _ValueError, _xkwds_pop2
30
30
  from pygeodesy.fmath import hypot, hypot1, sqrt0
31
31
  # from pygeodesy.internals import _under # from .named
32
32
  from pygeodesy.interns import NN, _COMMASPACE_, _inside_, _N_, \
33
33
  _pole_, _range_, _S_, _scale0_, \
34
34
  _SPACE_, _std_, _to_, _UTM_
35
35
  from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _getenv
36
- from pygeodesy.named import nameof, _xnamed, _under
36
+ from pygeodesy.named import nameof, _under
37
37
  from pygeodesy.namedTuples import EasNor2Tuple, UtmUps5Tuple, \
38
38
  UtmUps8Tuple, UtmUpsLatLon5Tuple
39
39
  from pygeodesy.props import deprecated_method, property_doc_, \
@@ -49,7 +49,7 @@ from pygeodesy.utmupsBase import Fmt, _LLEB, _hemi, _parseUTMUPS5, _to4lldn, \
49
49
  from math import atan2, fabs, radians, tan
50
50
 
51
51
  __all__ = _ALL_LAZY.ups
52
- __version__ = '25.05.13'
52
+ __version__ = '25.05.31'
53
53
 
54
54
  _BZ_UPS = _getenv('PYGEODESY_UPS_POLES', _std_) == _std_
55
55
  _Falsing = Meter(2000e3) # false easting and northing (C{meter})
@@ -57,18 +57,6 @@ _K0_UPS = Float(_K0_UPS= 0.994) # scale factor at central meridian
57
57
  _K1_UPS = Float(_K1_UPS=_1_0) # rescale point scale factor
58
58
 
59
59
 
60
- def _scale(E, rho, tau):
61
- # compute the point scale factor, ala Karney
62
- t = hypot1(tau)
63
- return Float(scale=(rho / E.a) * t * sqrt0(E.e21 + E.e2 / t**2))
64
-
65
-
66
- def _toBand(lat, lon): # see utm._toBand
67
- '''(INTERNAL) Get the I{polar} Band letter for a (lat, lon).
68
- '''
69
- return _Bands[(0 if lat < 0 else 2) + (0 if -180 < lon < 0 else 1)]
70
-
71
-
72
60
  class UPSError(_ValueError):
73
61
  '''Universal Polar Stereographic (UPS) parse or other L{Ups} issue.
74
62
  '''
@@ -88,7 +76,7 @@ class Ups(UtmUpsBase):
88
76
  def __init__(self, zone=0, pole=_N_, easting=_Falsing, # PYCHOK expected
89
77
  northing=_Falsing, band=NN, datum=_WGS84,
90
78
  falsed=True, gamma=None, scale=None,
91
- name=NN, **convergence):
79
+ **name_convergence):
92
80
  '''New L{Ups} UPS coordinate.
93
81
 
94
82
  @kwarg zone: UPS zone (C{int}, zero) or zone with/-out I{polar} Band
@@ -100,13 +88,13 @@ class Ups(UtmUpsBase):
100
88
  @kwarg band: Optional, I{polar} Band (C{str}, 'A'|'B'|'Y'|'Z').
101
89
  @kwarg datum: Optional, this coordinate's datum (L{Datum},
102
90
  L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}).
103
- @kwarg falsed: If C{True}, both B{C{easting}} and B{C{northing}}
104
- are falsed (C{bool}).
105
- @kwarg gamma: Optional, meridian convergence to save (C{degrees}).
106
- @kwarg scale: Optional, computed scale factor k to save
107
- (C{scalar}).
108
- @kwarg name: Optional name (C{str}).
109
- @kwarg convergence: DEPRECATED, use keyword argument C{B{gamma}=None}.
91
+ @kwarg falsed: If C{True}, both B{C{easting}} and B{C{northing}} are
92
+ falsed (C{bool}).
93
+ @kwarg gamma: Optional meridian convergence, bearing off grid North,
94
+ clockwise from true North to save (C{degrees}) or C{None}.
95
+ @kwarg scale: Optional grid scale factor to save (C{scalar}) or C{None}.
96
+ @kwarg name_convergence: Optional C{B{name}=NN} (C{str}) and DEPRECATED
97
+ keyword argument C{B{convergence}=None}, use B{C{gamma}}.
110
98
 
111
99
  @raise TypeError: Invalid B{C{datum}}.
112
100
 
@@ -114,18 +102,19 @@ class Ups(UtmUpsBase):
114
102
  B{C{northing}}, B{C{band}}, B{C{convergence}}
115
103
  or B{C{scale}}.
116
104
  '''
117
- if name:
118
- self.name = name
119
-
105
+ if name_convergence:
106
+ gamma, name = _xkwds_pop2(name_convergence, convergence=gamma)
107
+ if name:
108
+ self.name = name
120
109
  try:
121
- z, B, p = _to3zBhp(zone, band, hemipole=pole)
110
+ z, B, self._pole = _to3zBhp(zone, band, hemipole=pole)
122
111
  if z != _UPS_ZONE or (B and (B not in _Bands)):
123
112
  raise ValueError
124
113
  except (TypeError, ValueError) as x:
125
114
  raise UPSError(zone=zone, pole=pole, band=band, cause=x)
126
- self._pole = p
115
+
127
116
  UtmUpsBase.__init__(self, easting, northing, band=B, datum=datum, falsed=falsed,
128
- gamma=gamma, scale=scale, **convergence)
117
+ gamma=gamma, scale=scale)
129
118
 
130
119
  def __eq__(self, other):
131
120
  return isinstance(other, Ups) and other.zone == self.zone \
@@ -161,13 +150,11 @@ class Ups(UtmUpsBase):
161
150
  f = _Falsing if self.falsed else 0
162
151
  return EasNor2Tuple(f, f)
163
152
 
164
- def parse(self, strUPS, name=NN):
153
+ def parse(self, strUPS, **name):
165
154
  '''Parse a string to a similar L{Ups} instance.
166
155
 
167
- @arg strUPS: The UPS coordinate (C{str}),
168
- see function L{parseUPS5}.
169
- @kwarg name: Optional instance name (C{str}),
170
- overriding this name.
156
+ @arg strUPS: The UPS coordinate (C{str}), see function L{parseUPS5}.
157
+ @kwarg name: Optional C{B{name}=NN} (C{str}), overriding this name.
171
158
 
172
159
  @return: The similar instance (L{Ups}).
173
160
 
@@ -176,7 +163,7 @@ class Ups(UtmUpsBase):
176
163
  @see: Functions L{parseUTM5} and L{pygeodesy.parseUTMUPS5}.
177
164
  '''
178
165
  return parseUPS5(strUPS, datum=self.datum, Ups=self.classof,
179
- name=name or self.name)
166
+ name=self._name__(name))
180
167
 
181
168
  @deprecated_method
182
169
  def parseUPS(self, strUPS): # PYCHOK no cover
@@ -250,9 +237,8 @@ class Ups(UtmUpsBase):
250
237
  b, g, a = atan2(x, y), -1, _neg(a)
251
238
  ll = _LLEB(a, degrees180(b), datum=self._datum, name=self.name)
252
239
 
253
- ll._gamma = b * g
254
- ll._scale = _scale(E, r, t) if r > 0 else self.scale0
255
- self._latlon5args(ll, _toBand, unfalse)
240
+ k = _scale(E, r, t) if r > 0 else self.scale0
241
+ self._latlon5args(ll, g * b, k, _toBand, unfalse)
256
242
 
257
243
  def toRepr(self, prec=0, fmt=Fmt.SQUARE, sep=_COMMASPACE_, B=False, cs=False, **unused): # PYCHOK expected
258
244
  '''Return a string representation of this UPS coordinate.
@@ -353,7 +339,7 @@ class _Ups_K1(Ups):
353
339
  _scale0 = _K1_UPS
354
340
 
355
341
 
356
- def parseUPS5(strUPS, datum=_WGS84, Ups=Ups, falsed=True, name=NN):
342
+ def parseUPS5(strUPS, datum=_WGS84, Ups=Ups, falsed=True, **name):
357
343
  '''Parse a string representing a UPS coordinate, consisting of
358
344
  C{"[zone][band] pole easting northing"} where B{C{zone}} is
359
345
  pseudo zone C{"00"|"0"|""} and C{band} is C{'A'|'B'|'Y'|'Z'|''}.
@@ -362,8 +348,9 @@ def parseUPS5(strUPS, datum=_WGS84, Ups=Ups, falsed=True, name=NN):
362
348
  @kwarg datum: Optional datum to use (L{Datum}).
363
349
  @kwarg Ups: Optional class to return the UPS coordinate (L{Ups})
364
350
  or C{None}.
365
- @kwarg falsed: Both B{C{easting}} and B{C{northing}} are falsed (C{bool}).
366
- @kwarg name: Optional B{C{Ups}} name (C{str}).
351
+ @kwarg falsed: If C{True}, both B{C{easting}} and B{C{northing}}
352
+ are falsed (C{bool}).
353
+ @kwarg name: Optional B{C{Ups}} C{B{name}=NN} (C{str}).
367
354
 
368
355
  @return: The UPS coordinate (B{C{Ups}}) or a
369
356
  L{UtmUps5Tuple}C{(zone, hemipole, easting, northing,
@@ -376,43 +363,54 @@ def parseUPS5(strUPS, datum=_WGS84, Ups=Ups, falsed=True, name=NN):
376
363
  if z != _UPS_ZONE or (B and B not in _Bands):
377
364
  raise UPSError(strUPS=strUPS, zone=z, band=B)
378
365
 
379
- r = UtmUps5Tuple(z, p, e, n, B, Error=UPSError) if Ups is None \
380
- else Ups(z, p, e, n, band=B, falsed=falsed, datum=datum)
381
- return _xnamed(r, name)
366
+ r = UtmUps5Tuple(z, p, e, n, B, Error=UPSError, **name) if Ups is None \
367
+ else Ups(z, p, e, n, band=B, falsed=falsed, datum=datum, **name)
368
+ return r
369
+
370
+
371
+ def _scale(E, rho, tau):
372
+ # compute the point scale factor, ala Karney
373
+ t = hypot1(tau)
374
+ return Float(scale=(rho / E.a) * t * sqrt0(E.e21 + E.e2 / t**2))
375
+
376
+
377
+ def _toBand(lat, lon): # see utm._toBand
378
+ '''(INTERNAL) Get the I{polar} Band letter for a (lat, lon).
379
+ '''
380
+ return _Bands[(0 if lat < 0 else 2) + (0 if -180 < lon < 0 else 1)]
382
381
 
383
382
 
384
383
  def toUps8(latlon, lon=None, datum=None, Ups=Ups, pole=NN,
385
- falsed=True, strict=True, name=NN):
384
+ falsed=True, strict=True, **name):
386
385
  '''Convert a lat-/longitude point to a UPS coordinate.
387
386
 
388
- @arg latlon: Latitude (C{degrees}) or an (ellipsoidal)
389
- geodetic C{LatLon} point.
387
+ @arg latlon: Latitude (C{degrees}) or an (ellipsoidal) geodetic
388
+ C{LatLon} point.
390
389
  @kwarg lon: Optional longitude (C{degrees}) or C{None} if
391
390
  B{C{latlon}} is a C{LatLon}.
392
- @kwarg datum: Optional datum for this UPS coordinate,
393
- overriding B{C{latlon}}'s datum (C{Datum},
394
- L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}).
395
- @kwarg Ups: Optional class to return the UPS coordinate
396
- (L{Ups}) or C{None}.
391
+ @kwarg datum: Optional datum for this UPS coordinate, overriding
392
+ B{C{latlon}}'s datum (C{Datum}, L{Ellipsoid},
393
+ L{Ellipsoid2} or L{a_f2Tuple}).
394
+ @kwarg Ups: Optional class to return the UPS coordinate (L{Ups})
395
+ or C{None}.
397
396
  @kwarg pole: Optional top/center of (stereographic) projection
398
397
  (C{str}, C{'N[orth]'} or C{'S[outh]'}).
399
- @kwarg falsed: False both easting and northing (C{bool}).
398
+ @kwarg falsed: If C{True}, false both easting and northing (C{bool}).
400
399
  @kwarg strict: Restrict B{C{lat}} to UPS ranges (C{bool}).
401
- @kwarg name: Optional B{C{Ups}} name (C{str}).
400
+ @kwarg name: Optional B{C{Ups}} C{B{name}=NN} (C{str}).
402
401
 
403
- @return: The UPS coordinate (B{C{Ups}}) or a
404
- L{UtmUps8Tuple}C{(zone, hemipole, easting, northing,
405
- band, datum, gamma, scale)} if B{C{Ups}} is C{None}.
406
- The C{hemipole} is the C{'N'|'S'} pole, the UPS
407
- projection top/center.
402
+ @return: The UPS coordinate (B{C{Ups}}) or a L{UtmUps8Tuple}C{(zone,
403
+ hemipole, easting, northing, band, datum, gamma, scale)} if
404
+ B{C{Ups}} is C{None}. The C{hemipole} is the C{'N'|'S'}
405
+ pole, the UPS projection top/center.
408
406
 
409
407
  @raise RangeError: If B{C{strict}} and B{C{lat}} outside the valid
410
408
  UPS bands or if B{C{lat}} or B{C{lon}} outside
411
409
  the valid range and L{pygeodesy.rangerrors} set
412
410
  to C{True}.
413
411
 
414
- @raise TypeError: If B{C{latlon}} is not ellipsoidal or
415
- B{C{datum}} invalid.
412
+ @raise TypeError: If B{C{latlon}} is not ellipsoidal or if B{C{datum}}
413
+ is invalid.
416
414
 
417
415
  @raise ValueError: If B{C{lon}} value is missing or if B{C{latlon}}
418
416
  is invalid.
@@ -463,9 +461,7 @@ def toUps8(latlon, lon=None, datum=None, Ups=Ups, pole=NN,
463
461
  r = Ups(z, p, x, y, band=B, datum=d, falsed=falsed,
464
462
  gamma=g, scale=k, name=n)
465
463
  if isinstance(latlon, _LLEB) and d is latlon.datum: # see utm._toXtm8
466
- r._latlon5args(latlon, _toBand, falsed) # XXX weakref(latlon)?
467
- latlon._gamma = g
468
- latlon._scale = k
464
+ r._latlon5args(latlon, g, k, _toBand, falsed) # XXX weakref(latlon)?
469
465
  else:
470
466
  r._hemisphere = _hemi(lat)
471
467
  if not r._band:
@@ -473,18 +469,18 @@ def toUps8(latlon, lon=None, datum=None, Ups=Ups, pole=NN,
473
469
  return r
474
470
 
475
471
 
476
- def upsZoneBand5(lat, lon, strict=True, name=NN):
472
+ def upsZoneBand5(lat, lon, strict=True, **name):
477
473
  '''Return the UTM/UPS zone number, I{polar} Band letter, pole and
478
474
  clipped lat- and longitude for a given location.
479
475
 
480
476
  @arg lat: Latitude in degrees (C{scalar} or C{str}).
481
477
  @arg lon: Longitude in degrees (C{scalar} or C{str}).
482
478
  @kwarg strict: Restrict B{C{lat}} to UPS ranges (C{bool}).
483
- @kwarg name: Optional name (C{str}).
479
+ @kwarg name: Optional B{C{Ups}} C{B{name}=NN} (C{str}).
484
480
 
485
- @return: A L{UtmUpsLatLon5Tuple}C{(zone, band, hemipole,
486
- lat, lon)} where C{hemipole} is the C{'N'|'S'} pole,
487
- the UPS projection top/center and C{lon} [-180..180).
481
+ @return: A L{UtmUpsLatLon5Tuple}C{(zone, band, hemipole, lat,
482
+ lon)} where C{hemipole} is the C{'N'|'S'} pole, the
483
+ UPS projection top/center and C{lon} [-180..180).
488
484
 
489
485
  @note: The C{lon} is set to C{0} if B{C{lat}} is C{-90} or
490
486
  C{90}, see env variable C{PYGEODESY_UPS_POLES} in
@@ -514,7 +510,7 @@ def upsZoneBand5(lat, lon, strict=True, name=NN):
514
510
 
515
511
  else:
516
512
  B, p = NN, _hemi(lat)
517
- return UtmUpsLatLon5Tuple(z, B, p, lat, lon, Error=UPSError, name=name)
513
+ return UtmUpsLatLon5Tuple(z, B, p, lat, lon, Error=UPSError, **name)
518
514
 
519
515
  # **) MIT License
520
516
  #
pygeodesy/utily.py CHANGED
@@ -17,7 +17,7 @@ from pygeodesy.constants import EPS, EPS0, INF, NAN, PI, PI2, PI_2, R_M, \
17
17
  _N_180_0, _360_0, _400_0, _copysign_0_0, \
18
18
  _float as _F, _isfinite, isnan, isnear0, \
19
19
  _over, _umod_360, _umod_PI2
20
- from pygeodesy.errors import _ValueError, _xkwds, _xkwds_get, _ALL_LAZY, _MODS
20
+ from pygeodesy.errors import _ValueError, _xkwds, _xkwds_get1, _ALL_LAZY, _MODS
21
21
  from pygeodesy.internals import _passargs # , _MODS?
22
22
  from pygeodesy.interns import _edge_, _radians_, _semi_circular_, _SPACE_
23
23
  # from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .errors
@@ -27,7 +27,7 @@ from pygeodesy.units import Degrees, Degrees_, Feet, Float, Lam, Lam_, \
27
27
  from math import acos, asin, atan2, cos, degrees, fabs, radians, sin, tan # pow
28
28
 
29
29
  __all__ = _ALL_LAZY.utily
30
- __version__ = '24.05.14'
30
+ __version__ = '24.05.29'
31
31
 
32
32
  # read constant name "_M_Unit" as "meter per Unit"
33
33
  _M_CHAIN = _F( 20.1168) # yard2m(1) * 22
@@ -763,7 +763,7 @@ def sincos2d(deg, **adeg):
763
763
  q -= 1
764
764
  d = deg - q * _90_0
765
765
  if adeg:
766
- t = _xkwds_get(adeg, adeg=_0_0)
766
+ t = _xkwds_get1(adeg, adeg=_0_0)
767
767
  d = _MODS.karney._around(d + t)
768
768
  t = _sin0cos2(q & 3, radians(d), deg)
769
769
  else: