pygeodesy 24.10.10__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.10.dist-info → PyGeodesy-24.11.11.dist-info}/METADATA +12 -12
- PyGeodesy-24.11.11.dist-info/RECORD +118 -0
- {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/WHEEL +1 -1
- pygeodesy/__init__.py +14 -14
- pygeodesy/__main__.py +5 -5
- pygeodesy/albers.py +12 -17
- pygeodesy/azimuthal.py +51 -61
- pygeodesy/basics.py +60 -62
- pygeodesy/booleans.py +87 -79
- pygeodesy/cartesianBase.py +6 -6
- pygeodesy/constants.py +23 -19
- pygeodesy/css.py +7 -8
- pygeodesy/datums.py +3 -3
- pygeodesy/deprecated/__init__.py +1 -1
- pygeodesy/deprecated/classes.py +9 -9
- pygeodesy/deprecated/functions.py +6 -6
- pygeodesy/dms.py +250 -270
- pygeodesy/ecef.py +11 -14
- pygeodesy/ellipsoidalBase.py +106 -121
- pygeodesy/ellipsoidalBaseDI.py +114 -118
- pygeodesy/ellipsoidalExact.py +35 -37
- pygeodesy/ellipsoidalNvector.py +4 -4
- pygeodesy/ellipsoidalVincenty.py +2 -2
- pygeodesy/ellipsoids.py +10 -51
- pygeodesy/elliptic.py +14 -14
- pygeodesy/errors.py +28 -28
- pygeodesy/etm.py +92 -68
- pygeodesy/fmath.py +42 -40
- pygeodesy/formy.py +7 -6
- pygeodesy/fsums.py +72 -51
- pygeodesy/geodesici.py +43 -40
- pygeodesy/geodesicw.py +17 -16
- pygeodesy/geodesicx/__init__.py +2 -2
- pygeodesy/geodesicx/gxarea.py +3 -2
- pygeodesy/geodsolve.py +79 -39
- pygeodesy/geohash.py +2 -2
- pygeodesy/geoids.py +32 -31
- pygeodesy/heights.py +2 -2
- pygeodesy/internals.py +201 -147
- pygeodesy/interns.py +23 -20
- pygeodesy/karney.py +62 -13
- pygeodesy/ktm.py +11 -13
- pygeodesy/latlonBase.py +18 -20
- pygeodesy/lazily.py +210 -218
- pygeodesy/lcc.py +4 -4
- pygeodesy/ltp.py +10 -10
- pygeodesy/ltpTuples.py +74 -75
- pygeodesy/mgrs.py +20 -21
- pygeodesy/named.py +15 -10
- pygeodesy/nvectorBase.py +1 -1
- pygeodesy/osgr.py +9 -12
- pygeodesy/points.py +2 -2
- pygeodesy/props.py +35 -14
- pygeodesy/resections.py +9 -10
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/bases.py +5 -5
- pygeodesy/rhumb/solve.py +9 -10
- pygeodesy/simplify.py +5 -5
- pygeodesy/solveBase.py +7 -25
- pygeodesy/sphericalBase.py +20 -23
- pygeodesy/sphericalNvector.py +103 -145
- pygeodesy/sphericalTrigonometry.py +68 -73
- pygeodesy/streprs.py +5 -5
- pygeodesy/trf.py +6 -4
- pygeodesy/triaxials.py +46 -9
- pygeodesy/units.py +5 -4
- pygeodesy/ups.py +6 -6
- pygeodesy/utily.py +2 -2
- pygeodesy/utm.py +7 -7
- pygeodesy/vector2d.py +13 -13
- pygeodesy/vector3d.py +19 -21
- pygeodesy/vector3dBase.py +21 -19
- pygeodesy/webmercator.py +4 -4
- pygeodesy/wgrs.py +4 -4
- PyGeodesy-24.10.10.dist-info/RECORD +0 -118
- {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/top_level.txt +0 -0
pygeodesy/sphericalNvector.py
CHANGED
|
@@ -9,7 +9,7 @@ L{meanOf}, L{nearestOn3}, L{perimeterOf}, L{sumOf}, L{triangulate} and
|
|
|
9
9
|
L{trilaterate}, I{all spherical}.
|
|
10
10
|
|
|
11
11
|
Pure Python implementation of n-vector-based spherical geodetic (lat-/longitude)
|
|
12
|
-
methods, transcoded from JavaScript originals by I{(C) Chris Veness 2011-
|
|
12
|
+
methods, transcoded from JavaScript originals by I{(C) Chris Veness 2011-2024},
|
|
13
13
|
published under the same MIT Licence**. See U{Vector-based geodesy
|
|
14
14
|
<https://www.Movable-Type.co.UK/scripts/latlong-vectors.html>} and
|
|
15
15
|
U{Module latlon-nvector-spherical
|
|
@@ -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
|
|
|
@@ -797,7 +778,7 @@ class Nvector(NvectorBase):
|
|
|
797
778
|
return n.minus(e)
|
|
798
779
|
|
|
799
780
|
|
|
800
|
-
|
|
781
|
+
_Nv00 = LatLon(_0_0, _0_0, name=_Nv00_) # reference instance (L{LatLon})
|
|
801
782
|
|
|
802
783
|
|
|
803
784
|
def areaOf(points, radius=R_M, wrap=False):
|
|
@@ -821,7 +802,7 @@ def areaOf(points, radius=R_M, wrap=False):
|
|
|
821
802
|
and L{ellipsoidalKarney.areaOf}.
|
|
822
803
|
'''
|
|
823
804
|
def _interangles(ps, w): # like .karney._polygon
|
|
824
|
-
Ps =
|
|
805
|
+
Ps = _Nv00.PointsIter(ps, loop=2, wrap=w)
|
|
825
806
|
# use vector to 1st point as plane normal for sign of α
|
|
826
807
|
n0 = Ps[0].toNvector()
|
|
827
808
|
|
|
@@ -858,13 +839,14 @@ def intersecant2(center, circle, point, other, **radius_exact_height_wrap):
|
|
|
858
839
|
two points or as a point and bearing.
|
|
859
840
|
|
|
860
841
|
@arg center: Center of the circle (L{LatLon}).
|
|
861
|
-
@arg circle: Radius of the circle (C{meter}, same units as
|
|
862
|
-
or a point on the circle (L{LatLon}).
|
|
842
|
+
@arg circle: Radius of the circle (C{meter}, same units as the earth
|
|
843
|
+
B{C{radius}}) or a point on the circle (L{LatLon}).
|
|
863
844
|
@arg point: A point on the (great circle) line (L{LatLon}).
|
|
864
845
|
@arg other: An other point on the (great circle) line (L{LatLon}) or
|
|
865
846
|
the bearing at the B{C{point}} (compass C{degrees360}).
|
|
866
|
-
@kwarg radius_exact_height_wrap: Optional keyword arguments, see
|
|
867
|
-
|
|
847
|
+
@kwarg radius_exact_height_wrap: Optional keyword arguments, see method
|
|
848
|
+
L{intersecant2<pygeodesy.sphericalBase.LatLonSphericalBase.
|
|
849
|
+
intersecant2>} for further details.
|
|
868
850
|
|
|
869
851
|
@return: 2-Tuple of the intersection points (representing a chord), each
|
|
870
852
|
an instance of the B{C{point}} class. Both points are the same
|
|
@@ -872,14 +854,14 @@ def intersecant2(center, circle, point, other, **radius_exact_height_wrap):
|
|
|
872
854
|
|
|
873
855
|
@raise IntersectionError: The circle and line do not intersect.
|
|
874
856
|
|
|
875
|
-
@raise TypeError: If B{C{center}}
|
|
876
|
-
|
|
857
|
+
@raise TypeError: If B{C{center}}, B{C{point}}, B{C{circle}} or B{C{other}}
|
|
858
|
+
not L{LatLon}.
|
|
877
859
|
|
|
878
860
|
@raise UnitError: Invalid B{C{circle}}, B{C{other}}, B{C{radius}},
|
|
879
861
|
B{C{exact}}, B{C{height}} or B{C{napieradius}}.
|
|
880
862
|
'''
|
|
881
|
-
c =
|
|
882
|
-
p =
|
|
863
|
+
c = _Nv00.others(center=center)
|
|
864
|
+
p = _Nv00.others(point=point)
|
|
883
865
|
try:
|
|
884
866
|
return _intersecant2(c, circle, p, other, **radius_exact_height_wrap)
|
|
885
867
|
except (TypeError, ValueError) as x:
|
|
@@ -888,77 +870,54 @@ def intersecant2(center, circle, point, other, **radius_exact_height_wrap):
|
|
|
888
870
|
|
|
889
871
|
|
|
890
872
|
def intersection(start1, end1, start2, end2, height=None, wrap=False,
|
|
891
|
-
|
|
892
|
-
'''Locate
|
|
893
|
-
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.
|
|
894
876
|
|
|
895
|
-
@
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
@arg start2: Start point of the second line (L{LatLon}).
|
|
899
|
-
@arg end2: End point of the second line (L{LatLon}) or the initial
|
|
900
|
-
bearing at the second start point (compass C{degrees360}).
|
|
901
|
-
@kwarg height: Optional height at the intersection point,
|
|
902
|
-
overriding the mean height (C{meter}).
|
|
903
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{start2}}
|
|
904
|
-
and both B{C{end*}} points (C{bool}).
|
|
905
|
-
@kwarg LatLon: Optional class to return the intersection point
|
|
906
|
-
(L{LatLon}).
|
|
907
|
-
@kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword
|
|
908
|
-
arguments, ignored if C{B{LatLon} is None}.
|
|
909
|
-
|
|
910
|
-
@return: The intersection point (B{C{LatLon}}) or if C{B{LatLon}
|
|
911
|
-
is None}, a cartesian L{Ecef9Tuple}C{(x, y, z, lat, lon,
|
|
912
|
-
height, C, M, datum)} with C{C} and C{M} if available.
|
|
913
|
-
|
|
914
|
-
@raise TypeError: If B{C{start*}} or B{C{end*}} is not L{LatLon}.
|
|
915
|
-
|
|
916
|
-
@raise ValueError: Intersection is ambiguous or infinite or
|
|
917
|
-
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.
|
|
918
880
|
|
|
919
|
-
@see: Function L{sphericalNvector.intersection2}
|
|
881
|
+
@see: Function L{intersection2<sphericalNvector.intersection2>}
|
|
882
|
+
for further details.
|
|
920
883
|
'''
|
|
921
884
|
i, _, h = _intersect3(start1, end1, start2, end2, height, wrap)
|
|
922
|
-
kwds = _xkwds(
|
|
885
|
+
kwds = _xkwds(LatLon_and_kwds, height=h, LatLon=LatLon)
|
|
923
886
|
return i.toLatLon(**kwds)
|
|
924
887
|
|
|
925
888
|
|
|
926
889
|
def intersection2(start1, end1, start2, end2, height=None, wrap=False,
|
|
927
|
-
|
|
928
|
-
'''Locate
|
|
929
|
-
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.
|
|
930
893
|
|
|
931
894
|
@arg start1: Start point of the first line (L{LatLon}).
|
|
932
|
-
@arg end1: End point of the first line (L{LatLon}) or the
|
|
933
|
-
|
|
934
|
-
(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}).
|
|
935
897
|
@arg start2: Start point of the second line (L{LatLon}).
|
|
936
|
-
@arg end2: End point of the second line (L{LatLon}) or the
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
or if C{B{LatLon} is None}, a cartesian L{Ecef9Tuple}C{(x,
|
|
950
|
-
y, z, lat, lon, height, C, M, datum)} with C{C} and C{M}
|
|
951
|
-
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.
|
|
952
911
|
|
|
953
912
|
@raise TypeError: If B{C{start*}} or B{C{end*}} is not L{LatLon}.
|
|
954
913
|
|
|
955
|
-
@raise ValueError: Intersection is ambiguous or infinite or
|
|
956
|
-
|
|
914
|
+
@raise ValueError: Intersection is ambiguous or infinite or the lines are
|
|
915
|
+
parallel, coincident or null.
|
|
957
916
|
|
|
958
917
|
@see: Function L{sphericalNvector.intersection}.
|
|
959
918
|
'''
|
|
960
919
|
i, a, h = _intersect3(start1, end1, start2, end2, height, wrap)
|
|
961
|
-
kwds = _xkwds(
|
|
920
|
+
kwds = _xkwds(LatLon_and_kwds, height=h, LatLon=LatLon)
|
|
962
921
|
return i.toLatLon(**kwds), a.toLatLon(**kwds)
|
|
963
922
|
|
|
964
923
|
|
|
@@ -966,8 +925,8 @@ def _intersect3(start1, end1, start2, end2, height, wrap):
|
|
|
966
925
|
'''(INTERNAL) Return the intersection and antipodal points for
|
|
967
926
|
functions C{intersection} and C{intersection2}.
|
|
968
927
|
'''
|
|
969
|
-
p1 =
|
|
970
|
-
p2 =
|
|
928
|
+
p1 = _Nv00.others(start1=start1)
|
|
929
|
+
p2 = _Nv00.others(start2=start2)
|
|
971
930
|
if wrap:
|
|
972
931
|
p2 = _unrollon(p1, p2, wrap=wrap)
|
|
973
932
|
# If gc1 and gc2 are great circles through start and end points
|
|
@@ -976,8 +935,8 @@ def _intersect3(start1, end1, start2, end2, height, wrap):
|
|
|
976
935
|
# work is deciding the correct intersection point to select! If
|
|
977
936
|
# bearing is given, that determines the intersection, but if both
|
|
978
937
|
# lines are defined by start/end points, take closer intersection.
|
|
979
|
-
gc1, s1, e1 =
|
|
980
|
-
gc2, s2, e2 =
|
|
938
|
+
gc1, s1, e1 = _Nv00._gc3(p1, end1, 'end1', wrap=wrap)
|
|
939
|
+
gc2, s2, e2 = _Nv00._gc3(p2, end2, 'end2', wrap=wrap)
|
|
981
940
|
|
|
982
941
|
hs = start1.height, start2.height
|
|
983
942
|
# there are two (antipodal) candidate intersection
|
|
@@ -1021,24 +980,23 @@ def _intersect3(start1, end1, start2, end2, height, wrap):
|
|
|
1021
980
|
return (i1, i2, h) if d > 0 else (i2, i1, h)
|
|
1022
981
|
|
|
1023
982
|
|
|
1024
|
-
def meanOf(points, height=None, wrap=False,
|
|
983
|
+
def meanOf(points, height=None, wrap=False, **LatLon_and_kwds):
|
|
1025
984
|
'''Compute the I{geographic} mean of the supplied points.
|
|
1026
985
|
|
|
1027
986
|
@arg points: Array of points to be averaged (L{LatLon}[]).
|
|
1028
|
-
@kwarg height: Optional height, overriding the mean height
|
|
1029
|
-
(C{meter}).
|
|
987
|
+
@kwarg height: Optional height, overriding the mean height (C{meter}).
|
|
1030
988
|
@kwarg wrap: If C{True}, wrap or I{normalize} B{C{points}} (C{bool}).
|
|
1031
|
-
@kwarg
|
|
1032
|
-
|
|
1033
|
-
|
|
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}.
|
|
1034
992
|
|
|
1035
993
|
@return: Point at geographic mean and mean height (B{C{LatLon}}).
|
|
1036
994
|
|
|
1037
|
-
@raise PointsError: Insufficient number of B{C{points}} or
|
|
1038
|
-
|
|
995
|
+
@raise PointsError: Insufficient number of B{C{points}} or some
|
|
996
|
+
B{C{points}} are not C{LatLon}.
|
|
1039
997
|
'''
|
|
1040
998
|
def _N_vs(ps, w):
|
|
1041
|
-
Ps =
|
|
999
|
+
Ps = _Nv00.PointsIter(ps, wrap=w)
|
|
1042
1000
|
for p in Ps.iterate(closed=False):
|
|
1043
1001
|
yield p._N_vector
|
|
1044
1002
|
|
|
@@ -1046,9 +1004,9 @@ def meanOf(points, height=None, wrap=False, LatLon=LatLon, **LatLon_kwds):
|
|
|
1046
1004
|
# geographic mean
|
|
1047
1005
|
n = _nsumOf(_N_vs(points, wrap), height, Nvector, {})
|
|
1048
1006
|
except (TypeError, ValueError) as x:
|
|
1049
|
-
raise PointsError(points=points, wrap=wrap,
|
|
1050
|
-
return n.toLatLon(**_xkwds(
|
|
1051
|
-
|
|
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__))
|
|
1052
1010
|
|
|
1053
1011
|
|
|
1054
1012
|
@deprecated_function
|
|
@@ -1122,7 +1080,7 @@ def perimeterOf(points, closed=False, radius=R_M, wrap=False):
|
|
|
1122
1080
|
and L{sphericalTrigonometry.perimeterOf}.
|
|
1123
1081
|
'''
|
|
1124
1082
|
def _rads(ps, c, w): # angular edge lengths in radians
|
|
1125
|
-
Ps =
|
|
1083
|
+
Ps = _Nv00.PointsIter(ps, loop=1, wrap=w)
|
|
1126
1084
|
p1 = Ps[0]
|
|
1127
1085
|
v1 = p1._N_vector
|
|
1128
1086
|
for p2 in Ps.iterate(closed=c):
|
|
@@ -1163,8 +1121,8 @@ def sumOf(nvectors, Vector=Nvector, h=None, **Vector_kwds):
|
|
|
1163
1121
|
def triangulate(point1, bearing1, point2, bearing2,
|
|
1164
1122
|
height=None, wrap=False,
|
|
1165
1123
|
LatLon=LatLon, **LatLon_kwds):
|
|
1166
|
-
'''Locate a point given two known points and the (initial)
|
|
1167
|
-
from those points.
|
|
1124
|
+
'''Locate a point given two known, reference points and the (initial)
|
|
1125
|
+
bearing from those points.
|
|
1168
1126
|
|
|
1169
1127
|
@arg point1: First reference point (L{LatLon}).
|
|
1170
1128
|
@arg bearing1: Bearing at the first point (compass C{degrees360}).
|
|
@@ -1184,8 +1142,8 @@ def triangulate(point1, bearing1, point2, bearing2,
|
|
|
1184
1142
|
|
|
1185
1143
|
@raise Valuerror: Points coincide.
|
|
1186
1144
|
'''
|
|
1187
|
-
return _triangulate(
|
|
1188
|
-
|
|
1145
|
+
return _triangulate(_Nv00.others(point1=point1), bearing1,
|
|
1146
|
+
_Nv00.others(point2=point2), bearing2,
|
|
1189
1147
|
height=height, wrap=wrap,
|
|
1190
1148
|
LatLon=LatLon, **LatLon_kwds)
|
|
1191
1149
|
|
|
@@ -1225,9 +1183,9 @@ def trilaterate(point1, distance1, point2, distance2, point3, distance3, # PYCH
|
|
|
1225
1183
|
|
|
1226
1184
|
@see: U{Trilateration<https://WikiPedia.org/wiki/Trilateration>}.
|
|
1227
1185
|
'''
|
|
1228
|
-
return _trilaterate(
|
|
1229
|
-
|
|
1230
|
-
|
|
1186
|
+
return _trilaterate(_Nv00.others(point1=point1), distance1,
|
|
1187
|
+
_Nv00.others(point2=point2), distance2,
|
|
1188
|
+
_Nv00.others(point3=point3), distance3,
|
|
1231
1189
|
radius=radius, height=height, useZ=useZ,
|
|
1232
1190
|
wrap=wrap, LatLon=LatLon, **LatLon_kwds)
|
|
1233
1191
|
|