33
44from .ellipsoid import Ellipsoid
55from .utils import sanitize
6+ from .rcurve import rcurve_transverse
67
78try :
89 from numpy import radians , degrees , tan , sin , exp , pi , sqrt , inf , vectorize
2728 "geocentric2geodetic" ,
2829 "geodetic2authalic" ,
2930 "authalic2geodetic" ,
31+ "geod2geoc" ,
32+ "geoc2geod" ,
3033]
3134
3235if typing .TYPE_CHECKING :
3336 from numpy import ndarray
3437
3538
36- def geodetic2geocentric ( geodetic_lat : "ndarray" , ell : Ellipsoid = None , deg : bool = True ) -> "ndarray" :
39+ def geoc2geod ( geocentric_lat : "ndarray" , geocentric_distance : "ndarray" , ell : Ellipsoid = None , deg : bool = True ) -> "ndarray" :
3740 """
38- convert geodetic latitude to geocentric latitude.
41+ convert geocentric latitude to geodetic latitude, consider mean sea level altitude
3942
40- like Matlab geocentricLatitude()
43+ like Matlab geoc2geod()
44+
45+ Parameters
46+ ----------
47+ geocentric_lat : "ndarray"
48+ geocentric latitude
49+ geocentric_distance: "ndarray"
50+ distance from planet center, meters (NOT altitude above ground!)
51+ ell : Ellipsoid, optional
52+ reference ellipsoid (default WGS84)
53+ deg : bool, optional
54+ degrees input/output (False: radians in/out)
55+
56+ Returns
57+ -------
58+ geodetic_lat : "ndarray"
59+ geodetic latiude
60+
61+
62+ References
63+ ----------
64+ Long, S.A.T. "General-Altitude Transformation between Geocentric
65+ and Geodetic Coordinates. Celestial Mechanics (12), 2, p. 225-230 (1975)
66+ doi: 10.1007/BF01230214"
67+ """
68+ geocentric_lat , ell = sanitize (geocentric_lat , ell , deg )
69+
70+ r = geocentric_distance / ell .semimajor_axis
71+
72+ geodetic_lat = (
73+ geocentric_lat
74+ + (sin (2 * geocentric_lat ) / r ) * ell .flattening
75+ + ((1 / r ** 2 + 1 / (4 * r )) * sin (4 * geocentric_lat )) * ell .flattening ** 2
76+ )
77+
78+ return degrees (geodetic_lat ) if deg else geodetic_lat
79+
80+
81+ def geodetic2geocentric (geodetic_lat : "ndarray" , alt_m : "ndarray" , ell : Ellipsoid = None , deg : bool = True ) -> "ndarray" :
82+ """
83+ convert geodetic latitude to geocentric latitude on spheroid surface
84+
85+ like Matlab geocentricLatitude() with alt_m = 0
86+ like Matlab geod2geoc()
4187
4288 Parameters
4389 ----------
4490 geodetic_lat : "ndarray"
4591 geodetic latitude
92+ alt_m: "ndarray"
93+ altitude above ellipsoid
4694 ell : Ellipsoid, optional
4795 reference ellipsoid (default WGS84)
4896 deg : bool, optional
@@ -60,22 +108,28 @@ def geodetic2geocentric(geodetic_lat: "ndarray", ell: Ellipsoid = None, deg: boo
60108 Office, Washington, DC, 1987, pp. 13-18.
61109 """
62110 geodetic_lat , ell = sanitize (geodetic_lat , ell , deg )
63-
64- geocentric_lat = atan ((1 - ( ell .eccentricity ) ** 2 ) * tan (geodetic_lat ))
111+ r = rcurve_transverse ( geodetic_lat , ell , deg = False )
112+ geocentric_lat = atan ((1 - ell .eccentricity ** 2 * ( r / ( r + alt_m )) ) * tan (geodetic_lat ))
65113
66114 return degrees (geocentric_lat ) if deg else geocentric_lat
67115
68116
69- def geocentric2geodetic (geocentric_lat : "ndarray" , ell : Ellipsoid = None , deg : bool = True ) -> "ndarray" :
117+ geod2geoc = geodetic2geocentric
118+
119+
120+ def geocentric2geodetic (geocentric_lat : "ndarray" , alt_m : "ndarray" , ell : Ellipsoid = None , deg : bool = True ) -> "ndarray" :
70121 """
71122 converts from geocentric latitude to geodetic latitude
72123
73- like Matlab geodeticLatitudeFromGeocentric()
124+ like Matlab geodeticLatitudeFromGeocentric() when alt_m = 0
125+ like Matlab geod2geoc() but with sea level altitude rather than planet center distance
74126
75127 Parameters
76128 ----------
77129 geocentric_lat : "ndarray"
78130 geocentric latitude
131+ alt_m: "ndarray"
132+ altitude above ellipsoid
79133 ell : Ellipsoid, optional
80134 reference ellipsoid (default WGS84)
81135 deg : bool, optional
@@ -93,8 +147,8 @@ def geocentric2geodetic(geocentric_lat: "ndarray", ell: Ellipsoid = None, deg: b
93147 Office, Washington, DC, 1987, pp. 13-18.
94148 """
95149 geocentric_lat , ell = sanitize (geocentric_lat , ell , deg )
96-
97- geodetic_lat = atan (tan (geocentric_lat ) / (1 - ( ell .eccentricity ) ** 2 ))
150+ r = rcurve_transverse ( geocentric_lat , ell , deg = False )
151+ geodetic_lat = atan (tan (geocentric_lat ) / (1 - ell .eccentricity ** 2 * ( r / ( r + alt_m )) ))
98152
99153 return degrees (geodetic_lat ) if deg else geodetic_lat
100154
0 commit comments