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.
- pygeodesy/__init__.py +10 -10
- pygeodesy/cartesianBase.py +21 -20
- pygeodesy/ecef.py +324 -260
- pygeodesy/ellipsoidalBase.py +52 -58
- pygeodesy/ellipsoids.py +30 -14
- pygeodesy/elliptic.py +246 -225
- pygeodesy/fmath.py +6 -4
- pygeodesy/fsums.py +40 -18
- pygeodesy/geodesici.py +3 -3
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +2 -2
- pygeodesy/geodesicx/gx.py +3 -2
- pygeodesy/geodesicx/gxarea.py +4 -5
- pygeodesy/geodesicx/gxbases.py +3 -2
- pygeodesy/internals.py +3 -3
- pygeodesy/ktm.py +3 -3
- pygeodesy/latlonBase.py +4 -4
- pygeodesy/lazily.py +3 -3
- pygeodesy/nvectorBase.py +4 -4
- pygeodesy/sphericalTrigonometry.py +5 -5
- pygeodesy/vector3dBase.py +5 -3
- {pygeodesy-25.5.28.dist-info → pygeodesy-25.8.25.dist-info}/METADATA +12 -12
- {pygeodesy-25.5.28.dist-info → pygeodesy-25.8.25.dist-info}/RECORD +25 -25
- {pygeodesy-25.5.28.dist-info → pygeodesy-25.8.25.dist-info}/WHEEL +0 -0
- {pygeodesy-25.5.28.dist-info → pygeodesy-25.8.25.dist-info}/top_level.txt +0 -0
pygeodesy/ellipsoidalBase.py
CHANGED
|
@@ -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.
|
|
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
|
|
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
|
-
|
|
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>}
|
|
527
|
-
installed or not found, but only
|
|
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
|
|
680
|
-
C{Equidistant}, like L{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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
858
|
-
|
|
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:
|
|
864
|
+
@see: Methods L{toUtmUps} and L{toMgrs<pygeodesy.utmupsBase.UtmUpsBase.toMgrs>}.
|
|
863
865
|
'''
|
|
864
|
-
return self.toUtmUps(center=center,
|
|
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
|
|
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,
|
|
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(
|
|
946
|
-
|
|
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
|
-
@
|
|
958
|
+
@note: For the highest accuracy, use method L{toEtm} and
|
|
959
|
+
class L{pygeodesy.Etm} instead of L{pygeodesy.Utm}.
|
|
963
960
|
'''
|
|
964
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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,
|
|
70
|
-
|
|
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.
|
|
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
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
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
|