pygeodesy 24.5.8__py2.py3-none-any.whl → 24.5.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.
- {PyGeodesy-24.5.8.dist-info → PyGeodesy-24.5.24.dist-info}/METADATA +2 -2
- PyGeodesy-24.5.24.dist-info/RECORD +116 -0
- pygeodesy/__init__.py +16 -12
- pygeodesy/__main__.py +9 -10
- pygeodesy/albers.py +42 -42
- pygeodesy/auxilats/__init__.py +1 -1
- pygeodesy/auxilats/__main__.py +7 -10
- pygeodesy/auxilats/auxAngle.py +32 -31
- pygeodesy/auxilats/auxLat.py +81 -51
- pygeodesy/azimuthal.py +123 -124
- pygeodesy/basics.py +165 -176
- pygeodesy/booleans.py +14 -15
- pygeodesy/cartesianBase.py +25 -23
- pygeodesy/clipy.py +3 -3
- pygeodesy/constants.py +8 -6
- pygeodesy/css.py +50 -42
- pygeodesy/datums.py +50 -48
- pygeodesy/dms.py +6 -6
- pygeodesy/ecef.py +27 -27
- pygeodesy/elevations.py +2 -2
- pygeodesy/ellipsoidalBase.py +28 -27
- pygeodesy/ellipsoidalBaseDI.py +8 -7
- pygeodesy/ellipsoidalNvector.py +11 -12
- pygeodesy/ellipsoids.py +41 -35
- pygeodesy/elliptic.py +12 -10
- pygeodesy/epsg.py +4 -3
- pygeodesy/errors.py +35 -13
- pygeodesy/etm.py +62 -53
- pygeodesy/fmath.py +48 -41
- pygeodesy/formy.py +93 -65
- pygeodesy/frechet.py +117 -102
- pygeodesy/fstats.py +52 -46
- pygeodesy/fsums.py +169 -145
- pygeodesy/gars.py +10 -9
- pygeodesy/geodesicw.py +32 -30
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +4 -4
- pygeodesy/geodesicx/gx.py +40 -32
- pygeodesy/geodesicx/gxarea.py +15 -12
- pygeodesy/geodesicx/gxbases.py +3 -4
- pygeodesy/geodesicx/gxline.py +6 -8
- pygeodesy/geodsolve.py +28 -26
- pygeodesy/geohash.py +47 -44
- pygeodesy/geoids.py +37 -35
- pygeodesy/hausdorff.py +112 -99
- pygeodesy/heights.py +136 -129
- pygeodesy/internals.py +576 -0
- pygeodesy/interns.py +6 -207
- pygeodesy/iters.py +22 -19
- pygeodesy/karney.py +18 -15
- pygeodesy/ktm.py +31 -24
- pygeodesy/latlonBase.py +12 -11
- pygeodesy/lazily.py +140 -218
- pygeodesy/lcc.py +24 -25
- pygeodesy/ltp.py +83 -71
- pygeodesy/ltpTuples.py +7 -5
- pygeodesy/mgrs.py +5 -4
- pygeodesy/named.py +136 -49
- pygeodesy/namedTuples.py +33 -25
- pygeodesy/nvectorBase.py +10 -9
- pygeodesy/osgr.py +14 -12
- pygeodesy/points.py +13 -13
- pygeodesy/props.py +7 -7
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/bases.py +3 -2
- pygeodesy/rhumb/solve.py +2 -2
- pygeodesy/solveBase.py +8 -7
- pygeodesy/sphericalTrigonometry.py +5 -5
- pygeodesy/streprs.py +8 -7
- pygeodesy/trf.py +8 -8
- pygeodesy/triaxials.py +67 -63
- pygeodesy/units.py +48 -50
- pygeodesy/unitsBase.py +24 -11
- pygeodesy/ups.py +7 -6
- pygeodesy/utily.py +4 -4
- pygeodesy/utm.py +53 -52
- pygeodesy/utmupsBase.py +11 -8
- pygeodesy/vector2d.py +6 -7
- pygeodesy/vector3d.py +16 -17
- pygeodesy/vector3dBase.py +5 -5
- PyGeodesy-24.5.8.dist-info/RECORD +0 -115
- {PyGeodesy-24.5.8.dist-info → PyGeodesy-24.5.24.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.5.8.dist-info → PyGeodesy-24.5.24.dist-info}/top_level.txt +0 -0
pygeodesy/interns.py
CHANGED
|
@@ -5,14 +5,11 @@ modules and function L{pygeodesy.machine}.
|
|
|
5
5
|
'''
|
|
6
6
|
import sys as _sys
|
|
7
7
|
try:
|
|
8
|
-
_intern = intern # PYCHOK in .lazily
|
|
8
|
+
_intern = intern # PYCHOK in .lazily, .trf
|
|
9
9
|
except NameError: # Python 3+
|
|
10
10
|
_intern = _sys.intern
|
|
11
11
|
|
|
12
12
|
_COMMASPACE_ = ', ' # overriden below
|
|
13
|
-
_pf2List = [] # cached _platform2 list
|
|
14
|
-
_Py3List = [] # cached _pythonarchine list
|
|
15
|
-
|
|
16
13
|
_sub_packages = 'auxilats', 'deprecated', 'geodesicx', 'rhumb' # PYCHOK in .lazily,
|
|
17
14
|
# ... make._dist, MANIFEST, setup.setup, test.bases, test.testModules
|
|
18
15
|
|
|
@@ -204,11 +201,10 @@ _distance_ = 'distance' # PYCHOK OK
|
|
|
204
201
|
_distant_ = _Prefix('distant') # PYCHOK OK
|
|
205
202
|
_doesn_t_exist_ = "doesn't exist" # PYCHOK OK
|
|
206
203
|
_DOT_ = Str_('.') # PYCHOK OK
|
|
207
|
-
|
|
204
|
+
_dunder_name_ = '__name__' # PYCHOK _DUNDER_(NN, _name_, NN)
|
|
208
205
|
_e_ = 'e' # PYCHOK OK
|
|
209
206
|
_E_ = 'E' # PYCHOK OK
|
|
210
207
|
_earth_ = 'earth' # PYCHOK OK
|
|
211
|
-
_east_ = 'east' # PYCHOK OK
|
|
212
208
|
_easting_ = 'easting' # PYCHOK OK
|
|
213
209
|
_ecef_ = 'ecef' # PYCHOK OK
|
|
214
210
|
_edge_ = 'edge' # PYCHOK OK
|
|
@@ -262,8 +258,8 @@ _isclockwise_ = 'isclockwise' # PYCHOK OK
|
|
|
262
258
|
_ispolar_ = 'ispolar' # PYCHOK OK
|
|
263
259
|
_j_ = 'j' # PYCHOK OK
|
|
264
260
|
_k0_ = 'k0' # PYCHOK OK
|
|
261
|
+
_keyword_ = 'keyword' # PYCHOK OK
|
|
265
262
|
_kind_ = 'kind' # PYCHOK OK
|
|
266
|
-
_knots_ = 'knots' # PYCHOK OK
|
|
267
263
|
_Krassovski1940_ = 'Krassovski1940' # PYCHOK OK
|
|
268
264
|
_Krassowsky1940_ = 'Krassowsky1940' # PYCHOK OK
|
|
269
265
|
_LANGLE_ = '<' # PYCHOK OK
|
|
@@ -320,7 +316,6 @@ _NLHASH_ = Str_(_NL_ + '# ') # PYCHOK OK
|
|
|
320
316
|
# _NLNL_ = _DNL_ # PYCHOK OK
|
|
321
317
|
_NN_ = 'NN' # PYCHOK OK
|
|
322
318
|
_no_ = _Prefix('no') # PYCHOK OK
|
|
323
|
-
_north_ = 'north' # PYCHOK OK
|
|
324
319
|
_northing_ = 'northing' # PYCHOK OK
|
|
325
320
|
_NorthPole_ = 'NorthPole' # PYCHOK OK
|
|
326
321
|
_not_ = _Prefix('not') # PYCHOK OK
|
|
@@ -397,7 +392,6 @@ _STAR_ = Str_('*') # PYCHOK OK
|
|
|
397
392
|
_start_ = 'start' # PYCHOK OK
|
|
398
393
|
_std_ = 'std' # PYCHOK OK
|
|
399
394
|
_stdev_ = 'stdev' # PYCHOK OK
|
|
400
|
-
_supported_ = 'supported' # PYCHOK OK
|
|
401
395
|
_tbd_ = 'tbd' # PYCHOK OK
|
|
402
396
|
_TILDE_ = '~' # PYCHOK OK
|
|
403
397
|
_to_ = 'to' # PYCHOK OK
|
|
@@ -451,204 +445,9 @@ _LR_PAIRS = {_LANGLE_: _RANGLE_,
|
|
|
451
445
|
_LPAREN_: _RPAREN_,
|
|
452
446
|
_LSQUARE_: _RSQUARE_} # PYCHOK OK
|
|
453
447
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
'''
|
|
458
|
-
try:
|
|
459
|
-
return inst.__name__
|
|
460
|
-
except AttributeError:
|
|
461
|
-
pass
|
|
462
|
-
return dflt[0] if dflt else inst.__class__.__name__
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
def _enquote(strs, quote=_QUOTE2_, white=NN): # in .basics, .solveBase
|
|
466
|
-
'''(INTERNAL) Enquote a string containing whitespace or replace
|
|
467
|
-
whitespace by C{white} if specified.
|
|
468
|
-
'''
|
|
469
|
-
if strs:
|
|
470
|
-
t = strs.split()
|
|
471
|
-
if len(t) > 1:
|
|
472
|
-
strs = white.join(t if white else (quote, strs, quote))
|
|
473
|
-
return strs
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
def _headof(name):
|
|
477
|
-
'''(INTERNAL) Get the head name of qualified C{name} or the C{name}.
|
|
478
|
-
'''
|
|
479
|
-
i = name.find(_DOT_)
|
|
480
|
-
return name if i < 0 else name[:i]
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
def _is(a, b): # PYCHOK no cover
|
|
484
|
-
'''(INTERNAL) C{a is b}? in C{PyPy}
|
|
485
|
-
'''
|
|
486
|
-
return (a == b) if _isPyPy() else (a is b)
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
def _isPyPy():
|
|
490
|
-
'''(INTERNAL) Is this C{PyPy}?
|
|
491
|
-
'''
|
|
492
|
-
# platform.python_implementation() == 'PyPy'
|
|
493
|
-
return _pythonarchine()[0].startswith(_PyPy__)
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
def _load_lib(name):
|
|
497
|
-
'''(INTERNAL) Load a C{dylib}, B{C{name}} must startwith('lib').
|
|
498
|
-
'''
|
|
499
|
-
# macOS 11+ (aka 10.16) no longer provides direct loading of
|
|
500
|
-
# system libraries. As a result, C{ctypes.util.find_library}
|
|
501
|
-
# will not find any library, unless previously installed by a
|
|
502
|
-
# low-level dlopen(name) call (with the library base C{name}).
|
|
503
|
-
from ctypes import CDLL
|
|
504
|
-
from ctypes.util import find_library
|
|
505
|
-
|
|
506
|
-
ns = find_library(name), name
|
|
507
|
-
if _sys.platform[:6] == 'darwin': # and os.name == 'posix'
|
|
508
|
-
from ctypes import _dlopen, DEFAULT_MODE
|
|
509
|
-
from os.path import join
|
|
510
|
-
ns += (_DOT_(name, 'dylib'),
|
|
511
|
-
_DOT_(name, 'framework'), join(
|
|
512
|
-
_DOT_(name, 'framework'), name))
|
|
513
|
-
else: # non-macOS
|
|
514
|
-
DEFAULT_MODE = 0
|
|
515
|
-
|
|
516
|
-
def _dlopen(*unused):
|
|
517
|
-
return True
|
|
518
|
-
|
|
519
|
-
for n in ns:
|
|
520
|
-
try:
|
|
521
|
-
if n and _dlopen(n, DEFAULT_MODE): # pre-load handle
|
|
522
|
-
lib = CDLL(n) # == ctypes.cdll.LoadLibrary(n)
|
|
523
|
-
if lib._name: # has a qualified name
|
|
524
|
-
return lib
|
|
525
|
-
except (AttributeError, OSError):
|
|
526
|
-
pass
|
|
527
|
-
|
|
528
|
-
return None # raise OSError
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
def machine():
|
|
532
|
-
'''Return standard C{platform.machine}, but distinguishing Intel I{native}
|
|
533
|
-
from Intel I{emulation} on Apple Silicon (on macOS only).
|
|
534
|
-
|
|
535
|
-
@return: Machine C{'arm64'} for Apple Silicon I{native}, C{'x86_64'}
|
|
536
|
-
for Intel I{native}, C{"arm64_x86_64"} for Intel I{emulation},
|
|
537
|
-
etc. (C{str} with C{comma}s replaced by C{underscore}s).
|
|
538
|
-
'''
|
|
539
|
-
return _platform2()[1]
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
def _platform2(sep=NN):
|
|
543
|
-
'''(INTERNAL) Get platform architecture and machine as C{2-list} or C{str}.
|
|
544
|
-
'''
|
|
545
|
-
L = _pf2List
|
|
546
|
-
if not L:
|
|
547
|
-
import platform
|
|
548
|
-
m = platform.machine() # ARM64, arm64, x86_64, iPhone13,2, etc.
|
|
549
|
-
m = m.replace(_COMMA_, _UNDER_)
|
|
550
|
-
if m.lower() == 'x86_64': # on Intel or Rosetta2 ...
|
|
551
|
-
v = platform.mac_ver() # ... and only on macOS ...
|
|
552
|
-
if v and _version2(v[0]) > (10, 15): # ... 11+ aka 10.16
|
|
553
|
-
# <https://Developer.Apple.com/forums/thread/659846>
|
|
554
|
-
if _sysctl_uint('sysctl.proc_translated') == 1: # and \
|
|
555
|
-
# _sysctl_uint('hw.optional.arm64') == 1: # PYCHOK indent
|
|
556
|
-
m = _UNDER_('arm64', m) # Apple Si emulating Intel x86-64
|
|
557
|
-
L[:] = [platform.architecture()[0], # bits
|
|
558
|
-
m] # arm64, arm64_x86_64, x86_64, etc.
|
|
559
|
-
return sep.join(L) if sep else L # 2-list()
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
def _pythonarchine(sep=NN): # in test/bases.py versions
|
|
563
|
-
'''(INTERNAL) Get PyPy and Python versions and C{_platform2} as C{3- or 4-list} or C{str}.
|
|
564
|
-
'''
|
|
565
|
-
L = _Py3List
|
|
566
|
-
if not L:
|
|
567
|
-
v = _sys.version
|
|
568
|
-
L[:] = [_Python_(v)] + _platform2()
|
|
569
|
-
pypy = _PyPy__(v)
|
|
570
|
-
if pypy:
|
|
571
|
-
L.insert(0, pypy)
|
|
572
|
-
return sep.join(L) if sep else L # 3- or 4-list
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
def _sysctl_uint(name):
|
|
576
|
-
'''(INTERNAL) Get an unsigned int sysctl item by name, use on macOS ONLY!
|
|
577
|
-
'''
|
|
578
|
-
libc = _load_lib('libc')
|
|
579
|
-
if libc: # <https://StackOverflow.com/questions/759892/python-ctypes-and-sysctl>
|
|
580
|
-
from ctypes import byref, c_char_p, c_size_t, c_uint, sizeof # get_errno
|
|
581
|
-
n = name if str is bytes else bytes(name, _utf_8_) # PYCHOK isPython2 = str is bytes
|
|
582
|
-
u = c_uint(0)
|
|
583
|
-
z = c_size_t(sizeof(u))
|
|
584
|
-
r = libc.sysctlbyname(c_char_p(n), byref(u), byref(z), None, c_size_t(0))
|
|
585
|
-
else: # could find or load 'libc'
|
|
586
|
-
r = -2
|
|
587
|
-
return int(r if r else u.value) # -1 ENOENT error, -2 no libc
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
def _tailof(name):
|
|
591
|
-
'''(INTERNAL) Get the base name of qualified C{name} or the C{name}.
|
|
592
|
-
'''
|
|
593
|
-
i = name.rfind(_DOT_) + 1
|
|
594
|
-
return name[i:] if i > 0 else name
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
def _under(name): # PYCHOK in .datums, .auxilats, .ups, .utm, .utmupsBase, ...
|
|
598
|
-
'''(INTERNAL) Prefix C{name} with I{underscore}.
|
|
599
|
-
'''
|
|
600
|
-
return name if name.startswith(_UNDER_) else NN(_UNDER_, name)
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
def _usage(file_py, *args): # in .etm
|
|
604
|
-
'''(INTERNAL) Build "usage: python -m ..." cmd line for module B{C{file_py}}.
|
|
605
|
-
'''
|
|
606
|
-
import os
|
|
607
|
-
m = os.path.dirname(file_py).replace(os.getcwd(), _ELLIPSIS_) \
|
|
608
|
-
.replace(os.sep, _DOT_).strip()
|
|
609
|
-
b, x = os.path.splitext(os.path.basename(file_py))
|
|
610
|
-
if x == '.py' and b != '__main__':
|
|
611
|
-
m = _DOT_(m or _pygeodesy_, b)
|
|
612
|
-
p = NN(_python_, _sys.version_info[0])
|
|
613
|
-
return NN('usage', _SPACE_(_COLON_, p, '-m', _enquote(m), *args))
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
def _version2(version, n=2):
|
|
617
|
-
'''(INTERNAL) Split C{B{version} str} into a C{1-, 2- or 3-tuple} of C{int}s.
|
|
618
|
-
'''
|
|
619
|
-
t = _version_ints(version.split(_DOT_, 2))
|
|
620
|
-
if len(t) < n:
|
|
621
|
-
t += (0,) * n
|
|
622
|
-
return t[:n]
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
def _version_info(package): # in .Base.karney, .basics
|
|
626
|
-
'''(INTERNAL) Get the C{package.__version_info__} as a 2- or
|
|
627
|
-
3-tuple C{(major, minor, revision)} if C{int}s.
|
|
628
|
-
'''
|
|
629
|
-
try:
|
|
630
|
-
return _version_ints(package.__version_info__)
|
|
631
|
-
except AttributeError:
|
|
632
|
-
return _version2(package.__version__.strip(), n=3)
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
def _version_ints(vs):
|
|
636
|
-
# helper for _version2 and _version_info above
|
|
637
|
-
|
|
638
|
-
def _ints(vs):
|
|
639
|
-
for v in vs:
|
|
640
|
-
try:
|
|
641
|
-
yield int(v.strip())
|
|
642
|
-
except (TypeError, ValueError):
|
|
643
|
-
pass
|
|
644
|
-
|
|
645
|
-
return tuple(_ints(vs))
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
__all__ = (_NN_, # not MISSING!
|
|
649
|
-
Str_.__name__, # classes
|
|
650
|
-
machine.__name__) # in .lazily
|
|
651
|
-
__version__ = '24.05.08'
|
|
448
|
+
__all__ = (_NN_, # NOT MISSING!
|
|
449
|
+
Str_.__name__) # classes
|
|
450
|
+
__version__ = '24.05.21'
|
|
652
451
|
|
|
653
452
|
if __name__ == '__main__':
|
|
654
453
|
|
pygeodesy/iters.py
CHANGED
|
@@ -9,15 +9,16 @@ the initial items, skipping of duplicate items and copying of the
|
|
|
9
9
|
iterated items.
|
|
10
10
|
'''
|
|
11
11
|
|
|
12
|
-
from pygeodesy.basics import islistuple, issubclassof, \
|
|
13
|
-
|
|
12
|
+
from pygeodesy.basics import islistuple, issubclassof, len2, \
|
|
13
|
+
map2, _passarg
|
|
14
14
|
# from pygeodesy.constants import _1_0 # from .utily
|
|
15
15
|
from pygeodesy.errors import _IndexError, LenError, PointsError, \
|
|
16
16
|
_TypeError, _ValueError
|
|
17
|
-
from pygeodesy.
|
|
18
|
-
|
|
17
|
+
# from pygeodesy.internals import _passarg # from .basics
|
|
18
|
+
from pygeodesy.interns import _0_, _composite_, _few_, _latlon_, \
|
|
19
|
+
_points_, _too_
|
|
19
20
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
|
|
20
|
-
from pygeodesy.named import
|
|
21
|
+
from pygeodesy.named import _Named, property_RO, Fmt
|
|
21
22
|
from pygeodesy.namedTuples import Point3Tuple, Points2Tuple
|
|
22
23
|
# from pygeodesy.props import property_RO # from .named
|
|
23
24
|
# from pygeodesy.streprs import Fmt # from .named
|
|
@@ -25,7 +26,7 @@ from pygeodesy.units import Int, Radius
|
|
|
25
26
|
from pygeodesy.utily import degrees2m, _Wrap, _1_0
|
|
26
27
|
|
|
27
28
|
__all__ = _ALL_LAZY.iters
|
|
28
|
-
__version__ = '
|
|
29
|
+
__version__ = '24.05.23'
|
|
29
30
|
|
|
30
31
|
_items_ = 'items'
|
|
31
32
|
_iterNumpy2len = 1 # adjustable for testing purposes
|
|
@@ -49,7 +50,7 @@ class _BaseIter(_Named):
|
|
|
49
50
|
_prev = _NOTHING
|
|
50
51
|
_wrap = False
|
|
51
52
|
|
|
52
|
-
def __init__(self, items, loop=0, dedup=False, Error=None, name
|
|
53
|
+
def __init__(self, items, loop=0, dedup=False, Error=None, **name):
|
|
53
54
|
'''New iterator over an iterable of B{C{items}}.
|
|
54
55
|
|
|
55
56
|
@arg items: Iterable (any C{type}, except composites).
|
|
@@ -57,7 +58,7 @@ class _BaseIter(_Named):
|
|
|
57
58
|
iterate index (non-negative C{int}).
|
|
58
59
|
@kwarg dedup: Skip duplicate items (C{bool}).
|
|
59
60
|
@kwarg Error: Error to raise (L{LenError}).
|
|
60
|
-
@kwarg name: Optional name (C{str}).
|
|
61
|
+
@kwarg name: Optional C{B{name}="items"} (C{str}).
|
|
61
62
|
|
|
62
63
|
@raise Error: Invalid B{C{items}} or sufficient number of B{C{items}}.
|
|
63
64
|
|
|
@@ -237,10 +238,11 @@ class _BaseIter(_Named):
|
|
|
237
238
|
class PointsIter(_BaseIter):
|
|
238
239
|
'''Iterator for C{points} with optional loop-back and copies.
|
|
239
240
|
'''
|
|
240
|
-
_base =
|
|
241
|
-
_Error =
|
|
241
|
+
_base = None
|
|
242
|
+
_Error = PointsError
|
|
243
|
+
_name = _points_
|
|
242
244
|
|
|
243
|
-
def __init__(self, points, loop=0, base=None, dedup=False, wrap=False, name
|
|
245
|
+
def __init__(self, points, loop=0, base=None, dedup=False, wrap=False, **name):
|
|
244
246
|
'''New L{PointsIter} iterator.
|
|
245
247
|
|
|
246
248
|
@arg points: C{Iterable} or C{list}, C{sequence}, C{set}, C{tuple},
|
|
@@ -251,13 +253,13 @@ class PointsIter(_BaseIter):
|
|
|
251
253
|
@kwarg dedup: Skip duplicate points (C{bool}).
|
|
252
254
|
@kwarg wrap: If C{True}, wrap or I{normalize} the enum-/iterated
|
|
253
255
|
B{C{points}} (C{bool}).
|
|
254
|
-
@kwarg name: Optional name (C{str}).
|
|
256
|
+
@kwarg name: Optional C{B{name}="points"} (C{str}).
|
|
255
257
|
|
|
256
258
|
@raise PointsError: Insufficient number of B{C{points}}.
|
|
257
259
|
|
|
258
260
|
@raise TypeError: Some B{C{points}} are not B{C{base}}.
|
|
259
261
|
'''
|
|
260
|
-
_BaseIter.__init__(self, points, loop=loop, dedup=dedup, name
|
|
262
|
+
_BaseIter.__init__(self, points, loop=loop, dedup=dedup, **name)
|
|
261
263
|
|
|
262
264
|
if base and not (isNumpy2(points) or isTuple2(points)):
|
|
263
265
|
self._base = base
|
|
@@ -309,12 +311,13 @@ class PointsIter(_BaseIter):
|
|
|
309
311
|
class LatLon2PsxyIter(PointsIter):
|
|
310
312
|
'''Iterate and convert for C{points} with optional loop-back and copies.
|
|
311
313
|
'''
|
|
312
|
-
_deg2m =
|
|
313
|
-
|
|
314
|
-
|
|
314
|
+
_deg2m = None
|
|
315
|
+
_name = _latlon_
|
|
316
|
+
_radius = None # keep degrees
|
|
317
|
+
_wrap = True
|
|
315
318
|
|
|
316
319
|
def __init__(self, points, loop=0, base=None, wrap=True, radius=None,
|
|
317
|
-
dedup=False, name
|
|
320
|
+
dedup=False, **name):
|
|
318
321
|
'''New L{LatLon2PsxyIter} iterator.
|
|
319
322
|
|
|
320
323
|
@note: The C{LatLon} latitude is considered the I{pseudo-y} and
|
|
@@ -330,13 +333,13 @@ class LatLon2PsxyIter(PointsIter):
|
|
|
330
333
|
@kwarg radius: Mean earth radius (C{meter}) for conversion from
|
|
331
334
|
C{degrees} to C{meter} (or C{radians} if C{B{radius}=1}).
|
|
332
335
|
@kwarg dedup: Skip duplicate points (C{bool}).
|
|
333
|
-
@kwarg name: Optional name (C{str}).
|
|
336
|
+
@kwarg name: Optional C{B{name}="latlon"} (C{str}).
|
|
334
337
|
|
|
335
338
|
@raise PointsError: Insufficient number of B{C{points}}.
|
|
336
339
|
|
|
337
340
|
@raise TypeError: Some B{C{points}} are not B{C{base}}-compatible.
|
|
338
341
|
'''
|
|
339
|
-
PointsIter.__init__(self, points, loop=loop, base=base, dedup=dedup, name
|
|
342
|
+
PointsIter.__init__(self, points, loop=loop, base=base, dedup=dedup, **name)
|
|
340
343
|
if not wrap:
|
|
341
344
|
self._wrap = False
|
|
342
345
|
if radius:
|
pygeodesy/karney.py
CHANGED
|
@@ -140,15 +140,15 @@ in C{pygeodesy} are based on I{Karney}'s post U{Area of a spherical polygon
|
|
|
140
140
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
141
141
|
|
|
142
142
|
from pygeodesy.basics import _copysign, int1s, isint, itemsorted, neg, unsigned0, \
|
|
143
|
-
_xgeographiclib, _zip
|
|
143
|
+
_xgeographiclib, _zip, _version_info
|
|
144
144
|
from pygeodesy.constants import NAN, _isfinite as _math_isfinite, _0_0, \
|
|
145
|
-
_1_16th,
|
|
145
|
+
_1_16th, _1_0, _2_0, _180_0, _N_180_0, _360_0
|
|
146
146
|
from pygeodesy.errors import GeodesicError, _ValueError, _xkwds, _xkwds_get
|
|
147
147
|
from pygeodesy.fmath import cbrt, fremainder, norm2
|
|
148
|
+
# from pygeodesy.internals import _version_info # from .basics
|
|
148
149
|
from pygeodesy.interns import NN, _2_, _a12_, _area_, _azi2_, _azi12_, _composite_, \
|
|
149
150
|
_lat1_, _lat2_, _lon1_, _lon2_, _m12_, _M12_, _M21_, \
|
|
150
|
-
_number_, _s12_, _S12_, _UNDER_,
|
|
151
|
-
_BAR_ # PYCHOK used!
|
|
151
|
+
_number_, _s12_, _S12_, _UNDER_, _BAR_ # PYCHOK used!
|
|
152
152
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _getenv
|
|
153
153
|
from pygeodesy.named import ADict, _NamedBase, _NamedTuple, notImplemented, _Pass
|
|
154
154
|
from pygeodesy.props import deprecated_method, Property_RO
|
|
@@ -159,7 +159,7 @@ from pygeodesy.utily import atan2d, sincos2d, tand, _unrollon, fabs
|
|
|
159
159
|
# from math import fabs # from .utily
|
|
160
160
|
|
|
161
161
|
__all__ = _ALL_LAZY.karney
|
|
162
|
-
__version__ = '24.
|
|
162
|
+
__version__ = '24.05.20'
|
|
163
163
|
|
|
164
164
|
_K_2_0 = _getenv('PYGEODESY_GEOGRAPHICLIB', _2_) == _2_
|
|
165
165
|
_perimeter_ = 'perimeter'
|
|
@@ -168,7 +168,7 @@ _perimeter_ = 'perimeter'
|
|
|
168
168
|
class _GTuple(_NamedTuple): # in .testNamedTuples
|
|
169
169
|
'''(INTERNAL) Helper.
|
|
170
170
|
'''
|
|
171
|
-
def toGDict(self, **updates):
|
|
171
|
+
def toGDict(self, **updates): # NO name=NN
|
|
172
172
|
'''Convert this C{*Tuple} to a L{GDict}.
|
|
173
173
|
|
|
174
174
|
@kwarg updates: Optional items to apply (C{nam=value} pairs)
|
|
@@ -359,12 +359,11 @@ class _CapsBase(_NamedBase): # in .auxilats, .geodesicx.gxbases
|
|
|
359
359
|
'''
|
|
360
360
|
self._debug = Caps._DEBUG_ALL if debug else 0
|
|
361
361
|
|
|
362
|
-
def _iter2tion(self, r,
|
|
362
|
+
def _iter2tion(self, r, iter=None, **unused):
|
|
363
363
|
'''(INTERNAL) Copy C{C{s}.iter} into C{B{r}._iteration}.
|
|
364
364
|
'''
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
self._iteration = r._iteration = i
|
|
365
|
+
if iter is not None:
|
|
366
|
+
self._iteration = r._iteration = iter
|
|
368
367
|
return r
|
|
369
368
|
|
|
370
369
|
|
|
@@ -468,7 +467,7 @@ class Inverse10Tuple(_GTuple):
|
|
|
468
467
|
|
|
469
468
|
@kwarg updates: Optional items to apply (C{nam=value} pairs)
|
|
470
469
|
'''
|
|
471
|
-
return _GTuple.toGDict(self, azi1=atan2d(self.salp1, self.calp1), # PYCHOK
|
|
470
|
+
return _GTuple.toGDict(self, azi1=atan2d(self.salp1, self.calp1), # PYCHOK namedTuple
|
|
472
471
|
azi2=atan2d(self.salp2, self.calp2), # PYCHOK namedTuple
|
|
473
472
|
**updates) # PYCHOK indent
|
|
474
473
|
|
|
@@ -750,7 +749,10 @@ def _polynomial(x, cs, i, j): # PYCHOK shared
|
|
|
750
749
|
# for c in cs[i+1:j]:
|
|
751
750
|
# s, t = _sum2_(s * x, t * x, c)
|
|
752
751
|
# return s # + t
|
|
753
|
-
s
|
|
752
|
+
s = cs[i]
|
|
753
|
+
i += 1
|
|
754
|
+
if x and i < j:
|
|
755
|
+
s, _ = _sum2_(s, _0_0, x=x, *cs[i:j])
|
|
754
756
|
return s # + t
|
|
755
757
|
|
|
756
758
|
|
|
@@ -843,11 +845,12 @@ def _sum2_(s, t, *vs, **x):
|
|
|
843
845
|
|
|
844
846
|
@note: NOT "error-free", see C{pygeodesy.test/testKarney.py}.
|
|
845
847
|
'''
|
|
846
|
-
x = _xkwds_get(x, x=
|
|
848
|
+
x = _xkwds_get(x, x=_1_0)
|
|
849
|
+
p = x != _1_0
|
|
847
850
|
|
|
848
851
|
_s2, _u0 = _sum2, unsigned0
|
|
849
852
|
for v in vs:
|
|
850
|
-
if
|
|
853
|
+
if p:
|
|
851
854
|
s *= x
|
|
852
855
|
t *= x
|
|
853
856
|
if v:
|
|
@@ -857,7 +860,7 @@ def _sum2_(s, t, *vs, **x):
|
|
|
857
860
|
if s:
|
|
858
861
|
t += u # accumulate u into t
|
|
859
862
|
# elif t: # s == 0 implies t == 0
|
|
860
|
-
# raise _AssertionError(t=t,
|
|
863
|
+
# raise _AssertionError(t=t, txt_not_=_0_)
|
|
861
864
|
else:
|
|
862
865
|
s = _u0(u) # result is u, t = 0
|
|
863
866
|
else:
|
pygeodesy/ktm.py
CHANGED
|
@@ -48,18 +48,18 @@ from pygeodesy.constants import INF, _K0_UTM, PI, PI_2, _0_0s, _0_0, \
|
|
|
48
48
|
_1_0, _90_0, _copysignINF
|
|
49
49
|
from pygeodesy.datums import Datum, _spherical_datum, _WGS84, _EWGS84
|
|
50
50
|
# from pygeodesy.ellipsoids import _EWGS84 # from .datums
|
|
51
|
-
from pygeodesy.errors import _ValueError,
|
|
51
|
+
from pygeodesy.errors import _ValueError, _xkwds_pop2, _Xorder
|
|
52
52
|
from pygeodesy.fmath import hypot, hypot1
|
|
53
53
|
from pygeodesy.fsums import fsum1f_
|
|
54
|
-
from pygeodesy.interns import
|
|
54
|
+
from pygeodesy.interns import _COMMASPACE_, _singular_
|
|
55
55
|
from pygeodesy.karney import _atan2d, _diff182, _fix90, _norm180, \
|
|
56
|
-
_polynomial, _unsigned2
|
|
57
|
-
from pygeodesy.lazily import _ALL_LAZY
|
|
58
|
-
|
|
56
|
+
_polynomial, _unsigned2
|
|
57
|
+
# from pygeodesy.lazily import _ALL_LAZY # from .named
|
|
58
|
+
from pygeodesy.named import _NamedBase, pairs, _ALL_LAZY
|
|
59
59
|
from pygeodesy.namedTuples import Forward4Tuple, Reverse4Tuple
|
|
60
60
|
from pygeodesy.props import property_doc_, Property, Property_RO, \
|
|
61
61
|
_update_all
|
|
62
|
-
# from pygeodesy.streprs import pairs
|
|
62
|
+
# from pygeodesy.streprs import pairs # from .named
|
|
63
63
|
from pygeodesy.units import Degrees, Scalar_, _1mm as _TOL_10 # PYCHOK used!
|
|
64
64
|
from pygeodesy.utily import atan1d, _loneg, sincos2, sincos2d_
|
|
65
65
|
|
|
@@ -67,7 +67,7 @@ from cmath import polar
|
|
|
67
67
|
from math import atan2, asinh, cos, cosh, degrees, fabs, sin, sinh, sqrt, tanh
|
|
68
68
|
|
|
69
69
|
__all__ = _ALL_LAZY.ktm
|
|
70
|
-
__version__ = '24.
|
|
70
|
+
__version__ = '24.05.24'
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
class KTMError(_ValueError):
|
|
@@ -115,24 +115,33 @@ class KTransverseMercator(_NamedBase):
|
|
|
115
115
|
_mTM = 6
|
|
116
116
|
_raiser = False # throw Error
|
|
117
117
|
|
|
118
|
-
def __init__(self, a_earth=_EWGS84, f=None, lon0=0, k0=_K0_UTM,
|
|
119
|
-
|
|
118
|
+
def __init__(self, a_earth=_EWGS84, f=None, lon0=0, k0=_K0_UTM,
|
|
119
|
+
raiser=False, **TMorder_name):
|
|
120
120
|
'''New L{KTransverseMercator}.
|
|
121
121
|
|
|
122
122
|
@kwarg a_earth: This rhumb's earth (L{Ellipsoid}, L{Ellipsoid2},
|
|
123
123
|
L{a_f2Tuple}, L{Datum}, 2-tuple (C{a, f})) or the
|
|
124
124
|
equatorial radius (C{scalar}, C{meter}).
|
|
125
|
-
@kwarg f: The ellipsoid's flattening (C{scalar}), iff B{C{a_earth}}
|
|
126
|
-
a C{scalar}, ignored otherwise.
|
|
125
|
+
@kwarg f: The ellipsoid's flattening (C{scalar}), iff B{C{a_earth}}
|
|
126
|
+
is a C{scalar}, ignored otherwise.
|
|
127
127
|
@kwarg lon0: The central meridian (C{degrees180}).
|
|
128
128
|
@kwarg k0: Central scale factor (C{scalar}).
|
|
129
|
-
@kwarg name: Optional name (C{str}).
|
|
130
129
|
@kwarg raiser: If C{True}, throw a L{KTMError} for C{forward}
|
|
131
130
|
singularities (C{bool}).
|
|
132
|
-
@kwarg
|
|
131
|
+
@kwarg TMorder_name: Optional C{B{name}=NN} (C{str}) and optional
|
|
132
|
+
keyword argument C{B{TMorder}=6} for the order of
|
|
133
|
+
this L{KTransverseMercator}, see property C{TMorder}.
|
|
133
134
|
|
|
134
135
|
@raise KTMError: Invalid B{C{a_earth}}, B{C{f}} or B{C{TMorder}}.
|
|
135
136
|
'''
|
|
137
|
+
if TMorder_name:
|
|
138
|
+
M = self._mTM
|
|
139
|
+
m, name = _xkwds_pop2(TMorder_name, TMorder=M)
|
|
140
|
+
if m != M:
|
|
141
|
+
self.TMorder = m
|
|
142
|
+
if name:
|
|
143
|
+
self.name = name
|
|
144
|
+
|
|
136
145
|
if f is not None:
|
|
137
146
|
self.ellipsoid = a_earth, f
|
|
138
147
|
elif a_earth in (_EWGS84, _WGS84, None):
|
|
@@ -141,14 +150,11 @@ class KTransverseMercator(_NamedBase):
|
|
|
141
150
|
self.datum = a_earth
|
|
142
151
|
else:
|
|
143
152
|
self.ellipsoid = a_earth
|
|
153
|
+
|
|
144
154
|
self.lon0 = lon0
|
|
145
155
|
self.k0 = k0
|
|
146
|
-
if name: # PYCHOK no cover
|
|
147
|
-
self.name = name
|
|
148
156
|
if raiser:
|
|
149
157
|
self.raiser = True
|
|
150
|
-
if TMorder:
|
|
151
|
-
self.TMorder = _xkwds_get(TMorder, TMorder=self._mTM)
|
|
152
158
|
|
|
153
159
|
@Property_RO
|
|
154
160
|
def _Alp(self):
|
|
@@ -215,13 +221,13 @@ class KTransverseMercator(_NamedBase):
|
|
|
215
221
|
|
|
216
222
|
f = flattening
|
|
217
223
|
|
|
218
|
-
def forward(self, lat, lon, lon0=None, name
|
|
224
|
+
def forward(self, lat, lon, lon0=None, **name):
|
|
219
225
|
'''Forward projection, from geographic to transverse Mercator.
|
|
220
226
|
|
|
221
227
|
@arg lat: Latitude of point (C{degrees90}).
|
|
222
228
|
@arg lon: Longitude of point (C{degrees180}).
|
|
223
229
|
@arg lon0: Central meridian of the projection (C{degrees180}).
|
|
224
|
-
@kwarg name: Optional name (C{str}).
|
|
230
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
225
231
|
|
|
226
232
|
@return: L{Forward4Tuple}C{(easting, northing, gamma, scale)}
|
|
227
233
|
with C{easting} and C{northing} in C{meter}, unfalsed, the
|
|
@@ -272,7 +278,7 @@ class KTransverseMercator(_NamedBase):
|
|
|
272
278
|
y, g = neg_(y, g)
|
|
273
279
|
if _lon:
|
|
274
280
|
x, g = neg_(x, g)
|
|
275
|
-
return Forward4Tuple(x, y, _norm180(g), k, name=
|
|
281
|
+
return Forward4Tuple(x, y, _norm180(g), k, name=self._name__(name))
|
|
276
282
|
|
|
277
283
|
@property_doc_(''' the central scale factor (C{float}).''')
|
|
278
284
|
def k0(self):
|
|
@@ -347,12 +353,13 @@ class KTransverseMercator(_NamedBase):
|
|
|
347
353
|
self. lon0 = lon0
|
|
348
354
|
return t
|
|
349
355
|
|
|
350
|
-
def reverse(self, x, y, lon0=None, name
|
|
356
|
+
def reverse(self, x, y, lon0=None, **name):
|
|
351
357
|
'''Reverse projection, from transverse Mercator to geographic.
|
|
352
358
|
|
|
353
359
|
@arg x: Easting of point (C{meter}).
|
|
354
360
|
@arg y: Northing of point (C{meter}).
|
|
355
361
|
@arg lon0: Central meridian of the projection (C{degrees180}).
|
|
362
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
356
363
|
|
|
357
364
|
@return: L{Reverse4Tuple}C{(lat, lon, gamma, scale)} with
|
|
358
365
|
C{lat}- and C{lon}gitude in C{degrees}, I{unfalsed}.
|
|
@@ -394,7 +401,7 @@ class KTransverseMercator(_NamedBase):
|
|
|
394
401
|
lat += self._lat0
|
|
395
402
|
lon += self._lon0 if lon0 is None else _norm180(lon0)
|
|
396
403
|
return Reverse4Tuple(lat, _norm180(lon), _norm180(g), k,
|
|
397
|
-
name=
|
|
404
|
+
name=self._name__(name))
|
|
398
405
|
|
|
399
406
|
@Property
|
|
400
407
|
def TMorder(self):
|
|
@@ -419,7 +426,7 @@ class KTransverseMercator(_NamedBase):
|
|
|
419
426
|
d = dict(ellipsoid=self.ellipsoid, k0=self.k0, TMorder=self.TMorder)
|
|
420
427
|
if self.name: # PYCHOK no cover
|
|
421
428
|
d.update(name=self.name)
|
|
422
|
-
return _COMMASPACE_.join(
|
|
429
|
+
return _COMMASPACE_.join(pairs(d, **kwds))
|
|
423
430
|
|
|
424
431
|
|
|
425
432
|
def _cma(a, b0, b1, Cn):
|
|
@@ -605,7 +612,7 @@ assert set(_AlpCoeffs.keys()) == set(_BetCoeffs.keys())
|
|
|
605
612
|
|
|
606
613
|
if __name__ == '__main__':
|
|
607
614
|
|
|
608
|
-
from pygeodesy.
|
|
615
|
+
from pygeodesy.internals import _usage
|
|
609
616
|
from sys import argv, exit as _exit
|
|
610
617
|
|
|
611
618
|
_exit(_usage(*argv).replace('.ktm', '.etm -series'))
|