pygeodesy 24.5.24__py2.py3-none-any.whl → 24.6.9__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.9.dist-info}/METADATA +6 -5
  2. PyGeodesy-24.6.9.dist-info/RECORD +116 -0
  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 +54 -67
  9. pygeodesy/cartesianBase.py +138 -147
  10. pygeodesy/constants.py +3 -3
  11. pygeodesy/deprecated/functions.py +9 -3
  12. pygeodesy/ecef.py +67 -72
  13. pygeodesy/ellipsoidalBase.py +18 -56
  14. pygeodesy/ellipsoidalGeodSolve.py +2 -2
  15. pygeodesy/ellipsoidalKarney.py +3 -3
  16. pygeodesy/ellipsoidalNvector.py +7 -7
  17. pygeodesy/ellipsoids.py +6 -5
  18. pygeodesy/errors.py +20 -10
  19. pygeodesy/etm.py +16 -21
  20. pygeodesy/fmath.py +9 -20
  21. pygeodesy/formy.py +60 -74
  22. pygeodesy/frechet.py +13 -14
  23. pygeodesy/fsums.py +60 -26
  24. pygeodesy/geodesicx/__init__.py +1 -1
  25. pygeodesy/geodesicx/__main__.py +2 -2
  26. pygeodesy/geodesicx/gx.py +3 -5
  27. pygeodesy/geodsolve.py +24 -26
  28. pygeodesy/geohash.py +27 -40
  29. pygeodesy/geoids.py +1 -1
  30. pygeodesy/hausdorff.py +17 -18
  31. pygeodesy/heights.py +17 -30
  32. pygeodesy/internals.py +15 -14
  33. pygeodesy/interns.py +3 -9
  34. pygeodesy/iters.py +2 -2
  35. pygeodesy/karney.py +8 -7
  36. pygeodesy/latlonBase.py +189 -176
  37. pygeodesy/lazily.py +92 -56
  38. pygeodesy/lcc.py +2 -2
  39. pygeodesy/ltp.py +93 -55
  40. pygeodesy/ltpTuples.py +304 -240
  41. pygeodesy/mgrs.py +51 -24
  42. pygeodesy/named.py +159 -136
  43. pygeodesy/namedTuples.py +43 -14
  44. pygeodesy/nvectorBase.py +20 -23
  45. pygeodesy/osgr.py +40 -48
  46. pygeodesy/points.py +11 -11
  47. pygeodesy/props.py +29 -16
  48. pygeodesy/rhumb/aux_.py +13 -15
  49. pygeodesy/rhumb/bases.py +12 -5
  50. pygeodesy/rhumb/ekx.py +24 -18
  51. pygeodesy/rhumb/solve.py +20 -70
  52. pygeodesy/simplify.py +16 -16
  53. pygeodesy/solveBase.py +35 -32
  54. pygeodesy/sphericalBase.py +33 -31
  55. pygeodesy/sphericalTrigonometry.py +17 -17
  56. pygeodesy/streprs.py +6 -4
  57. pygeodesy/trf.py +11 -9
  58. pygeodesy/triaxials.py +71 -50
  59. pygeodesy/units.py +40 -65
  60. pygeodesy/unitsBase.py +2 -2
  61. pygeodesy/ups.py +66 -70
  62. pygeodesy/utily.py +7 -6
  63. pygeodesy/utm.py +152 -156
  64. pygeodesy/utmups.py +38 -38
  65. pygeodesy/utmupsBase.py +102 -106
  66. pygeodesy/vector3d.py +34 -36
  67. pygeodesy/vector3dBase.py +12 -9
  68. pygeodesy/webmercator.py +43 -51
  69. PyGeodesy-24.5.24.dist-info/RECORD +0 -116
  70. {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.9.dist-info}/WHEEL +0 -0
  71. {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.9.dist-info}/top_level.txt +0 -0
pygeodesy/lazily.py CHANGED
@@ -29,39 +29,33 @@ and line number.
29
29
 
30
30
  from pygeodesy import internals as _internals, interns as _interns, \
31
31
  _isfrozen # DON'T _lazy_import2
32
- # from pygeodesy.errors import _error_init # _ALL_MODS
32
+ # from pygeodesy.errors import _error_init, _xkwds_item2 # _ALL_MODS
33
33
  from pygeodesy.internals import _caller3, _dunder_nameof, _dunder_ismain, \
34
34
  _headof, _osversion2, printf, _Pythonarchine, \
35
- _tailof
36
- from pygeodesy.interns import NN, _areaOf_, _attribute_, _by_, _COLONSPACE_, \
37
- _COMMASPACE_, _doesn_t_exist_, _DOT_, _enabled_, \
38
- _EQUALSPACED_, _from_, _HASH_, _immutable_, \
39
- _isclockwise_, _ispolar_, _line_, _module_, \
40
- _no_, _NorthPole_, _not_, _or_, _pygeodesy_, \
41
- _pygeodesy_abspath_, _SouthPole_, \
42
- _SPACE_, _sub_packages, _sys, _UNDER_, _version_, \
35
+ _tailof # _Property_RO
36
+ from pygeodesy.interns import NN, _attribute_, _by_, _COLONSPACE_, _COMMASPACE_, \
37
+ _doesn_t_exist_, _DOT_, _EQUALSPACED_, _from_, \
38
+ _HASH_, _immutable_, _line_, _module_, _no_, _not_, \
39
+ _or_, _pygeodesy_abspath_, _pygeodesy_, _SPACE_, \
40
+ _SUB_PACKAGES, _UNDER_, _version_, _sys, \
43
41
  _intern # function
44
42
  # from pygeodesy.streprs import unstr # _ALL_MODS
45
43
 
46
- from os import getenv as _getenv
47
44
  try:
48
45
  from importlib import import_module
49
46
  except ImportError as x: # Python 2.6-
50
- _str_x = str(x)
51
-
52
- def import_module(name, *package):
53
- t = _ALL_MODS.streprs.unstr(import_module, name, *package)
54
- raise LazyImportError(t, txt=_str_x)
47
+ raise ImportError(_COLONSPACE_(_Pythonarchine(sep=_SPACE_), x))
48
+ from os import getenv as _getenv
49
+ # import sys as _sys # from .interns
55
50
 
56
51
  __as__ = ' as '
57
52
  _dunder_all_ = '__all__' # in .__main__
58
- _dunder_package_ = '__package__'
53
+ _enabled_ = 'enabled'
59
54
  _FOR_DOCS = _getenv('PYGEODESY_FOR_DOCS', NN) # for epydoc ...
60
- _from_DOT__ = _SPACE_(NN, _from_, _DOT_)
61
55
  _i0 = () # PYCHOK empty tuple
62
56
  _init__all__ = _FOR_DOCS or _getenv('PYGEODESY_INIT__ALL__', _dunder_all_) == _dunder_all_ # PYCHOK exported
63
57
  _lazily_ = 'lazily'
64
- _lazily_imported__ = _SPACE_(_HASH_, _lazily_, 'imported', NN)
58
+ _lazily_imported_ = _SPACE_(_HASH_, _lazily_, 'imported')
65
59
  _PYGEODESY_GEOCONVERT_ = 'PYGEODESY_GEOCONVERT' # PYCHOK .mgrs, test.bases
66
60
  _PYGEODESY_GEODSOLVE_ = 'PYGEODESY_GEODSOLVE' # PYCHOK .geodsolve, test.bases
67
61
  _PYGEODESY_LAZY_IMPORT_ = 'PYGEODESY_LAZY_IMPORT'
@@ -73,7 +67,7 @@ _unlazy = _unLazy0 = _isfrozen or _sys_version_info2 < (3, 7) # PYCHOK mod
73
67
  _WARNINGS_X_DEV = _getenv('PYGEODESY_WARNINGS', NN) and (
74
68
  _PYTHON_X_DEV or bool(_sys.warnoptions)) # PYCHOK .props
75
69
  # @module_property[_RO?] <https://GitHub.com/jtushman/proxy_tools/>
76
- isLazy = None # see @var isLazy in .__init__
70
+ isLazy = None # see @var isLazy in .__init__
77
71
 
78
72
 
79
73
  class LazyAttributeError(AttributeError):
@@ -168,7 +162,7 @@ class _NamedEnum_RO(dict):
168
162
  for a in t:
169
163
  a, _, as_ = a.partition(__as__)
170
164
  if as_: # import attr as attr_
171
- _a(as_, _DOT_(m, a, NN), *_sub_packages)
165
+ _a(as_, _DOT_(m, a, NN), *_SUB_PACKAGES)
172
166
  else:
173
167
  _a(a, m)
174
168
  return _D
@@ -185,7 +179,7 @@ def _ALL_ATTRS(*attrs):
185
179
  '''
186
180
  t = ()
187
181
  for attr in attrs:
188
- t += tuple(map(_attrof, attr))
182
+ t += tuple(map(_getattrof, attr))
189
183
  return t
190
184
 
191
185
 
@@ -269,7 +263,7 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
269
263
  'antipode', 'antipode_', 'bearing', 'bearing_',
270
264
  'compassAngle', 'cosineForsytheAndoyerLambert', 'cosineForsytheAndoyerLambert_',
271
265
  'cosineAndoyerLambert', 'cosineAndoyerLambert_', 'cosineLaw', 'cosineLaw_',
272
- 'equirectangular', 'equirectangular_', 'euclidean', 'euclidean_',
266
+ 'equirectangular', 'equirectangular4', 'euclidean', 'euclidean_',
273
267
  'excessAbc_', 'excessCagnoli_', 'excessGirard_', 'excessLHuilier_',
274
268
  'excessKarney', 'excessKarney_', 'excessQuad', 'excessQuad_',
275
269
  'flatLocal', 'flatLocal_', 'flatPolar', 'flatPolar_',
@@ -290,7 +284,7 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
290
284
  'fsum', 'fsum_', 'fsumf_', 'fsum1', 'fsum1_', 'fsum1f_'),
291
285
  gars=_i('Garef', 'GARSError'),
292
286
  geodesicw=_i('Geodesic', 'GeodesicLine', 'Geodesic_WGS84'),
293
- geodesicx=_i('gx', 'gxarea', 'gxbases', 'gxline', # modules, see _sub_packages
287
+ geodesicx=_i('gx', 'gxarea', 'gxbases', 'gxline', # modules
294
288
  'GeodesicAreaExact', 'GeodesicExact', 'GeodesicLineExact', 'PolygonArea'),
295
289
  geodsolve=_i('GeodesicSolve', 'GeodesicLineSolve', 'GeodSolve12Tuple'),
296
290
  geohash=_i('Geohash', 'GeohashError', 'Neighbors8Dict', 'Resolutions2Tuple'),
@@ -340,11 +334,11 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
340
334
  'Reverse4Tuple', 'Triangle7Tuple', 'Triangle8Tuple', 'Trilaterate5Tuple',
341
335
  'UtmUps2Tuple', 'UtmUps5Tuple', 'UtmUps8Tuple', 'UtmUpsLatLon5Tuple',
342
336
  'Vector2Tuple', 'Vector3Tuple', 'Vector4Tuple'),
343
- nvectorBase=_i(_NorthPole_, _SouthPole_),
337
+ nvectorBase=_i('NorthPole', 'SouthPole'),
344
338
  osgr=_i('Osgr', 'OSGRError', 'parseOSGR', 'toOsgr'),
345
339
  points=_i('LatLon_', 'LatLon2psxy', 'Numpy2LatLon', 'Shape2Tuple', 'Tuple2LatLon',
346
- _areaOf_, 'boundsOf', 'centroidOf', 'fractional',
347
- _isclockwise_, 'isconvex', 'isconvex_', 'isenclosedBy', _ispolar_,
340
+ 'areaOf', 'boundsOf', 'centroidOf', 'fractional',
341
+ 'isclockwise', 'isconvex', 'isconvex_', 'isenclosedBy', 'ispolar',
348
342
  'luneOf', 'nearestOn5', 'perimeterOf', 'quadOf'),
349
343
  props=_i('Property', 'Property_RO', 'property_RO', 'property_doc_',
350
344
  'deprecated_class', 'deprecated_function', 'deprecated_method',
@@ -421,7 +415,7 @@ _ALL_DEPRECATED = _NamedEnum_RO(_name='_ALL_DEPRECATED',
421
415
  'R_M', 'R_MA', 'R_MB', 'R_KM', 'R_NM', 'R_SM', 'R_FM', 'R_VM'),
422
416
  deprecated_functions=_i('anStr', 'areaof', 'atand', 'bounds', # most of the DEPRECATED functions, except ...
423
417
  'clipCS3', 'clipDMS', 'clipStr', 'collins', 'copysign', # ... ellipsoidal, spherical flavors
424
- 'decodeEPSG2', 'encodeEPSG', 'enStr2', 'equirectangular3',
418
+ 'decodeEPSG2', 'encodeEPSG', 'enStr2', 'equirectangular_', 'equirectangular3',
425
419
  'excessAbc', 'excessGirard', 'excessLHuilier',
426
420
  'false2f', 'falsed2f', 'float0', 'fStr', 'fStrzs', 'hypot3',
427
421
  'inStr', 'isenclosedby', 'istuplist',
@@ -432,7 +426,7 @@ _ALL_DEPRECATED = _NamedEnum_RO(_name='_ALL_DEPRECATED',
432
426
  deprecated_nvector=_i('LatLonNvectorBase', 'Nvector', 'sumOf', 'NorthPole', 'SouthPole'),)
433
427
 
434
428
 
435
- class _ALL_MODS(_internals._ALL_MODS_Base):
429
+ class _ALL_MODS(_internals._MODS_Base):
436
430
  '''(INTERNAL) Memoized import of any L{pygeodesy} module.
437
431
  '''
438
432
  def __getattr__(self, name):
@@ -474,7 +468,7 @@ class _ALL_MODS(_internals._ALL_MODS_Base):
474
468
  return v
475
469
 
476
470
  def getmodule(self, name, parent=_pygeodesy_):
477
- '''Get a C{pygeodesy} module.
471
+ '''Get a C{pygeodesy} module or the C{__main__}.
478
472
 
479
473
  @arg name: Un/qualified module name (C{str}).
480
474
 
@@ -482,12 +476,36 @@ class _ALL_MODS(_internals._ALL_MODS_Base):
482
476
 
483
477
  @raise ImportError: Importing module B{C{name}} failed.
484
478
  '''
485
- if _headof(name) != parent:
479
+ if _headof(name) != parent and not _dunder_ismain(name):
486
480
  name = _DOT_(parent, name)
487
481
  try:
488
482
  return _sys.modules[name]
489
483
  except KeyError:
490
- return import_module(name, parent)
484
+ return _getmodule(name, parent)
485
+
486
+ def into(self, **mod_dunder_name_):
487
+ '''Lazily import module C{mod} into module C{_dunder_name_}
488
+ and set C{_dunder_name_._mod} to module C{mod}, I{once}.
489
+ '''
490
+ class _Into(object):
491
+
492
+ def __getattr__(unused, name):
493
+ mod, dun = self.errors._xkwds_item2(mod_dunder_name_)
494
+ _mod = _UNDER_(NN, mod)
495
+ d = self.getmodule(dun) # '__main__' OK
496
+ i = _getattribute(d, _mod, dun)
497
+ assert isinstance(i, _Into)
498
+ m = self.getmodule(mod)
499
+ setattr(d, _mod, m) # overwrite C{d._mod}
500
+ return getattr(m, name)
501
+
502
+ return _Into()
503
+
504
+ # @_Property_RO
505
+ # def _isBoolean(self):
506
+ # '''(INTERNAL) Get function C(.booleans.isBoolean}, I{once}.
507
+ # '''
508
+ # return self.booleans.isBoolean
491
509
 
492
510
  def items(self): # no module named 'items'
493
511
  '''Yield the modules imported so far.
@@ -500,7 +518,7 @@ class _ALL_MODS(_internals._ALL_MODS_Base):
500
518
  _internals._MODS = _ALL_MODS = _ALL_MODS() # PYCHOK singleton
501
519
 
502
520
  __all__ = _ALL_LAZY.lazily
503
- __version__ = '24.05.15'
521
+ __version__ = '24.06.05'
504
522
 
505
523
 
506
524
  def _ALL_OTHER(*objs):
@@ -565,11 +583,34 @@ def _all_missing2(_all_):
565
583
  (_DOT_(_pygeodesy_, _dunder_all_), _diff(_alzy.keys(), _all_)))
566
584
 
567
585
 
568
- def _attrof(attr_as): # .testDeprecated
586
+ def _getattribute(m, name, mod=_pygeodesy_):
587
+ '''(INTERNAL) Get attr C{m.name}.
588
+ '''
589
+ try:
590
+ return getattr(m, name)
591
+ except AttributeError:
592
+ name = _DOT_(mod, name)
593
+ # <https://GitHub.com/mrJean1/PyGeodesy/issues/76>
594
+ raise LazyAttributeError(_no_(_attribute_), txt=name)
595
+
596
+
597
+ def _getattrof(attr_as): # .testDeprecated
598
+ '''(INTERNAL) Get the C{"as name"} or C{"name"} of a lazy entry.
599
+ '''
569
600
  a_, _, as_ = attr_as.partition(__as__)
570
601
  return as_ or a_.rstrip(_DOT_)
571
602
 
572
603
 
604
+ def _getmodule(name, *parent):
605
+ '''(INTERNAL) Wrapper for C{import_module}.
606
+ '''
607
+ try:
608
+ return import_module(name, parent)
609
+ except ImportError:
610
+ # <https://GitHub.com/mrJean1/PyGeodesy/issues/76>
611
+ raise LazyImportError(_no_(_module_), txt=name)
612
+
613
+
573
614
  # def _lazy_attributes(_dunder_name_):
574
615
  # '''(INTERNAL) Return a function to C{B{__name__}.__getattr__(attr)}
575
616
  # on lazily imported modules and sub-modules.
@@ -615,17 +656,19 @@ def _lazy_import2(pack): # MCCABE 14
615
656
  U{PEP 562<https://www.Python.org/dev/peps/pep-0562>} and the
616
657
  U{new way<https://Snarky.Ca/lazy-importing-in-python-3-7/>}.
617
658
  '''
659
+ _DOT_ = _interns._DOT_
660
+ _SPACE_ = _interns._SPACE_
661
+
618
662
  if pack != _pygeodesy_ or _unlazy: # Python 3.7+
619
663
  t = _no_(_DOT_(pack, _dunder_nameof(_lazy_import2))) # PYCHOK no cover
620
664
  raise LazyImportError(t, txt=_Pythonarchine(sep=_SPACE_))
621
665
 
622
- package, parent = _lazy_init2(pack) # _pygeodesy_
623
-
624
- subpacks = set((parent, NN) + tuple(
625
- _DOT_(parent, s) for s in _sub_packages))
626
- MISSING = object() # DON'T interns.MISSING!
627
- imports = _all_imports()
628
- deprecates = _all_deprecates()
666
+ package, parent = _lazy_init2(pack) # _pygeodesy_
667
+ sub_packages = set((parent, NN) + tuple(
668
+ _DOT_(parent, s) for s in _SUB_PACKAGES))
669
+ imports = _all_imports()
670
+ deprecates = _all_deprecates()
671
+ _dunder_package_ = '__package__'
629
672
 
630
673
  def __getattr__(name): # __getattr__ only for Python 3.7+
631
674
  # only called once for each undefined pygeodesy attribute
@@ -638,21 +681,12 @@ def _lazy_import2(pack): # MCCABE 14
638
681
  mod, _, attr = mod[:-1].rpartition(_DOT_)
639
682
  else: # from mod import name
640
683
  attr = name
641
- try:
642
- t = _DOT_(pack, mod)
643
- v = import_module(t, parent)
644
- except ImportError:
645
- # <https://GitHub.com/mrJean1/PyGeodesy/issues/76>
646
- raise LazyImportError(_no_(_module_), txt=t)
647
- t = getattr(v, _dunder_package_, None)
648
- if t not in subpacks: # invalid module package
684
+ v = _getmodule(_DOT_(pack, mod), parent)
685
+ t = getattr(v, _dunder_package_, None)
686
+ if t not in sub_packages: # invalid module package
649
687
  raise LazyImportError(_DOT_(mod, _dunder_package_), t)
650
- if attr: # get the attribute
651
- v = getattr(v, attr, MISSING)
652
- if v is MISSING: # PYCHOK no cover
653
- t = _DOT_(mod, attr)
654
- # <https://GitHub.com/mrJean1/PyGeodesy/issues/76>
655
- raise LazyAttributeError(_no_(_attribute_), txt=t)
688
+ if attr: # get mod.attr
689
+ v = _getattribute(v, attr, mod)
656
690
 
657
691
  elif name in (_dunder_all_,): # XXX _dunder_dir_, _dunder_members_?
658
692
  v = _ALL_INIT + tuple(imports.keys())
@@ -663,9 +697,9 @@ def _lazy_import2(pack): # MCCABE 14
663
697
 
664
698
  setattr(package, name, v) # package.__dict__[name] = val
665
699
  if isLazy > 1:
666
- t = NN(_lazily_imported__, _DOT_(parent, name))
700
+ t = _SPACE_(_lazily_imported_, _DOT_(parent, name))
667
701
  if mod and _tailof(mod) != name:
668
- t = NN(t, _from_DOT__, mod)
702
+ t = _SPACE_(t, _from_, _DOT_(NN, mod))
669
703
  if isLazy > 2:
670
704
  try: # see C{_caller3}
671
705
  _, f, s = _caller3(2)
@@ -827,6 +861,8 @@ def _lazy_module(name): # overwritten by _lazy_import2
827
861
 
828
862
  # del _i, _i0
829
863
 
864
+ # _ = _ALL_MODS.errors # force import pygeodesy.errors
865
+
830
866
  if _dunder_ismain(__name__): # PYCHOK no cover
831
867
 
832
868
  from timeit import timeit
pygeodesy/lcc.py CHANGED
@@ -48,7 +48,7 @@ from pygeodesy.utily import atan1, degrees90, degrees180, sincos2, tanPI_2_2
48
48
  from math import atan, fabs, log, radians, sin, sqrt
49
49
 
50
50
  __all__ = _ALL_LAZY.lcc
51
- __version__ = '24.05.24'
51
+ __version__ = '24.06.09'
52
52
 
53
53
  _E0_ = 'E0'
54
54
  _N0_ = 'N0'
@@ -454,7 +454,7 @@ class Lcc(_NamedBase):
454
454
  #
455
455
  # kwds = _xkwds(e_n_h_conic, e=self.easting, n=self.northing,
456
456
  # h=self.height, conic=self.conic,
457
- # name=name or self.name)
457
+ # name=self._name__(name))
458
458
  # args, kwds = _args_kwds(**kwds)
459
459
  # return self.__class__(*args, **kwds) # .classof
460
460
 
pygeodesy/ltp.py CHANGED
@@ -13,23 +13,25 @@ and L{ChLVe} and L{Ltp}, L{ChLV}, L{LocalError}, L{Attitude} and L{Frustum}.
13
13
  # make sure int/int division yields float quotient, see .basics
14
14
  from __future__ import division as _; del _ # PYCHOK semicolon
15
15
 
16
- from pygeodesy.basics import _args_kwds_names, issubclassof, map1, map2 # .datums
16
+ from pygeodesy.basics import _args_kwds_names, map1, map2, _xinstanceof, \
17
+ _xsubclassof # .datums
17
18
  from pygeodesy.constants import EPS, INT0, _umod_360, _0_0, _0_01, _0_5, _1_0, \
18
19
  _2_0, _60_0, _90_0, _100_0, _180_0, _3600_0, \
19
20
  _N_1_0 # PYCHOK used!
20
- from pygeodesy.datums import _WGS84, _xinstanceof
21
- from pygeodesy.ecef import _EcefBase, EcefKarney, _llhn4, _xyzn4
22
- from pygeodesy.errors import _NotImplementedError, _TypesError, _ValueError, \
23
- _xattr, _xkwds, _xkwds_get, _xkwds_pop2
21
+ # from pygeodesy.datums import _WGS84 # from .ecef
22
+ from pygeodesy.ecef import _EcefBase, EcefKarney, Ecef9Tuple, _llhn4, \
23
+ _xyzn4, _WGS84
24
+ from pygeodesy.errors import _NotImplementedError, _ValueError, _xattr, \
25
+ _xkwds, _xkwds_get, _xkwds_pop2
24
26
  from pygeodesy.fmath import fabs, fdot, Fhorner
25
27
  from pygeodesy.fsums import _floor, _Fsumf_, fsumf_, fsum1f_
26
28
  from pygeodesy.interns import _0_, _COMMASPACE_, _DOT_, _ecef_, _height_, _M_, \
27
- _invalid_, _lat0_, _lon0_, _ltp_, _name_, _too_
29
+ _invalid_, _lat0_, _lon0_, _name_, _too_
28
30
  # from pygeodesy.lazily import _ALL_LAZY # from vector3d
29
31
  from pygeodesy.ltpTuples import Attitude4Tuple, ChLVEN2Tuple, ChLV9Tuple, \
30
32
  ChLVYX2Tuple, Footprint5Tuple, Local9Tuple, \
31
33
  ChLVyx2Tuple, _XyzLocals4, _XyzLocals5, Xyz4Tuple
32
- from pygeodesy.named import _name__, _NamedBase, notOverloaded
34
+ from pygeodesy.named import _name__, _name2__, _NamedBase, notOverloaded
33
35
  from pygeodesy.namedTuples import LatLon3Tuple, LatLon4Tuple, Vector3Tuple
34
36
  from pygeodesy.props import Property, Property_RO, property_doc_, property_RO, \
35
37
  _update_all
@@ -42,25 +44,15 @@ from pygeodesy.vector3d import _ALL_LAZY, Vector3d
42
44
  # from math import fabs, floor as _floor # from .fmath, .fsums
43
45
 
44
46
  __all__ = _ALL_LAZY.ltp
45
- __version__ = '24.04.23'
47
+ __version__ = '24.06.07'
46
48
 
47
49
  _height0_ = _height_ + _0_
48
50
  _narrow_ = 'narrow'
49
51
  _wide_ = 'wide'
50
- _Xyz_ = 'Xyz'
51
-
52
-
53
- def _fov_2(**fov):
54
- # Half a field-of-view angle in C{degrees}.
55
- f = Degrees(Error=LocalError, **fov) * _0_5
56
- if EPS < f < _90_0:
57
- return f
58
- t = _invalid_ if f < 0 else _too_(_wide_ if f > EPS else _narrow_)
59
- raise LocalError(txt=t, **fov)
60
52
 
61
53
 
62
54
  class Attitude(_NamedBase):
63
- '''The orientation of a plane or camera in space.
55
+ '''The pose of a plane or camera in space.
64
56
  '''
65
57
  _alt = Meter( alt =_0_0)
66
58
  _roll = Degrees(roll=_0_0)
@@ -70,9 +62,9 @@ class Attitude(_NamedBase):
70
62
  def __init__(self, alt_attitude=INT0, tilt=INT0, yaw=INT0, roll=INT0, **name):
71
63
  '''New L{Attitude}.
72
64
 
73
- @kwarg alt_attitude: An altitude (C{meter}) above earth or an attitude
74
- (L{Attitude} or L{Attitude4Tuple}) with the
75
- C{B{alt}itude}, B{C{tilt}}, B{C{yaw}} and B{C{roll}}.
65
+ @kwarg alt_attitude: Altitude (C{meter}) above earth or previous attitude
66
+ (L{Attitude} or L{Attitude4Tuple}) with the C{B{alt}itude},
67
+ B{C{tilt}}, B{C{yaw}} and B{C{roll}}.
76
68
  @kwarg tilt: Pitch, elevation from horizontal (C{degrees180}), negative down
77
69
  (clockwise rotation along and around the x- or East axis).
78
70
  @kwarg yaw: Bearing, heading (compass C{degrees360}), clockwise from North
@@ -149,23 +141,26 @@ class Attitude(_NamedBase):
149
141
 
150
142
  bank = roll
151
143
 
152
- def rotate(self, x_xyz, y=None, z=None, Vector=None, **Vector_kwds):
144
+ def rotate(self, x_xyz, y=None, z=None, Vector=None, **name_Vector_kwds):
153
145
  '''Transform a (local) cartesian by this attitude's matrix.
154
146
 
155
- @arg x_xyz: X component of vector (C{scalar}) or (3-D) vector
156
- (C{Cartesian}, L{Vector3d} or L{Vector3Tuple}).
147
+ @arg x_xyz: X component of vector (C{scalar}) or (3-D) vector (C{Cartesian},
148
+ L{Vector3d} or L{Vector3Tuple}).
157
149
  @kwarg y: Y component of vector (C{scalar}), same units as B{C{x}}.
158
150
  @kwarg z: Z component of vector (C{scalar}), same units as B{C{x}}.
159
- @kwarg Vector: Class to return transformed point (C{Cartesian},
160
- L{Vector3d} or C{Vector3Tuple}) or C{None}.
161
- @kwarg Vector_kwds: Optional, additional B{C{Vector}} keyword arguments,
162
- ignored if C{B{Vector} is None}.
151
+ @kwarg Vector: Class to return transformed point (C{Cartesian}, L{Vector3d}
152
+ or C{Vector3Tuple}) or C{None}.
153
+ @kwarg name_Vector_kwds: Optional C{B{name}=NN} (C{str}) and optional,
154
+ additional B{C{Vector}} keyword arguments, ignored if
155
+ C{B{Vector} is None}.
163
156
 
164
- @return: A B{C{Vector}} instance or a L{Vector3Tuple}C{(x, y, z)} if
165
- C{B{Vector}=None}.
157
+ @return: A named B{C{Vector}} instance or if B{C{Vector}} is C{None},
158
+ a named L{Vector3Tuple}C{(x, y, z)}.
166
159
 
167
160
  @raise AttitudeError: Invalid B{C{x_xyz}}, B{C{y}} or B{C{z}}.
168
161
 
162
+ @raise TypeError: Invalid B{C{Vector}} or B{C{name_Vector_kwds}}.
163
+
169
164
  @see: U{Yaw, pitch, and roll rotations<http://MSL.CS.UIUC.edu/planning/node102.html>}.
170
165
  '''
171
166
  try:
@@ -177,8 +172,9 @@ class Attitude(_NamedBase):
177
172
  raise AttitudeError(x_xyz=x_xyz, y=y, z=z, cause=x)
178
173
 
179
174
  x, y, z = (fdot(r, *xyz) for r in self.matrix)
180
- return Vector3Tuple(x, y, z, name=self.name) if Vector is None else \
181
- Vector(x, y, z, **_xkwds(Vector_kwds, name=self.name))
175
+ n, kwds = _name2__(name_Vector_kwds, _or_nameof=self)
176
+ return Vector3Tuple(x, y, z, name=n) if Vector is None else \
177
+ Vector(x, y, z, name=n, **kwds)
182
178
 
183
179
  @property_doc_(' tilt/pitch/elevation from horizontal in C{degrees180}, negative down.')
184
180
  def tilt(self):
@@ -469,29 +465,34 @@ class LocalCartesian(_NamedBase):
469
465
  '''
470
466
  return self._ecef
471
467
 
472
- def _ecef2local(self, ecef, Xyz, Xyz_kwds):
468
+ def _ecef2local(self, ecef, Xyz, name_Xyz_kwds):
473
469
  '''(INTERNAL) Convert geocentric/geodetic to local, like I{forward}.
474
470
 
475
471
  @arg ecef: Geocentric (and geodetic) (L{Ecef9Tuple}).
476
472
  @arg Xyz: An L{XyzLocal}, L{Enu} or L{Ned} I{class} or C{None}.
477
- @arg Xyz_kwds: B{C{Xyz}} keyword arguments, ignored if C{B{Xyz} is None}.
473
+ @arg name_Xyz_kwds: Optional C{B{name}=NN} (C{str}) and optional,
474
+ additional B{C{Xyz}} keyword arguments, ignored if
475
+ C{B{Xyz} is None}.
478
476
 
479
- @return: An C{B{Xyz}(x, y, z, ltp, **B{Xyz_kwds}} instance or if
480
- C{B{Xyz} is None}, a L{Local9Tuple}C{(x, y, z, lat, lon,
477
+ @return: An C{B{Xyz}(x, y, z, ltp, **B{name_Xyz_kwds}} instance or
478
+ if C{B{Xyz} is None}, a L{Local9Tuple}C{(x, y, z, lat, lon,
481
479
  height, ltp, ecef, M)} with this C{ltp}, B{C{ecef}}
482
480
  (L{Ecef9Tuple}) converted to this C{datum} and C{M=None},
483
481
  always.
482
+
483
+ @raise TypeError: Invalid B{C{Xyz}} or B{C{name_Xyz_kwds}}.
484
484
  '''
485
+ _xinstanceof(Ecef9Tuple, ecef=ecef)
485
486
  ltp = self
486
487
  if ecef.datum != ltp.datum:
487
488
  ecef = ecef.toDatum(ltp.datum)
488
- x, y, z = self.M.rotate(ecef.xyz, *ltp._t0_xyz)
489
+ n, kwds = _name2__(name_Xyz_kwds, _or_nameof=ecef)
490
+ x, y, z = self.M.rotate(ecef.xyz, *ltp._t0_xyz)
489
491
  r = Local9Tuple(x, y, z, ecef.lat, ecef.lon, ecef.height,
490
- ltp, ecef, None, name=ecef.name)
492
+ ltp, ecef, None, name=n)
491
493
  if Xyz:
492
- if not issubclassof(Xyz, *_XyzLocals4): # Vector3d
493
- raise _TypesError(_Xyz_, Xyz, *_XyzLocals4)
494
- r = r.toXyz(Xyz=Xyz, **Xyz_kwds)
494
+ _xsubclassof(*_XyzLocals4, Xyz=Xyz) # Vector3d
495
+ r = r.toXyz(Xyz=Xyz, name=n, **kwds)
495
496
  return r
496
497
 
497
498
  @Property_RO
@@ -554,13 +555,14 @@ class LocalCartesian(_NamedBase):
554
555
  '''(INTERNAL) Convert I{local} to geocentric/geodetic, like I{.reverse}.
555
556
 
556
557
  @arg local: Local (L{XyzLocal}, L{Enu}, L{Ned}, L{Aer} or L{Local9Tuple}).
557
- @kwarg nine: Return 3- or 9-tuple (C{bool}).
558
+ @kwarg nine: If C{True}, return a 9-, otherwise a 3-tuple (C{bool}).
558
559
  @kwarg M: Include the rotation matrix (C{bool}).
559
560
 
560
561
  @return: A I{geocentric} 3-tuple C{(x, y, z)} or if C{B{nine}=True},
561
562
  an L{Ecef9Tuple}C{(x, y, z, lat, lon, height, C, M, datum)},
562
- optionally including rotation matrix C{M} or C{None}.
563
+ optionally including rotation matrix C{M} otherwise C{None}.
563
564
  '''
565
+ _xinstanceof(*_XyzLocals5, local=local)
564
566
  t = self.M.unrotate(local.xyz, *self._t0_xyz)
565
567
  if nine:
566
568
  t = self.ecef.reverse(*t, M=M)
@@ -1065,8 +1067,30 @@ class ChLVe(_ChLV, LocalCartesian):
1065
1067
  return t
1066
1068
 
1067
1069
 
1068
- def tyr3d(tilt=INT0, yaw=INT0, roll=INT0, Vector=Vector3d, **Vector_kwds):
1069
- '''Convert an attitude oriention into a (3-D) direction vector.
1070
+ def _fov_2(**fov):
1071
+ # Half a field-of-view angle in C{degrees}.
1072
+ f = Degrees(Error=LocalError, **fov) * _0_5
1073
+ if EPS < f < _90_0:
1074
+ return f
1075
+ t = _invalid_ if f < 0 else _too_(_wide_ if f > EPS else _narrow_)
1076
+ raise LocalError(txt=t, **fov)
1077
+
1078
+
1079
+ def _toLocal(inst, ltp, Xyz, Xyz_kwds):
1080
+ '''(INTENRAL) Helper for C{CartesianBase.toLocal} and C{latLonBase.toLocal}.
1081
+ '''
1082
+ return _xLtp(ltp, inst._Ltp)._ecef2local(inst._ecef9, Xyz, Xyz_kwds)
1083
+
1084
+
1085
+ def _toLtp(inst, Ecef, ecef9, name):
1086
+ '''(INTENRAL) Helper for C{CartesianBase.toLtp} and C{latLonBase.toLtp}.
1087
+ '''
1088
+ return inst._Ltp if Ecef in (None, inst.Ecef) and not name else \
1089
+ Ltp(ecef9, ecef=Ecef(inst.datum), name=inst._name__(name))
1090
+
1091
+
1092
+ def tyr3d(tilt=INT0, yaw=INT0, roll=INT0, Vector=Vector3d, **name_Vector_kwds):
1093
+ '''Convert an attitude pose into a (3-D) direction vector.
1070
1094
 
1071
1095
  @kwarg tilt: Pitch, elevation from horizontal (C{degrees}), negative down
1072
1096
  (clockwise rotation along and around the x-axis).
@@ -1074,27 +1098,41 @@ def tyr3d(tilt=INT0, yaw=INT0, roll=INT0, Vector=Vector3d, **Vector_kwds):
1074
1098
  (counter-clockwise rotation along and around the z-axis).
1075
1099
  @kwarg roll: Roll, bank (C{degrees}), positive to the right and down
1076
1100
  (clockwise rotation along and around the y-axis).
1101
+ @kwarg Vector: Class to return the direction vector (C{Cartesian},
1102
+ L{Vector3d} or C{Vector3Tuple}) or C{None}.
1103
+ @kwarg name_Vector_kwds: Optional C{B{name}=NN} (C{str}) and optional,
1104
+ additional B{C{Vector}} keyword arguments, ignored if
1105
+ C{B{Vector} is None}.
1077
1106
 
1078
1107
  @return: A named B{C{Vector}} instance or if B{C{Vector}} is C{None},
1079
1108
  a named L{Vector3Tuple}C{(x, y, z)}.
1080
1109
 
1110
+ @raise AttitudeError: Invalid B{C{tilt}}, B{C{yaw}} or B{C{roll}}.
1111
+
1112
+ @raise TypeError: Invalid B{C{Vector}} or B{C{name_Vector_kwds}}.
1113
+
1081
1114
  @see: U{Yaw, pitch, and roll rotations<http://MSL.CS.UIUC.edu/planning/node102.html>}
1082
- and function L{pygeodesy.hartzell} argument C{los}.
1115
+ and function L{pygeodesy.hartzell} argument C{los}, Line-Of-Sight.
1083
1116
  '''
1084
- d = Attitude4Tuple(_0_0, tilt, yaw, roll).tyr3d
1085
- return d if Vector is type(d) else (
1086
- Vector3Tuple(d.x, d.y, d.z, name=d.name) if Vector is None else
1087
- Vector(d.x, d.y, d.z, **_xkwds(Vector_kwds, name=d.name))) # PYCHOK indent
1117
+ v = Attitude4Tuple(_0_0, tilt, yaw, roll).tyr3d
1118
+ if Vector is not type(v):
1119
+ n, kwds = _name2__(name_Vector_kwds, name__=tyr3d)
1120
+ v = Vector3Tuple(v.x, v.y, v.z, name=n) if Vector is None else \
1121
+ Vector(v.x, v.y, v.z, name=n, **kwds)
1122
+ elif name_Vector_kwds:
1123
+ n, _ = _name2__(name_Vector_kwds)
1124
+ if n:
1125
+ v = v.copy(name=n)
1126
+ return v
1088
1127
 
1089
1128
 
1090
1129
  def _xLtp(ltp, *dflt):
1091
- '''(INTERNAL) Validate B{C{ltp}}.
1130
+ '''(INTERNAL) Validate B{C{ltp}} or ist B{C{dflt}}.
1092
1131
  '''
1093
1132
  if dflt and ltp is None:
1094
1133
  ltp = dflt[0]
1095
- if isinstance(ltp, (LocalCartesian, Ltp)):
1096
- return ltp
1097
- raise _TypesError(_ltp_, ltp, Ltp, LocalCartesian)
1134
+ _xinstanceof(Ltp, LocalCartesian, ltp=ltp)
1135
+ return ltp
1098
1136
 
1099
1137
  # **) MIT License
1100
1138
  #