pygeodesy 24.10.24__py2.py3-none-any.whl → 24.11.11__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.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/METADATA +4 -4
- {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/RECORD +54 -54
- {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/WHEEL +1 -1
- pygeodesy/__init__.py +2 -2
- pygeodesy/azimuthal.py +51 -61
- pygeodesy/basics.py +34 -33
- pygeodesy/booleans.py +36 -36
- pygeodesy/cartesianBase.py +5 -5
- pygeodesy/constants.py +4 -4
- pygeodesy/css.py +7 -8
- pygeodesy/deprecated/__init__.py +1 -1
- pygeodesy/deprecated/classes.py +9 -9
- pygeodesy/deprecated/functions.py +6 -6
- pygeodesy/ecef.py +11 -14
- pygeodesy/ellipsoidalBase.py +105 -120
- pygeodesy/ellipsoidalBaseDI.py +114 -118
- pygeodesy/ellipsoidalExact.py +35 -37
- pygeodesy/ellipsoids.py +3 -3
- pygeodesy/errors.py +24 -24
- pygeodesy/etm.py +80 -72
- pygeodesy/fmath.py +39 -37
- pygeodesy/formy.py +3 -2
- pygeodesy/fsums.py +51 -40
- pygeodesy/geodesicw.py +15 -14
- pygeodesy/geodesicx/__init__.py +2 -2
- pygeodesy/geodsolve.py +7 -16
- pygeodesy/geoids.py +5 -5
- pygeodesy/heights.py +2 -2
- pygeodesy/internals.py +63 -79
- pygeodesy/karney.py +2 -2
- pygeodesy/ktm.py +11 -13
- pygeodesy/latlonBase.py +6 -6
- pygeodesy/lazily.py +5 -5
- pygeodesy/lcc.py +4 -4
- pygeodesy/ltp.py +10 -10
- pygeodesy/ltpTuples.py +74 -75
- pygeodesy/mgrs.py +9 -10
- pygeodesy/named.py +4 -0
- pygeodesy/osgr.py +9 -12
- pygeodesy/props.py +2 -2
- pygeodesy/resections.py +9 -10
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/solve.py +3 -3
- pygeodesy/simplify.py +5 -5
- pygeodesy/sphericalNvector.py +80 -123
- pygeodesy/sphericalTrigonometry.py +60 -66
- pygeodesy/units.py +2 -2
- pygeodesy/utm.py +6 -6
- pygeodesy/vector2d.py +13 -13
- pygeodesy/vector3d.py +19 -21
- pygeodesy/vector3dBase.py +18 -15
- pygeodesy/webmercator.py +4 -4
- pygeodesy/wgrs.py +4 -4
- {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/top_level.txt +0 -0
pygeodesy/sphericalNvector.py
CHANGED
|
@@ -38,7 +38,7 @@ from pygeodesy.constants import EPS, EPS0, PI, PI2, PI_2, R_M, \
|
|
|
38
38
|
_0_0, _0_5, _1_0
|
|
39
39
|
# from pygeodesy.datums import Datums # from .sphericalBase
|
|
40
40
|
from pygeodesy.errors import PointsError, VectorError, _xError, _xkwds
|
|
41
|
-
from pygeodesy.fmath import fmean, fsum
|
|
41
|
+
from pygeodesy.fmath import fdot_, fmean, fsum
|
|
42
42
|
# from pygeodesy.fsums import fsum # from .fmath
|
|
43
43
|
from pygeodesy.interns import _composite_, _end_, _Nv00_, _other_, \
|
|
44
44
|
_point_, _pole_
|
|
@@ -61,7 +61,7 @@ from pygeodesy.utily import atan2, degrees360, fabs, sincos2, sincos2_, \
|
|
|
61
61
|
# from math import atan2, fabs # from utily
|
|
62
62
|
|
|
63
63
|
__all__ = _ALL_LAZY.sphericalNvector
|
|
64
|
-
__version__ = '24.
|
|
64
|
+
__version__ = '24.11.07'
|
|
65
65
|
|
|
66
66
|
_lines_ = 'lines'
|
|
67
67
|
|
|
@@ -273,8 +273,10 @@ class LatLon(LatLonNvectorBase, LatLonSphericalBase):
|
|
|
273
273
|
a, b = self.philam
|
|
274
274
|
|
|
275
275
|
sa, ca, sb, cb, st, ct = sincos2_(a, b, t)
|
|
276
|
-
|
|
277
|
-
|
|
276
|
+
|
|
277
|
+
sa *= st
|
|
278
|
+
return Nvector(fdot_(sb, ct, -sa, cb),
|
|
279
|
+
-fdot_(cb, ct, sa, sb),
|
|
278
280
|
ca * st, name=self.name) # XXX .unit()
|
|
279
281
|
|
|
280
282
|
def greatCircleTo(self, other, wrap=False):
|
|
@@ -391,47 +393,29 @@ class LatLon(LatLonNvectorBase, LatLonSphericalBase):
|
|
|
391
393
|
return i.toLatLon(height=h, LatLon=self.classof) # Nvector(i.x, i.y, i.z).toLatLon(...)
|
|
392
394
|
|
|
393
395
|
def intersection(self, end1, start2, end2, height=None, wrap=False):
|
|
394
|
-
'''Locate
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
@arg end1: End point of the first line (L{LatLon}) or the
|
|
398
|
-
initial bearing at this point (compass C{degrees360}).
|
|
399
|
-
@arg start2: Start point of the second line (L{LatLon}).
|
|
400
|
-
@arg end2: End point of the second line (L{LatLon}) or the
|
|
401
|
-
initial bearing at the second point (compass
|
|
402
|
-
C{degrees}).
|
|
403
|
-
@kwarg height: Optional height at the intersection point,
|
|
404
|
-
overriding the mean height (C{meter}).
|
|
405
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll all
|
|
406
|
-
start and end points (C{bool}).
|
|
396
|
+
'''Locate an intersection point of two lines each defined by two
|
|
397
|
+
points or by a point and an (initial) bearing.
|
|
407
398
|
|
|
408
399
|
@return: The intersection point (L{LatLon}).
|
|
409
400
|
|
|
410
|
-
@
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
@raise ValueError: Intersection is ambiguous or infinite or
|
|
414
|
-
the lines are parallel, coincident or null.
|
|
415
|
-
|
|
416
|
-
@see: Function L{sphericalNvector.intersection} and method
|
|
417
|
-
L{intersection2}.
|
|
401
|
+
@see: Method L{intersection2<sphericalNvector.LatLon.intersection2>}
|
|
402
|
+
for further details.
|
|
418
403
|
'''
|
|
419
404
|
return intersection(self, end1, start2, end2, height=height,
|
|
420
405
|
wrap=wrap, LatLon=self.classof)
|
|
421
406
|
|
|
422
407
|
def intersection2(self, end1, start2, end2, height=None, wrap=False):
|
|
423
|
-
'''Locate
|
|
424
|
-
by two points or by a
|
|
425
|
-
|
|
426
|
-
@arg end1: End point of the
|
|
427
|
-
|
|
428
|
-
@arg start2: Start point of the
|
|
429
|
-
@arg end2: End point of the
|
|
430
|
-
|
|
431
|
-
C{degrees360}).
|
|
408
|
+
'''Locate both intersections of two (great circle) lines each defined
|
|
409
|
+
by two points or by a point and an (initial) bearing.
|
|
410
|
+
|
|
411
|
+
@arg end1: End point of the line starting at this point (L{LatLon})
|
|
412
|
+
or the bearing at this point (compass C{degrees360}).
|
|
413
|
+
@arg start2: Start point of the other line (L{LatLon}).
|
|
414
|
+
@arg end2: End point of the other line (L{LatLon}) or the bearing
|
|
415
|
+
at B{C{start2}} (compass C{degrees360}).
|
|
432
416
|
@kwarg height: Optional height at the intersection and antipodal
|
|
433
417
|
point, overriding the mean height (C{meter}).
|
|
434
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll
|
|
418
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
|
|
435
419
|
B{C{start2}} and both B{C{end*}} points (C{bool}).
|
|
436
420
|
|
|
437
421
|
@return: 2-Tuple C{(intersection, antipode)}, each a B{C{LatLon}}.
|
|
@@ -442,8 +426,7 @@ class LatLon(LatLonNvectorBase, LatLonSphericalBase):
|
|
|
442
426
|
@raise ValueError: Intersection is ambiguous or infinite or
|
|
443
427
|
the lines are parallel, coincident or null.
|
|
444
428
|
|
|
445
|
-
@see: Function L{sphericalNvector.intersection2}
|
|
446
|
-
L{intersection}.
|
|
429
|
+
@see: Function L{sphericalNvector.intersection2}.
|
|
447
430
|
'''
|
|
448
431
|
return intersection2(self, end1, start2, end2, height=height,
|
|
449
432
|
wrap=wrap, LatLon=self.classof)
|
|
@@ -472,17 +455,14 @@ class LatLon(LatLonNvectorBase, LatLonSphericalBase):
|
|
|
472
455
|
|
|
473
456
|
# sum subtended angles of each edge (using n0, the
|
|
474
457
|
# normal vector to this point for sign of α)
|
|
475
|
-
def
|
|
476
|
-
|
|
477
|
-
n0
|
|
478
|
-
_m0 = n0.minus
|
|
479
|
-
p1 = Ps[0]
|
|
480
|
-
vs1 = _m0(p1.toNvector())
|
|
458
|
+
def _subt(Ps, n0, w):
|
|
459
|
+
p1 = Ps[0]
|
|
460
|
+
vs1 = n0.minus(p1.toNvector())
|
|
481
461
|
for p2 in Ps.iterate(closed=True):
|
|
482
462
|
if w and not Ps.looped:
|
|
483
463
|
p2 = _unrollon(p1, p2)
|
|
484
|
-
p1 =
|
|
485
|
-
vs2 =
|
|
464
|
+
p1 = p2
|
|
465
|
+
vs2 = n0.minus(p2.toNvector())
|
|
486
466
|
yield vs1.angleTo(vs2, vSign=n0) # PYCHOK false
|
|
487
467
|
vs1 = vs2
|
|
488
468
|
|
|
@@ -491,7 +471,8 @@ class LatLon(LatLonNvectorBase, LatLonSphericalBase):
|
|
|
491
471
|
# an exterior point will sum to 0°. On a sphere, enclosed
|
|
492
472
|
# point angles will sum to less than 360° (due to spherical
|
|
493
473
|
# excess), exterior point angles will be small but non-zero.
|
|
494
|
-
s = fsum(
|
|
474
|
+
s = fsum(_subt(self.PointsIter(points, loop=1, wrap=wrap),
|
|
475
|
+
self.toNvector(), wrap)) # normal vector
|
|
495
476
|
# XXX are winding number optimisations equally applicable to
|
|
496
477
|
# spherical surface?
|
|
497
478
|
return fabs(s) > PI
|
|
@@ -642,8 +623,8 @@ class LatLon(LatLonNvectorBase, LatLonSphericalBase):
|
|
|
642
623
|
return r.closest, r.distance
|
|
643
624
|
|
|
644
625
|
def nearestOn3(self, points, closed=False, radius=R_M, height=None, wrap=False):
|
|
645
|
-
'''Locate the point on a path or polygon (with great circle
|
|
646
|
-
|
|
626
|
+
'''Locate the point on a path or polygon (with great circle arcs
|
|
627
|
+
joining consecutive points) closest to this point.
|
|
647
628
|
|
|
648
629
|
The closest point is either on within the extent of any great
|
|
649
630
|
circle arc or the nearest of the arc's end points.
|
|
@@ -653,14 +634,14 @@ class LatLon(LatLonNvectorBase, LatLonSphericalBase):
|
|
|
653
634
|
@kwarg radius: Mean earth radius (C{meter}) or C{None}.
|
|
654
635
|
@kwarg height: Optional height, overriding the mean height
|
|
655
636
|
for a point within the arc (C{meter}).
|
|
656
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll
|
|
657
|
-
|
|
637
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
|
|
638
|
+
B{C{points}} (C{bool}).
|
|
658
639
|
|
|
659
640
|
@return: A L{NearestOn3Tuple}C{(closest, distance, angle)} of
|
|
660
641
|
the C{closest} point (L{LatLon}), the C{distance}
|
|
661
642
|
between this and the C{closest} point in C{meter},
|
|
662
|
-
same units as B{C{radius}} or in C{radians} if
|
|
663
|
-
C{B{radius} is None} and the C{angle} from this to
|
|
643
|
+
same units as B{C{radius}} (or in C{radians} if
|
|
644
|
+
C{B{radius} is None}) and the C{angle} from this to
|
|
664
645
|
the C{closest} point in compass C{degrees360}.
|
|
665
646
|
|
|
666
647
|
@raise TypeError: Some B{C{points}} are not C{LatLon}.
|
|
@@ -668,16 +649,16 @@ class LatLon(LatLonNvectorBase, LatLonSphericalBase):
|
|
|
668
649
|
@raise ValueError: No B{C{points}}.
|
|
669
650
|
'''
|
|
670
651
|
Ps = self.PointsIter(points, loop=1, wrap=wrap)
|
|
671
|
-
|
|
652
|
+
_d = self.distanceTo
|
|
672
653
|
_n = self.nearestOn
|
|
673
654
|
|
|
674
655
|
c = p1 = Ps[0]
|
|
675
|
-
r =
|
|
656
|
+
r = _d(c, radius=None) # radians
|
|
676
657
|
for p2 in Ps.iterate(closed=closed):
|
|
677
658
|
if wrap and not Ps.looped:
|
|
678
659
|
p2 = _unrollon(p1, p2)
|
|
679
660
|
p = _n(p1, p2, height=height)
|
|
680
|
-
d =
|
|
661
|
+
d = _d(p, radius=None) # radians
|
|
681
662
|
if d < r:
|
|
682
663
|
c, r = p, d
|
|
683
664
|
p1 = p2
|
|
@@ -775,13 +756,13 @@ class Nvector(NvectorBase):
|
|
|
775
756
|
|
|
776
757
|
def greatCircle(self, bearing):
|
|
777
758
|
'''Compute the n-vector normal to great circle obtained by
|
|
778
|
-
heading on given
|
|
759
|
+
heading on given (initial) bearing from this point as its
|
|
779
760
|
n-vector.
|
|
780
761
|
|
|
781
762
|
Direction of vector is such that initial bearing vector
|
|
782
763
|
b = c × p.
|
|
783
764
|
|
|
784
|
-
@arg bearing: Initial
|
|
765
|
+
@arg bearing: Initial bearing (compass C{degrees360}).
|
|
785
766
|
|
|
786
767
|
@return: N-vector representing great circle (C{Nvector}).
|
|
787
768
|
|
|
@@ -889,77 +870,54 @@ def intersecant2(center, circle, point, other, **radius_exact_height_wrap):
|
|
|
889
870
|
|
|
890
871
|
|
|
891
872
|
def intersection(start1, end1, start2, end2, height=None, wrap=False,
|
|
892
|
-
|
|
893
|
-
'''Locate
|
|
894
|
-
by two points or by a
|
|
873
|
+
**LatLon_and_kwds):
|
|
874
|
+
'''Locate an intersection point of two (great circle) lines each defined
|
|
875
|
+
by two points or by a point and an (initial) bearing.
|
|
895
876
|
|
|
896
|
-
@
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
@arg start2: Start point of the second line (L{LatLon}).
|
|
900
|
-
@arg end2: End point of the second line (L{LatLon}) or the initial
|
|
901
|
-
bearing at the second start point (compass C{degrees360}).
|
|
902
|
-
@kwarg height: Optional height at the intersection point,
|
|
903
|
-
overriding the mean height (C{meter}).
|
|
904
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{start2}}
|
|
905
|
-
and both B{C{end*}} points (C{bool}).
|
|
906
|
-
@kwarg LatLon: Optional class to return the intersection point
|
|
907
|
-
(L{LatLon}).
|
|
908
|
-
@kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword
|
|
909
|
-
arguments, ignored if C{B{LatLon} is None}.
|
|
910
|
-
|
|
911
|
-
@return: The intersection point (B{C{LatLon}}) or if C{B{LatLon}
|
|
912
|
-
is None}, a cartesian L{Ecef9Tuple}C{(x, y, z, lat, lon,
|
|
913
|
-
height, C, M, datum)} with C{C} and C{M} if available.
|
|
914
|
-
|
|
915
|
-
@raise TypeError: If B{C{start*}} or B{C{end*}} is not L{LatLon}.
|
|
916
|
-
|
|
917
|
-
@raise ValueError: Intersection is ambiguous or infinite or
|
|
918
|
-
the lines are parallel, coincident or null.
|
|
877
|
+
@return: The intersection point (L{LatLon}) or if C{B{LatLon}=None},
|
|
878
|
+
a cartesian L{Ecef9Tuple}C{(x, y, z, lat, lon, height, C, M,
|
|
879
|
+
datum)} with C{C} and C{M} if available.
|
|
919
880
|
|
|
920
|
-
@see: Function L{sphericalNvector.intersection2}
|
|
881
|
+
@see: Function L{intersection2<sphericalNvector.intersection2>}
|
|
882
|
+
for further details.
|
|
921
883
|
'''
|
|
922
884
|
i, _, h = _intersect3(start1, end1, start2, end2, height, wrap)
|
|
923
|
-
kwds = _xkwds(
|
|
885
|
+
kwds = _xkwds(LatLon_and_kwds, height=h, LatLon=LatLon)
|
|
924
886
|
return i.toLatLon(**kwds)
|
|
925
887
|
|
|
926
888
|
|
|
927
889
|
def intersection2(start1, end1, start2, end2, height=None, wrap=False,
|
|
928
|
-
|
|
929
|
-
'''Locate
|
|
930
|
-
by two points or by a
|
|
890
|
+
**LatLon_and_kwds):
|
|
891
|
+
'''Locate both intersections of two (great circle) lines each defined
|
|
892
|
+
by two points or by a point and an (initial) bearing.
|
|
931
893
|
|
|
932
894
|
@arg start1: Start point of the first line (L{LatLon}).
|
|
933
|
-
@arg end1: End point of the first line (L{LatLon}) or the
|
|
934
|
-
|
|
935
|
-
(compass C{degrees360}).
|
|
895
|
+
@arg end1: End point of the first line (L{LatLon}) or the bearing at
|
|
896
|
+
B{C{start1}} (compass C{degrees360}).
|
|
936
897
|
@arg start2: Start point of the second line (L{LatLon}).
|
|
937
|
-
@arg end2: End point of the second line (L{LatLon}) or the
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
or if C{B{LatLon} is None}, a cartesian L{Ecef9Tuple}C{(x,
|
|
951
|
-
y, z, lat, lon, height, C, M, datum)} with C{C} and C{M}
|
|
952
|
-
if available.
|
|
898
|
+
@arg end2: End point of the second line (L{LatLon}) or the bearing at
|
|
899
|
+
B{C{start2}} (compass C{degrees360}).
|
|
900
|
+
@kwarg height: Optional height at the intersection and antipodal point,
|
|
901
|
+
overriding the mean height (C{meter}).
|
|
902
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{start2}} and
|
|
903
|
+
both B{C{end*}} points (C{bool}).
|
|
904
|
+
@kwarg LatLon_and_kwds: Optional class C{B{LatLon}=}L{LatLon} to return
|
|
905
|
+
the intersection points and optionally, additional B{C{LatLon}}
|
|
906
|
+
keyword arguments, ignored if C{B{LatLon} is None}.
|
|
907
|
+
|
|
908
|
+
@return: 2-Tuple C{(intersection, antipode)}, each a (B{C{LatLon}}) or if
|
|
909
|
+
C{B{LatLon}=None}, a cartesian L{Ecef9Tuple}C{(x, y, z, lat, lon,
|
|
910
|
+
height, C, M, datum)} with C{C} and C{M} if available.
|
|
953
911
|
|
|
954
912
|
@raise TypeError: If B{C{start*}} or B{C{end*}} is not L{LatLon}.
|
|
955
913
|
|
|
956
|
-
@raise ValueError: Intersection is ambiguous or infinite or
|
|
957
|
-
|
|
914
|
+
@raise ValueError: Intersection is ambiguous or infinite or the lines are
|
|
915
|
+
parallel, coincident or null.
|
|
958
916
|
|
|
959
917
|
@see: Function L{sphericalNvector.intersection}.
|
|
960
918
|
'''
|
|
961
919
|
i, a, h = _intersect3(start1, end1, start2, end2, height, wrap)
|
|
962
|
-
kwds = _xkwds(
|
|
920
|
+
kwds = _xkwds(LatLon_and_kwds, height=h, LatLon=LatLon)
|
|
963
921
|
return i.toLatLon(**kwds), a.toLatLon(**kwds)
|
|
964
922
|
|
|
965
923
|
|
|
@@ -1022,21 +980,20 @@ def _intersect3(start1, end1, start2, end2, height, wrap):
|
|
|
1022
980
|
return (i1, i2, h) if d > 0 else (i2, i1, h)
|
|
1023
981
|
|
|
1024
982
|
|
|
1025
|
-
def meanOf(points, height=None, wrap=False,
|
|
983
|
+
def meanOf(points, height=None, wrap=False, **LatLon_and_kwds):
|
|
1026
984
|
'''Compute the I{geographic} mean of the supplied points.
|
|
1027
985
|
|
|
1028
986
|
@arg points: Array of points to be averaged (L{LatLon}[]).
|
|
1029
|
-
@kwarg height: Optional height, overriding the mean height
|
|
1030
|
-
(C{meter}).
|
|
987
|
+
@kwarg height: Optional height, overriding the mean height (C{meter}).
|
|
1031
988
|
@kwarg wrap: If C{True}, wrap or I{normalize} B{C{points}} (C{bool}).
|
|
1032
|
-
@kwarg
|
|
1033
|
-
|
|
1034
|
-
|
|
989
|
+
@kwarg LatLon_and_kwds: Optional class C{B{LatLon}=}L{LatLon} to return
|
|
990
|
+
the mean point and optionally, additional B{C{LatLon}}
|
|
991
|
+
keyword arguments, ignored if C{B{LatLon} is None}.
|
|
1035
992
|
|
|
1036
993
|
@return: Point at geographic mean and mean height (B{C{LatLon}}).
|
|
1037
994
|
|
|
1038
|
-
@raise PointsError: Insufficient number of B{C{points}} or
|
|
1039
|
-
|
|
995
|
+
@raise PointsError: Insufficient number of B{C{points}} or some
|
|
996
|
+
B{C{points}} are not C{LatLon}.
|
|
1040
997
|
'''
|
|
1041
998
|
def _N_vs(ps, w):
|
|
1042
999
|
Ps = _Nv00.PointsIter(ps, wrap=w)
|
|
@@ -1047,9 +1004,9 @@ def meanOf(points, height=None, wrap=False, LatLon=LatLon, **LatLon_kwds):
|
|
|
1047
1004
|
# geographic mean
|
|
1048
1005
|
n = _nsumOf(_N_vs(points, wrap), height, Nvector, {})
|
|
1049
1006
|
except (TypeError, ValueError) as x:
|
|
1050
|
-
raise PointsError(points=points, wrap=wrap,
|
|
1051
|
-
return n.toLatLon(**_xkwds(
|
|
1052
|
-
|
|
1007
|
+
raise PointsError(points=points, wrap=wrap, cause=x, **LatLon_and_kwds)
|
|
1008
|
+
return n.toLatLon(**_xkwds(LatLon_and_kwds, LatLon=LatLon, height=n.h,
|
|
1009
|
+
name=meanOf.__name__))
|
|
1053
1010
|
|
|
1054
1011
|
|
|
1055
1012
|
@deprecated_function
|
|
@@ -1164,8 +1121,8 @@ def sumOf(nvectors, Vector=Nvector, h=None, **Vector_kwds):
|
|
|
1164
1121
|
def triangulate(point1, bearing1, point2, bearing2,
|
|
1165
1122
|
height=None, wrap=False,
|
|
1166
1123
|
LatLon=LatLon, **LatLon_kwds):
|
|
1167
|
-
'''Locate a point given two known points and the (initial)
|
|
1168
|
-
from those points.
|
|
1124
|
+
'''Locate a point given two known, reference points and the (initial)
|
|
1125
|
+
bearing from those points.
|
|
1169
1126
|
|
|
1170
1127
|
@arg point1: First reference point (L{LatLon}).
|
|
1171
1128
|
@arg bearing1: Bearing at the first point (compass C{degrees360}).
|
|
@@ -24,7 +24,7 @@ from pygeodesy.datums import _ellipsoidal_datum, _mean_radius
|
|
|
24
24
|
from pygeodesy.errors import _AssertionError, CrossError, crosserrors, \
|
|
25
25
|
_TypeError, _ValueError, IntersectionError, \
|
|
26
26
|
_xError, _xkwds, _xkwds_get, _xkwds_pop2
|
|
27
|
-
from pygeodesy.fmath import favg, fdot, fmean, hypot
|
|
27
|
+
from pygeodesy.fmath import favg, fdot, fdot_, fmean, hypot
|
|
28
28
|
from pygeodesy.fsums import Fsum, fsum, fsumf_
|
|
29
29
|
from pygeodesy.formy import antipode_, bearing_, _bearingTo2, excessAbc_, \
|
|
30
30
|
excessGirard_, excessLHuilier_, opposing_, _radical2, \
|
|
@@ -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.
|
|
57
|
+
__version__ = '24.11.07'
|
|
58
58
|
|
|
59
59
|
_PI_EPS4 = PI - EPS4
|
|
60
60
|
if _PI_EPS4 >= PI:
|
|
@@ -182,8 +182,8 @@ class LatLon(LatLonSphericalBase):
|
|
|
182
182
|
return degrees180(m - d), degrees180(m + d)
|
|
183
183
|
|
|
184
184
|
def crossTrackDistanceTo(self, start, end, radius=R_M, wrap=False):
|
|
185
|
-
'''Compute the (signed) distance from this point to
|
|
186
|
-
|
|
185
|
+
'''Compute the (signed) distance from this point to a great
|
|
186
|
+
circle from a start to an end point.
|
|
187
187
|
|
|
188
188
|
@arg start: Start point of the great circle line (L{LatLon}).
|
|
189
189
|
@arg end: End point of the great circle line (L{LatLon}).
|
|
@@ -205,7 +205,7 @@ class LatLon(LatLonSphericalBase):
|
|
|
205
205
|
|
|
206
206
|
def destination(self, distance, bearing, radius=R_M, height=None):
|
|
207
207
|
'''Locate the destination from this point after having
|
|
208
|
-
travelled the given distance on
|
|
208
|
+
travelled the given distance on a bearing from North.
|
|
209
209
|
|
|
210
210
|
@arg distance: Distance travelled (C{meter}, same units as
|
|
211
211
|
B{C{radius}}).
|
|
@@ -253,7 +253,7 @@ class LatLon(LatLonSphericalBase):
|
|
|
253
253
|
|
|
254
254
|
def greatCircle(self, bearing, Vector=Vector3d, **Vector_kwds):
|
|
255
255
|
'''Compute the vector normal to great circle obtained by heading
|
|
256
|
-
on the
|
|
256
|
+
from this point on the bearing from North.
|
|
257
257
|
|
|
258
258
|
Direction of vector is such that initial bearing vector
|
|
259
259
|
b = c × n, where n is an n-vector representing this point.
|
|
@@ -271,8 +271,9 @@ class LatLon(LatLonSphericalBase):
|
|
|
271
271
|
a, b = self.philam
|
|
272
272
|
sa, ca, sb, cb, st, ct = sincos2_(a, b, Bearing_(bearing))
|
|
273
273
|
|
|
274
|
-
|
|
275
|
-
|
|
274
|
+
sa *= st
|
|
275
|
+
return Vector(fdot_(sb, ct, -cb, sa),
|
|
276
|
+
-fdot_(cb, ct, sb, sa),
|
|
276
277
|
ca * st, **Vector_kwds) # XXX .unit()?
|
|
277
278
|
|
|
278
279
|
def initialBearingTo(self, other, wrap=False, raiser=False):
|
|
@@ -341,9 +342,9 @@ class LatLon(LatLonSphericalBase):
|
|
|
341
342
|
a = sin(r - t) # / sr superflous
|
|
342
343
|
b = sin( t) # / sr superflous
|
|
343
344
|
|
|
344
|
-
x = a
|
|
345
|
-
y = a
|
|
346
|
-
z = a
|
|
345
|
+
x = fdot_(a, ca1 * cb1, b, ca2 * cb2)
|
|
346
|
+
y = fdot_(a, ca1 * sb1, b, ca2 * sb2)
|
|
347
|
+
z = fdot_(a, sa1, b, sa2)
|
|
347
348
|
|
|
348
349
|
a = atan1d(z, hypot(x, y))
|
|
349
350
|
b = atan2d(y, x)
|
|
@@ -358,7 +359,7 @@ class LatLon(LatLonSphericalBase):
|
|
|
358
359
|
|
|
359
360
|
def intersection(self, end1, other, end2, height=None, wrap=False):
|
|
360
361
|
'''Compute the intersection point of two lines, each defined by
|
|
361
|
-
two points or a start point and bearing from North.
|
|
362
|
+
two points or a start point and a bearing from North.
|
|
362
363
|
|
|
363
364
|
@arg end1: End point of this line (L{LatLon}) or the initial
|
|
364
365
|
bearing at this point (compass C{degrees360}).
|
|
@@ -395,7 +396,7 @@ class LatLon(LatLonSphericalBase):
|
|
|
395
396
|
def intersections2(self, rad1, other, rad2, radius=R_M, eps=_0_0,
|
|
396
397
|
height=None, wrap=True):
|
|
397
398
|
'''Compute the intersection points of two circles, each defined
|
|
398
|
-
by a center point and radius.
|
|
399
|
+
by a center point and a radius.
|
|
399
400
|
|
|
400
401
|
@arg rad1: Radius of the this circle (C{meter} or C{radians},
|
|
401
402
|
see B{C{radius}}).
|
|
@@ -536,7 +537,7 @@ class LatLon(LatLonSphericalBase):
|
|
|
536
537
|
return r
|
|
537
538
|
|
|
538
539
|
def nearestOn(self, point1, point2, radius=R_M, **wrap_adjust_limit):
|
|
539
|
-
'''Locate the point between two points closest to this point.
|
|
540
|
+
'''Locate the point between two other points closest to this point.
|
|
540
541
|
|
|
541
542
|
Distances are approximated by function L{pygeodesy.equirectangular4},
|
|
542
543
|
subject to the supplied B{C{options}}.
|
|
@@ -679,8 +680,8 @@ class LatLon(LatLonSphericalBase):
|
|
|
679
680
|
return self._xnamed(_t7Tuple(t, radius))
|
|
680
681
|
|
|
681
682
|
def triangulate(self, bearing1, other, bearing2, **height_wrap):
|
|
682
|
-
'''Locate a point given this, an other point and
|
|
683
|
-
|
|
683
|
+
'''Locate a point given this, an other point and a bearing from
|
|
684
|
+
North at both points.
|
|
684
685
|
|
|
685
686
|
@arg bearing1: Bearing at this point (compass C{degrees360}).
|
|
686
687
|
@arg other: The other point (C{LatLon}).
|
|
@@ -755,8 +756,8 @@ _T00 = LatLon(0, 0, name='T00') # reference instance (L{LatLon})
|
|
|
755
756
|
|
|
756
757
|
|
|
757
758
|
def areaOf(points, radius=R_M, wrap=False): # was=True
|
|
758
|
-
'''Calculate the area of a (spherical) polygon or composite
|
|
759
|
-
|
|
759
|
+
'''Calculate the area of a (spherical) polygon or composite (with the
|
|
760
|
+
points joined by great circle arcs).
|
|
760
761
|
|
|
761
762
|
@arg points: The polygon points or clips (L{LatLon}[], L{BooleanFHP}
|
|
762
763
|
or L{BooleanGH}).
|
|
@@ -868,8 +869,8 @@ def _int3d2(s, end, wrap, _i_, Vector, hs):
|
|
|
868
869
|
-(b1 + b2) * _0_5)
|
|
869
870
|
cb21 *= sin(a1 - a2) # sa21
|
|
870
871
|
sb21 *= sin(a1 + a2) # sa12
|
|
871
|
-
x = Vector(sb12
|
|
872
|
-
cb12
|
|
872
|
+
x = Vector(fdot_(sb12, cb21, -cb12, sb21),
|
|
873
|
+
fdot_(cb12, cb21, sb12, sb21),
|
|
873
874
|
cos(a1) * cos(a2) * sin(db)) # ll=start
|
|
874
875
|
return x.unit(), (db, (a2 - a1)) # negated d
|
|
875
876
|
|
|
@@ -882,7 +883,7 @@ def _intdot(ds, a1, b1, a, b, wrap):
|
|
|
882
883
|
|
|
883
884
|
def intersecant2(center, circle, point, other, **radius_exact_height_wrap):
|
|
884
885
|
'''Compute the intersections of a circle and a (great circle) line given as
|
|
885
|
-
two points or as a point and bearing.
|
|
886
|
+
two points or as a point and a bearing from North.
|
|
886
887
|
|
|
887
888
|
@arg center: Center of the circle (L{LatLon}).
|
|
888
889
|
@arg circle: Radius of the circle (C{meter}, same units as the earth
|
|
@@ -916,7 +917,7 @@ def intersecant2(center, circle, point, other, **radius_exact_height_wrap):
|
|
|
916
917
|
|
|
917
918
|
|
|
918
919
|
def _intersect(start1, end1, start2, end2, height=None, wrap=False, # in.ellipsoidalBaseDI._intersect3
|
|
919
|
-
LatLon=
|
|
920
|
+
LatLon=LatLon, **LatLon_kwds):
|
|
920
921
|
# (INTERNAL) Intersect two (spherical) lines, see L{intersection}
|
|
921
922
|
# above, separated to allow callers to embellish any exceptions
|
|
922
923
|
|
|
@@ -984,75 +985,68 @@ def _intersect(start1, end1, start2, end2, height=None, wrap=False, # in.ellips
|
|
|
984
985
|
|
|
985
986
|
|
|
986
987
|
def intersection(start1, end1, start2, end2, height=None, wrap=False,
|
|
987
|
-
|
|
988
|
-
'''Compute the intersection point of two lines, each defined
|
|
989
|
-
|
|
988
|
+
**LatLon_and_kwds):
|
|
989
|
+
'''Compute the intersection point of two lines, each defined by
|
|
990
|
+
two points or by a start point and a bearing from North.
|
|
990
991
|
|
|
991
992
|
@arg start1: Start point of the first line (L{LatLon}).
|
|
992
|
-
@arg end1: End point of the first line (L{LatLon}) or
|
|
993
|
-
|
|
994
|
-
(compass C{degrees360}).
|
|
993
|
+
@arg end1: End point of the first line (L{LatLon}) or the bearing
|
|
994
|
+
at the first start point (compass C{degrees360}).
|
|
995
995
|
@arg start2: Start point of the second line (L{LatLon}).
|
|
996
|
-
@arg end2: End point of the second line (L{LatLon}) or
|
|
997
|
-
|
|
998
|
-
(compass C{degrees360}).
|
|
996
|
+
@arg end2: End point of the second line (L{LatLon}) or the bearing
|
|
997
|
+
at the second start point (compass C{degrees360}).
|
|
999
998
|
@kwarg height: Optional height for the intersection point,
|
|
1000
999
|
overriding the mean height (C{meter}).
|
|
1001
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll
|
|
1002
|
-
|
|
1003
|
-
@kwarg
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1000
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{start2}}
|
|
1001
|
+
and both B{C{end*}} points (C{bool}).
|
|
1002
|
+
@kwarg LatLon_and_kwds: Optional class C{B{LatLon}=}L{LatLon} to use
|
|
1003
|
+
for the intersection point and optionally additional
|
|
1004
|
+
B{C{LatLon}} keyword arguments, ignored if C{B{LatLon}
|
|
1005
|
+
is None}.
|
|
1007
1006
|
|
|
1008
|
-
@return: The intersection point as a (B{C{LatLon}}) or if
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
be the L{antipode} to the returned result.
|
|
1007
|
+
@return: The intersection point as a (B{C{LatLon}}) or if C{B{LatLon}
|
|
1008
|
+
is None} a L{LatLon3Tuple}C{(lat, lon, height)}. An alternate
|
|
1009
|
+
intersection point might be the L{antipode} to the returned result.
|
|
1012
1010
|
|
|
1013
|
-
@raise IntersectionError: Ambiguous or infinite intersection
|
|
1014
|
-
|
|
1015
|
-
non-intersecting lines.
|
|
1011
|
+
@raise IntersectionError: Ambiguous or infinite intersection or colinear,
|
|
1012
|
+
parallel or otherwise non-intersecting lines.
|
|
1016
1013
|
|
|
1017
|
-
@raise TypeError: A B{C{start1}}, B{C{end1}}, B{C{start2}}
|
|
1018
|
-
|
|
1014
|
+
@raise TypeError: A B{C{start1}}, B{C{end1}}, B{C{start2}} or B{C{end2}}
|
|
1015
|
+
point not L{LatLon}.
|
|
1019
1016
|
|
|
1020
1017
|
@raise ValueError: Invalid B{C{height}} or C{null} line.
|
|
1021
1018
|
'''
|
|
1022
1019
|
s1 = _T00.others(start1=start1)
|
|
1023
1020
|
s2 = _T00.others(start2=start2)
|
|
1024
1021
|
try:
|
|
1025
|
-
return _intersect(s1, end1, s2, end2, height=height, wrap=wrap,
|
|
1026
|
-
LatLon=LatLon, **LatLon_kwds)
|
|
1022
|
+
return _intersect(s1, end1, s2, end2, height=height, wrap=wrap, **LatLon_and_kwds)
|
|
1027
1023
|
except (TypeError, ValueError) as x:
|
|
1028
1024
|
raise _xError(x, start1=start1, end1=end1, start2=start2, end2=end2)
|
|
1029
1025
|
|
|
1030
1026
|
|
|
1031
1027
|
def intersections2(center1, rad1, center2, rad2, radius=R_M, eps=_0_0,
|
|
1032
1028
|
height=None, wrap=False, # was=True
|
|
1033
|
-
|
|
1034
|
-
'''Compute the intersection points of two circles each defined
|
|
1035
|
-
|
|
1029
|
+
**LatLon_and_kwds):
|
|
1030
|
+
'''Compute the intersection points of two circles each defined by a
|
|
1031
|
+
center point and a radius.
|
|
1036
1032
|
|
|
1037
1033
|
@arg center1: Center of the first circle (L{LatLon}).
|
|
1038
|
-
@arg rad1: Radius of the first circle (C{meter} or C{radians},
|
|
1039
|
-
|
|
1034
|
+
@arg rad1: Radius of the first circle (C{meter} or C{radians}, see
|
|
1035
|
+
B{C{radius}}).
|
|
1040
1036
|
@arg center2: Center of the second circle (L{LatLon}).
|
|
1041
|
-
@arg rad2: Radius of the second circle (C{meter} or C{radians},
|
|
1042
|
-
|
|
1037
|
+
@arg rad2: Radius of the second circle (C{meter} or C{radians}, see
|
|
1038
|
+
B{C{radius}}).
|
|
1043
1039
|
@kwarg radius: Mean earth radius (C{meter} or C{None} if B{C{rad1}},
|
|
1044
1040
|
B{C{rad2}} and B{C{eps}} are given in C{radians}).
|
|
1045
|
-
@kwarg eps: Required overlap (C{meter} or C{radians}, see
|
|
1046
|
-
B{C{radius}}).
|
|
1041
|
+
@kwarg eps: Required overlap (C{meter} or C{radians}, see B{C{radius}}).
|
|
1047
1042
|
@kwarg height: Optional height for the intersection points (C{meter},
|
|
1048
1043
|
conventionally) or C{None} for the I{"radical height"}
|
|
1049
1044
|
at the I{radical line} between both centers.
|
|
1050
1045
|
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{center2}}
|
|
1051
1046
|
(C{bool}).
|
|
1052
|
-
@kwarg
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
arguments, ignored if C{B{LatLon} is None}.
|
|
1047
|
+
@kwarg LatLon_and_kwds: Optional class C{B{LatLon}=}L{LatLon} to use for
|
|
1048
|
+
the intersection points and optionally additional B{C{LatLon}}
|
|
1049
|
+
keyword arguments, ignored if C{B{LatLon} is None}.
|
|
1056
1050
|
|
|
1057
1051
|
@return: 2-Tuple of the intersection points, each a B{C{LatLon}}
|
|
1058
1052
|
instance or if C{B{LatLon} is None} a L{LatLon3Tuple}C{(lat,
|
|
@@ -1077,7 +1071,7 @@ def intersections2(center1, rad1, center2, rad2, radius=R_M, eps=_0_0,
|
|
|
1077
1071
|
try:
|
|
1078
1072
|
return _intersects2(c1, rad1, c2, rad2, radius=radius, eps=eps,
|
|
1079
1073
|
height=height, wrap=wrap,
|
|
1080
|
-
|
|
1074
|
+
**LatLon_and_kwds)
|
|
1081
1075
|
except (TypeError, ValueError) as x:
|
|
1082
1076
|
raise _xError(x, center1=center1, rad1=rad1,
|
|
1083
1077
|
center2=center2, rad2=rad2, wrap=wrap)
|
|
@@ -1226,7 +1220,7 @@ def nearestOn3(point, points, closed=False, radius=R_M, wrap=False, adjust=True,
|
|
|
1226
1220
|
(C{degrees}), default C{9 degrees} is about C{1,000 Km} (for
|
|
1227
1221
|
(mean spherical earth radius L{R_KM}).
|
|
1228
1222
|
@kwarg LatLon_and_kwds: Optional class C{B{LatLon}=L{LatLon}} to return the
|
|
1229
|
-
closest point and
|
|
1223
|
+
closest point and optionally additional C{B{LatLon}} keyword
|
|
1230
1224
|
arguments or specify C{B{LatLon}=None}.
|
|
1231
1225
|
|
|
1232
1226
|
@return: A L{NearestOn3Tuple}C{(closest, distance, angle)} with the
|
|
@@ -1331,9 +1325,9 @@ def triangle7(latA, lonA, latB, lonB, latC, lonC, radius=R_M,
|
|
|
1331
1325
|
C{a}, C{b} and C{c} all in C{degrees} and C{area}
|
|
1332
1326
|
in I{square} C{meter} or same units as B{C{radius}}
|
|
1333
1327
|
I{squared} or if C{B{radius}=0} or C{None}, a
|
|
1334
|
-
L{Triangle8Tuple}C{(A, a, B, b, C, c, D, E)}
|
|
1335
|
-
C{
|
|
1336
|
-
C{unit area} in C{radians}.
|
|
1328
|
+
L{Triangle8Tuple}C{(A, a, B, b, C, c, D, E)} with
|
|
1329
|
+
I{spherical deficit} C{D} and I{spherical excess}
|
|
1330
|
+
C{E} as the C{unit area}, all in C{radians}.
|
|
1337
1331
|
'''
|
|
1338
1332
|
t = triangle8_(Phid(latA=latA), Lamd(lonA=lonA),
|
|
1339
1333
|
Phid(latB=latB), Lamd(lonB=lonB),
|