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.
Files changed (54) hide show
  1. {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/METADATA +4 -4
  2. {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/RECORD +54 -54
  3. {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/WHEEL +1 -1
  4. pygeodesy/__init__.py +2 -2
  5. pygeodesy/azimuthal.py +51 -61
  6. pygeodesy/basics.py +34 -33
  7. pygeodesy/booleans.py +36 -36
  8. pygeodesy/cartesianBase.py +5 -5
  9. pygeodesy/constants.py +4 -4
  10. pygeodesy/css.py +7 -8
  11. pygeodesy/deprecated/__init__.py +1 -1
  12. pygeodesy/deprecated/classes.py +9 -9
  13. pygeodesy/deprecated/functions.py +6 -6
  14. pygeodesy/ecef.py +11 -14
  15. pygeodesy/ellipsoidalBase.py +105 -120
  16. pygeodesy/ellipsoidalBaseDI.py +114 -118
  17. pygeodesy/ellipsoidalExact.py +35 -37
  18. pygeodesy/ellipsoids.py +3 -3
  19. pygeodesy/errors.py +24 -24
  20. pygeodesy/etm.py +80 -72
  21. pygeodesy/fmath.py +39 -37
  22. pygeodesy/formy.py +3 -2
  23. pygeodesy/fsums.py +51 -40
  24. pygeodesy/geodesicw.py +15 -14
  25. pygeodesy/geodesicx/__init__.py +2 -2
  26. pygeodesy/geodsolve.py +7 -16
  27. pygeodesy/geoids.py +5 -5
  28. pygeodesy/heights.py +2 -2
  29. pygeodesy/internals.py +63 -79
  30. pygeodesy/karney.py +2 -2
  31. pygeodesy/ktm.py +11 -13
  32. pygeodesy/latlonBase.py +6 -6
  33. pygeodesy/lazily.py +5 -5
  34. pygeodesy/lcc.py +4 -4
  35. pygeodesy/ltp.py +10 -10
  36. pygeodesy/ltpTuples.py +74 -75
  37. pygeodesy/mgrs.py +9 -10
  38. pygeodesy/named.py +4 -0
  39. pygeodesy/osgr.py +9 -12
  40. pygeodesy/props.py +2 -2
  41. pygeodesy/resections.py +9 -10
  42. pygeodesy/rhumb/__init__.py +1 -1
  43. pygeodesy/rhumb/solve.py +3 -3
  44. pygeodesy/simplify.py +5 -5
  45. pygeodesy/sphericalNvector.py +80 -123
  46. pygeodesy/sphericalTrigonometry.py +60 -66
  47. pygeodesy/units.py +2 -2
  48. pygeodesy/utm.py +6 -6
  49. pygeodesy/vector2d.py +13 -13
  50. pygeodesy/vector3d.py +19 -21
  51. pygeodesy/vector3dBase.py +18 -15
  52. pygeodesy/webmercator.py +4 -4
  53. pygeodesy/wgrs.py +4 -4
  54. {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/top_level.txt +0 -0
@@ -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.10.19'
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
- return Nvector(sb * ct - sa * cb * st,
277
- -cb * ct - sa * sb * st,
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 the intersection point of two lines each defined
395
- by two points or a start point and bearing from North.
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
- @raise TypeError: If B{C{start2}}, B{C{end1}} or B{C{end2}}
411
- point is not L{LatLon}.
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 the intersections of two (great circle) lines each defined
424
- by two points or by a start point and an (initial) bearing.
425
-
426
- @arg end1: End point of the first line (L{LatLon}) or the
427
- initial bearing at this point (compass C{degrees360}).
428
- @arg start2: Start point of the second line (L{LatLon}).
429
- @arg end2: End point of the second line (L{LatLon}) or the
430
- initial bearing at the second start point (compass
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} and method
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 _subtangles(ps, w):
476
- Ps = self.PointsIter(ps, loop=1, wrap=w)
477
- n0 = self.toNvector()
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 = p2
485
- vs2 = _m0(p2.toNvector())
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(_subtangles(points, wrap)) # normal vector
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
- arcs joining consecutive points) closest to this point.
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
- the B{C{points}} (C{bool}).
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
- _r = self.distanceTo
652
+ _d = self.distanceTo
672
653
  _n = self.nearestOn
673
654
 
674
655
  c = p1 = Ps[0]
675
- r = _r(c, radius=None) # radians
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 = _r(p, radius=None) # radians
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 compass bearing from this point as its
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 compass bearing (C{degrees}).
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
- LatLon=LatLon, **LatLon_kwds):
893
- '''Locate the intersections of two (great circle) lines each defined
894
- by two points or by a start point and an (initial) bearing.
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
- @arg start1: Start point of the first line (L{LatLon}).
897
- @arg end1: End point of the first line (L{LatLon}) or the initial
898
- bearing at the first start point (compass C{degrees360}).
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(LatLon_kwds, height=h, LatLon=LatLon)
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
- LatLon=LatLon, **LatLon_kwds):
929
- '''Locate the intersections of two (great circle) lines each defined
930
- by two points or by a start point and an (initial) bearing.
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
- initial bearing at the first start point
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
- initial bearing at the second start point
939
- (compass C{degrees360}).
940
- @kwarg height: Optional height at the intersection and antipodal
941
- point, overriding the mean height (C{meter}).
942
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{start2}}
943
- and both B{C{end*}} points (C{bool}).
944
- @kwarg LatLon: Optional class to return the intersection and
945
- antipodal points (L{LatLon}).
946
- @kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword
947
- arguments, ignored if C{B{LatLon} is None}.
948
-
949
- @return: 2-Tuple C{(intersection, antipode)}, each a (B{C{LatLon}})
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
- the lines are parallel, coincident or null.
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(LatLon_kwds, height=h, LatLon=LatLon)
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, LatLon=LatLon, **LatLon_kwds):
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 LatLon: Optional class to return the mean point (L{LatLon}).
1033
- @kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword
1034
- arguments, ignored if C{B{LatLon} is None}.
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
- some B{C{points}} are not C{LatLon}.
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, LatLon=LatLon, cause=x)
1051
- return n.toLatLon(**_xkwds(LatLon_kwds, LatLon=LatLon, height=n.h,
1052
- name=meanOf.__name__))
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) bearing
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.10.12'
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
- the great circle defined by a start and an end point.
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 the given initial bearing.
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 given initial bearing from this point.
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
- return Vector(sb * ct - cb * sa * st,
275
- -cb * ct - sb * sa * st,
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 * ca1 * cb1 + b * ca2 * cb2
345
- y = a * ca1 * sb1 + b * ca2 * sb2
346
- z = a * sa1 + b * sa2
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 the (initial) bearing
683
- at this and at the other point.
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
- (with the pointsjoined by great circle arcs).
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 * cb21 - cb12 * sb21,
872
- cb12 * cb21 + sb12 * sb21,
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=None, **LatLon_kwds):
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
- LatLon=LatLon, **LatLon_kwds):
988
- '''Compute the intersection point of two lines, each defined
989
- by two points or a start point and bearing from North.
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
- the initial bearing at the first start point
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
- the initial bearing at the second start point
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
- B{C{start2}} and both B{C{end*}} points (C{bool}).
1003
- @kwarg LatLon: Optional class to return the intersection
1004
- point (L{LatLon}) or C{None}.
1005
- @kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword
1006
- arguments, ignored if C{B{LatLon} is None}.
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
- C{B{LatLon} is None} a L{LatLon3Tuple}C{(lat, lon,
1010
- height)}. An alternate intersection point might
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
- or colinear, parallel or otherwise
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
- or B{C{end2}} point not L{LatLon}.
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
- LatLon=LatLon, **LatLon_kwds):
1034
- '''Compute the intersection points of two circles each defined
1035
- by a center point and a radius.
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
- see B{C{radius}}).
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
- see B{C{radius}}).
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 LatLon: Optional class to return the intersection
1053
- points (L{LatLon}) or C{None}.
1054
- @kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword
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
- LatLon=LatLon, **LatLon_kwds)
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 optional, additional C{B{LatLon}} keyword
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)} all in
1335
- C{radians} with the I{spherical excess} C{E} as the
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),