pygeodesy 25.5.28__py2.py3-none-any.whl → 25.8.25__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.
@@ -46,7 +46,7 @@ from pygeodesy.units import Epoch, _isDegrees, Radius_, _1mm as _TOL_M
46
46
  # from math import fabs # from .latlonBase
47
47
 
48
48
  __all__ = _ALL_LAZY.ellipsoidalBase
49
- __version__ = '25.05.12'
49
+ __version__ = '25.07.21'
50
50
 
51
51
 
52
52
  class CartesianEllipsoidalBase(CartesianBase):
@@ -136,7 +136,7 @@ class CartesianEllipsoidalBase(CartesianBase):
136
136
 
137
137
  If C{B{sphere} is False}, a 2-tuple with the two intersection points
138
138
  of the I{circles}. For abutting circles, both points are the same
139
- instance, aka the I{radical center}.
139
+ instance (aka the I{radical center}).
140
140
 
141
141
  @raise IntersectionError: Concentric, invalid or non-intersecting spheres or circles.
142
142
 
@@ -449,8 +449,7 @@ class LatLonEllipsoidalBase(LatLonBase):
449
449
  def _etm(self):
450
450
  '''(INTERNAL) Get this C{LatLon} point as an ETM coordinate (L{pygeodesy.toEtm8}).
451
451
  '''
452
- etm = _MODS.etm
453
- return etm.toEtm8(self, datum=self.datum, Etm=etm.Etm)
452
+ return self._toX8(_MODS.etm.toEtm8)
454
453
 
455
454
  @property_RO
456
455
  def gamma(self):
@@ -523,8 +522,8 @@ class LatLonEllipsoidalBase(LatLonBase):
523
522
  a C{LatLon} instance.
524
523
 
525
524
  @raise ImportError: Package U{geographiclib
526
- <https://PyPI.org/project/geographiclib>} not
527
- installed or not found, but only in case
525
+ <https://PyPI.org/project/geographiclib>}
526
+ not installed or not found, but only if
528
527
  C{B{equidistant}=}L{EquidistantKarney}.
529
528
 
530
529
  @raise IntersectionError: Skew, colinear, parallel or otherwise non-intersecting
@@ -676,8 +675,8 @@ class LatLonEllipsoidalBase(LatLonBase):
676
675
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll both B{C{point1}} and
677
676
  B{C{point2}} (C{bool}).
678
677
  @kwarg equidistant: An azimuthal equidistant projection (I{class} or function
679
- L{pygeodesy.equidistant}) or C{None} for this point's preferred
680
- C{Equidistant}, like L{Equidistant<LatLonEllipsoidalBase.Equidistant>}.
678
+ L{pygeodesy.equidistant}) or C{None} for this point's
679
+ preferred C{Equidistant}, like L{Equidistant}.
681
680
  @kwarg tol: Convergence tolerance (C{meter}, conventionally).
682
681
 
683
682
  @return: Closest point (C{LatLon}).
@@ -778,6 +777,11 @@ class LatLonEllipsoidalBase(LatLonBase):
778
777
  '''
779
778
  return self._scale
780
779
 
780
+ def _toX8(self, toX8, **kwds):
781
+ '''(INTERNAL) Return toX8(self, ...).
782
+ '''
783
+ return toX8(self, **_xkwds(kwds, datum=self.datum, name=self.name))
784
+
781
785
  def toCartesian(self, height=None, **Cartesian_and_kwds): # PYCHOK signature
782
786
  '''Convert this point to cartesian, I{geocentric} coordinates,
783
787
  also known as I{Earth-Centered, Earth-Fixed} (ECEF).
@@ -793,11 +797,10 @@ class LatLonEllipsoidalBase(LatLonBase):
793
797
  def toCss(self, **toCss_kwds):
794
798
  '''Convert this C{LatLon} point to a Cassini-Soldner location.
795
799
 
796
- @kwarg toCss_kwds: Optional L{pygeodesy.toCss} keyword arguments.
800
+ @kwarg toCss_kwds: Optional keyword arguments for function
801
+ L{pygeodesy.toCss}.
797
802
 
798
803
  @return: The Cassini-Soldner location (L{Css}).
799
-
800
- @see: Function L{pygeodesy.toCss}.
801
804
  '''
802
805
  return _MODS.css.toCss(self, **self._name1__(toCss_kwds))
803
806
 
@@ -829,39 +832,38 @@ class LatLonEllipsoidalBase(LatLonBase):
829
832
  def toEtm(self, **toEtm8_kwds):
830
833
  '''Convert this C{LatLon} point to an ETM coordinate.
831
834
 
832
- @kwarg toEtm8_kwds: Optional L{pygeodesy.toEtm8} keyword arguments.
835
+ @kwarg toEtm8_kwds: Optional keyword arguments for
836
+ function L{pygeodesy.toEtm8}.
833
837
 
834
838
  @return: The ETM coordinate (L{Etm}).
835
-
836
- @see: Function L{pygeodesy.toEtm8}.
837
839
  '''
838
- return _MODS.etm.toEtm8(self, **self._name1__(toEtm8_kwds)) if toEtm8_kwds else self._etm
840
+ return self._etm if not toEtm8_kwds else \
841
+ self._toX8(_MODS.etm.toEtm8, **toEtm8_kwds)
839
842
 
840
843
  def toLcc(self, **toLcc_kwds):
841
844
  '''Convert this C{LatLon} point to a Lambert location.
842
845
 
843
- @kwarg toLcc_kwds: Optional L{pygeodesy.toLcc} keyword arguments.
846
+ @kwarg toLcc_kwds: Optional keyword arguments for
847
+ function L{pygeodesy.toLcc}.
844
848
 
845
849
  @return: The Lambert location (L{Lcc}).
846
-
847
- @see: Function L{pygeodesy.toLcc}.
848
850
  '''
849
851
  return _MODS.lcc.toLcc(self, **self._name1__(toLcc_kwds))
850
852
 
851
- def toMgrs(self, center=False, pole=NN):
853
+ def toMgrs(self, center=False, **toUtmUps_kwds):
852
854
  '''Convert this C{LatLon} point to an MGRS coordinate.
853
855
 
854
856
  @kwarg center: If C{True}, try to I{un}-center MGRS
855
857
  to its C{lowerleft} (C{bool}) or by
856
858
  C{B{center} meter} (C{scalar}).
857
- @kwarg pole: Optional top/center for the MGRS UPS
858
- projection (C{str}, 'N[orth]' or 'S[outh]').
859
+ @kwarg toUtmUps_kwds: Optional keyword arguments for
860
+ method L{toUtmUps}.
859
861
 
860
862
  @return: The MGRS coordinate (L{Mgrs}).
861
863
 
862
- @see: Method L{toUtmUps} and L{Mgrs.toLatLon}.
864
+ @see: Methods L{toUtmUps} and L{toMgrs<pygeodesy.utmupsBase.UtmUpsBase.toMgrs>}.
863
865
  '''
864
- return self.toUtmUps(center=center, pole=pole).toMgrs(center=False)
866
+ return self.toUtmUps(center=center, **toUtmUps_kwds).toMgrs(center=False)
865
867
 
866
868
  def toOsgr(self, kTM=False, **toOsgr_kwds):
867
869
  '''Convert this C{LatLon} point to an OSGR coordinate.
@@ -869,11 +871,10 @@ class LatLonEllipsoidalBase(LatLonBase):
869
871
  @kwarg kTM: If C{True}, use I{Karney}'s Krüger method from module
870
872
  L{ktm}, otherwise I{Ordinance Survery}'s recommended
871
873
  formulation (C{bool}).
872
- @kwarg toOsgr_kwds: Optional L{pygeodesy.toOsgr} keyword arguments.
874
+ @kwarg toOsgr_kwds: Optional keyword arguments for function
875
+ L{pygeodesy.toOsgr}.
873
876
 
874
877
  @return: The OSGR coordinate (L{Osgr}).
875
-
876
- @see: Function L{pygeodesy.toOsgr}.
877
878
  '''
878
879
  return _MODS.osgr.toOsgr(self, kTM=kTM, **self._name1__(toOsgr_kwds))
879
880
 
@@ -928,42 +929,40 @@ class LatLonEllipsoidalBase(LatLonBase):
928
929
  r = c.toLatLon(LatLon=self.classof, **_xkwds(LatLon_kwds, height=self.height))
929
930
  return r
930
931
 
931
- def toUps(self, pole=NN, falsed=True, center=False):
932
+ def toUps(self, center=False, **toUps8_kwds):
932
933
  '''Convert this C{LatLon} point to a UPS coordinate.
933
934
 
934
- @kwarg pole: Optional top/center of (stereographic)
935
- projection (C{str}, 'N[orth]' or 'S[outh]').
936
- @kwarg falsed: False easting and northing (C{bool}).
937
935
  @kwarg center: If C{True}, I{un}-center the UPS to its
938
936
  C{lowerleft} (C{bool}) or by C{B{center}
939
937
  meter} (C{scalar}).
938
+ @kwarg toUps8_kwds: Optional keyword arguments for
939
+ function L{pygeodesy.toUps8}.
940
940
 
941
941
  @return: The UPS coordinate (L{Ups}).
942
-
943
- @see: Function L{pygeodesy.toUps8}.
944
942
  '''
945
- if self._upsOK(pole, falsed):
946
- u = self._ups
947
- else:
948
- ups = _MODS.ups
949
- u = ups.toUps8(self, datum=self.datum, Ups=ups.Ups,
950
- pole=pole, falsed=falsed)
943
+ u = self._ups if (not toUps8_kwds) and self._upsOK() else \
944
+ self._toX8(_MODS.ups.toUps8, **toUps8_kwds)
951
945
  return _lowerleft(u, center)
952
946
 
953
- def toUtm(self, center=False):
947
+ def toUtm(self, center=False, **toUtm8_kwds):
954
948
  '''Convert this C{LatLon} point to a UTM coordinate.
955
949
 
956
950
  @kwarg center: If C{True}, I{un}-center the UTM to its
957
951
  C{lowerleft} (C{bool}) or by C{B{center}
958
952
  meter} (C{scalar}).
953
+ @kwarg toUtm8_kwds: Optional keyword arguments for function
954
+ L{pygeodesy.toUtm8}.
959
955
 
960
956
  @return: The UTM coordinate (L{Utm}).
961
957
 
962
- @see: Method L{Mgrs.toUtm} and function L{pygeodesy.toUtm8}.
958
+ @note: For the highest accuracy, use method L{toEtm} and
959
+ class L{pygeodesy.Etm} instead of L{pygeodesy.Utm}.
963
960
  '''
964
- return _lowerleft(self._utm, center)
961
+ u = self._utm if not toUtm8_kwds else \
962
+ self._toX8(_MODS.utm.toUtm8, **toUtm8_kwds)
963
+ return _lowerleft(u, center)
965
964
 
966
- def toUtmUps(self, pole=NN, center=False):
965
+ def toUtmUps(self, pole=NN, center=False, **toUtmUps8_kwds):
967
966
  '''Convert this C{LatLon} point to a UTM or UPS coordinate.
968
967
 
969
968
  @kwarg pole: Optional top/center of UPS (stereographic)
@@ -971,19 +970,19 @@ class LatLonEllipsoidalBase(LatLonBase):
971
970
  @kwarg center: If C{True}, I{un}-center the UTM or UPS to
972
971
  its C{lowerleft} (C{bool}) or by C{B{center}
973
972
  meter} (C{scalar}).
973
+ @kwarg toUtmUps8_kwds: Optional keyword arguments for
974
+ function L{pygeodesy.toUtmUps8}.
974
975
 
975
976
  @return: The UTM or UPS coordinate (L{Utm} or L{Ups}).
976
-
977
- @see: Function L{pygeodesy.toUtmUps8}.
978
977
  '''
979
- if self._utmOK():
978
+ x = not toUtmUps8_kwds
979
+ if x and self._utmOK():
980
980
  u = self._utm
981
- elif self._upsOK(pole):
981
+ elif x and self._upsOK(pole):
982
982
  u = self._ups
983
983
  else: # no cover
984
984
  utmups = _MODS.utmups
985
- u = utmups.toUtmUps8(self, datum=self.datum, pole=pole, name=self.name,
986
- Utm=utmups.Utm, Ups=utmups.Ups)
985
+ u = self._toX8(utmups.toUtmUps8, pole=pole, **toUtmUps8_kwds)
987
986
  if isinstance(u, utmups.Utm):
988
987
  self._update(False, _utm=u) # PYCHOK kwds
989
988
  elif isinstance(u, utmups.Ups):
@@ -1011,13 +1010,11 @@ class LatLonEllipsoidalBase(LatLonBase):
1011
1010
  @arg other: The other point (C{LatLon}).
1012
1011
  @arg bearing2: Bearing at the B{C{other}} point (compass C{degrees360}).
1013
1012
  @kwarg height_wrap_tol: Optional keyword arguments C{B{height}=None},
1014
- C{B{wrap}=False} and C{B{tol}}, see method L{intersection3
1015
- <pygeodesy.ellipsoidalBase.LatLonEllipsoidalBase>}.
1013
+ C{B{wrap}=False} and C{B{tol}}, see method L{intersection3}.
1016
1014
 
1017
1015
  @return: Triangulated point (C{LatLon}).
1018
1016
 
1019
- @see: Method L{intersection3<pygeodesy.ellipsoidalBase.LatLonEllipsoidalBase>}
1020
- for further details.
1017
+ @see: Method L{intersection3} for further details.
1021
1018
  '''
1022
1019
  if _isDegrees(bearing1) and _isDegrees(bearing2):
1023
1020
  r = self.intersection3(bearing1, other, bearing2, **height_wrap_tol)
@@ -1086,11 +1083,9 @@ class LatLonEllipsoidalBase(LatLonBase):
1086
1083
  '''(INTERNAL) Get this C{LatLon} point as UPS coordinate (L{Ups}),
1087
1084
  see L{pygeodesy.toUps8}.
1088
1085
  '''
1089
- ups = _MODS.ups
1090
- return ups.toUps8(self, datum=self.datum, Ups=ups.Ups,
1091
- pole=NN, falsed=True, name=self.name)
1086
+ return self._toX8(_MODS.ups.toUps8) # pole=NN, falsed=True
1092
1087
 
1093
- def _upsOK(self, pole=NN, falsed=True):
1088
+ def _upsOK(self, pole=NN, falsed=True, **unused):
1094
1089
  '''(INTERNAL) Check matching C{Ups}.
1095
1090
  '''
1096
1091
  try:
@@ -1104,8 +1099,7 @@ class LatLonEllipsoidalBase(LatLonBase):
1104
1099
  '''(INTERNAL) Get this C{LatLon} point as UTM coordinate (L{Utm}),
1105
1100
  see L{pygeodesy.toUtm8}.
1106
1101
  '''
1107
- utm = _MODS.utm
1108
- return utm.toUtm8(self, datum=self.datum, Utm=utm.Utm, name=self.name)
1102
+ return self._toX8(_MODS.utm.toUtm8)
1109
1103
 
1110
1104
  def _utmOK(self):
1111
1105
  '''(INTERNAL) Check C{Utm}.
pygeodesy/ellipsoids.py CHANGED
@@ -66,8 +66,9 @@ from __future__ import division as _; del _ # noqa: E702 ;
66
66
 
67
67
  # from pygeodesy.albers import AlbersEqualAreaCylindrical # _MODS
68
68
  from pygeodesy.basics import copysign0, isbool, _isin, isint, typename
69
- from pygeodesy.constants import EPS, EPS0, EPS02, EPS1, INF, NINF, PI4, PI_2, PI_3, R_M, R_MA, R_FM, \
70
- _EPSqrt, _EPStol as _TOL, _floatuple as _T, _isfinite, _over, \
69
+ from pygeodesy.constants import EPS, EPS_2, EPS0, EPS02, EPS1, INF, NINF, \
70
+ _over, PI_2, PI_3, PI4, R_M, R_MA, R_FM, \
71
+ _EPSqrt, _EPStol as _TOL, _floatuple as _T, _isfinite, \
71
72
  _0_0s, _0_0, _0_5, _1_0, _1_EPS, _2_0, _4_0, _90_0, \
72
73
  _0_25, _3_0 # PYCHOK used!
73
74
  from pygeodesy.errors import _AssertionError, IntersectionError, _ValueError, _xattr, _xkwds_not
@@ -95,7 +96,7 @@ from pygeodesy.utily import atan1, atan1d, atan2b, degrees90, m2radians, radians
95
96
  from math import asinh, atan, atanh, cos, degrees, exp, fabs, radians, sin, sinh, sqrt, tan # as _tan
96
97
 
97
98
  __all__ = _ALL_LAZY.ellipsoids
98
- __version__ = '25.05.12'
99
+ __version__ = '25.08.25'
99
100
 
100
101
  _f_0_0 = Float(f =_0_0) # zero flattening
101
102
  _f__0_0 = Float(f_=_0_0) # zero inverse flattening
@@ -1186,6 +1187,22 @@ class Ellipsoid(_NamedEnumItem):
1186
1187
 
1187
1188
  return Vector4Tuple(v.x, v.y, v.z, h, iteration=i, name__=self.height4)
1188
1189
 
1190
+ def _heightB(self, sa, ca, z, p): # in ecef.EcefSudano, ecec.EcefVeness
1191
+ '''(INTERNAL) Height above ellipsoid (Bowring eqn 7) at C{lat}.
1192
+ '''
1193
+ # sa, ca = sincos2d(lat)
1194
+ # p = hypot(x, y) # distance to polar axis
1195
+
1196
+ # r = a / self.e2s(sa) # length of normal terminated by polar axis
1197
+ # h = p * ca + z * sa - (a * a / r)
1198
+ return (p * ca + fabs(z * sa) - self.a * self.e2s(sa)) if sa else (p - self.a)
1199
+
1200
+ @Property_RO
1201
+ def _heightMax(self):
1202
+ '''(INTERNAL) Get the height limit (C{meter}, conventionally).
1203
+ '''
1204
+ return self.a / EPS_2 # self.a * _2_EPS, about 12M lightyears
1205
+
1189
1206
  def _hubeny_2(self, phi2, phi1, lam21, scaled=True, squared=True):
1190
1207
  '''(INTERNAL) like function C{pygeodesy.flatLocal_}/C{pygeodesy.hubeny_},
1191
1208
  returning the I{angular} distance in C{radians squared} or C{radians}
@@ -1542,7 +1559,7 @@ class Ellipsoid(_NamedEnumItem):
1542
1559
 
1543
1560
  @deprecated_property_RO
1544
1561
  def rhumbx(self):
1545
- '''DEPRECATED on 2023.11.28, use property C{rhumbekx}. '''
1562
+ '''DEPRECATED on 2023.11.28, use property C{rhumbekx}.'''
1546
1563
  return self.rhumbekx
1547
1564
 
1548
1565
  def Rlat(self, lat):
@@ -1587,16 +1604,15 @@ class Ellipsoid(_NamedEnumItem):
1587
1604
 
1588
1605
  @see: Method L{roc2_} and class L{EcefYou}.
1589
1606
  '''
1590
- if not self.f: # .isSpherical
1591
- n = self.a
1592
- elif ca is None:
1593
- r = self.e2s2(sa) # see .roc2_ and _EcefBase._forward
1594
- n = sqrt(self.a2 / r) if r > EPS02 else _0_0
1595
- elif ca: # derived from EcefYou.forward
1596
- h = hypot(ca, self.b_a * sa) if sa else fabs(ca)
1597
- n = self.a / h
1598
- elif sa:
1599
- n = self.a2_b / fabs(sa)
1607
+ if sa and self.f: # .isEllipsoidal
1608
+ if ca is None:
1609
+ r = self.e2s2(sa) # see .roc2_ and _EcefBase._forward
1610
+ n = sqrt(self.a2 / r) if r > EPS02 else _0_0
1611
+ elif ca: # derived from EcefYou.forward
1612
+ h = hypot(ca, self.b_a * sa)
1613
+ n = self.a / h
1614
+ else:
1615
+ n = self.a2_b / fabs(sa)
1600
1616
  else:
1601
1617
  n = self.a
1602
1618
  return n