Coverage for pygeodesy/ecefLocals.py: 92%

49 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2025-05-29 12:40 -0400

1 

2# -*- coding: utf-8 -*- 

3 

4u'''(INTERNAL) ECEF to local coodinate conversions, separated from 

5module C{ecef} to defer importing the latter into C{CartesianBase} 

6and C{LatLonBase}. 

7''' 

8 

9from pygeodesy.basics import _isin, _xsubclassof 

10# from pygeodesy.ecef import EcefKarney # _MODS 

11from pygeodesy.errors import _xkwds_item2, _xkwds_pop2 

12from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS 

13# from pygeodesy import ltp as _ltp # _MODS.into 

14# from pygeodesy import ltpTuples as _ltpTuples # _MODS.into 

15from pygeodesy.named import _Named, notOverloaded 

16from pygeodesy.props import Property_RO, property_RO, property_ROver 

17 

18__all__ = _ALL_LAZY.ecefLocals 

19__version__ = '25.04.28' 

20 

21_ltp = _MODS.into(ltp=__name__) 

22_ltpTuples = _MODS.into(ltpTuples=__name__) 

23 

24 

25class _EcefLocal(_Named): 

26 '''(INTERNAL) Base class for C{CartesianBase}, C{Ecef9Tuple} and 

27 C{LatLonBase}, providing ECEF to local coordinate conversions. 

28 ''' 

29 

30 @property_ROver 

31 def Ecef(self): 

32 '''Get the ECEF I{class} (L{EcefKarney}), I{once}. 

33 ''' 

34 return _MODS.ecef.EcefKarney 

35 

36 @property_RO 

37 def _ecef9(self): 

38 '''I{Must be overloaded}.''' 

39 notOverloaded(self) 

40 

41 @property_RO 

42 def _ecef9datum(self): 

43 try: 

44 d = self.datum # PYCHOK C{CartesianBase}, ... 

45 except AttributeError: 

46 d = None 

47 return d or self._ecef9.datum 

48 

49 @Property_RO 

50 def _ltp(self): 

51 '''(INTERNAL) Cache this instance' LTP (L{Ltp}). 

52 ''' 

53 return _ltp.Ltp(self._ecef9, ecef=self.Ecef(self._ecef9datum), name=self.name) 

54 

55 def _ltp_ecef2local(self, ltp, Xyz_kwds, _None=None, **Xyz): # in C{Ecef9Tuple} 

56 '''(INTERNAL) Invoke C{_ltp._xLtp(ltp, self._ltp)._ecef2local}. 

57 ''' 

58 C, _ = Xyz_ = _xkwds_pop2(Xyz_kwds, **Xyz) 

59 if C is not _None: # validate C, see .toLocal 

60 n, X = _xkwds_item2(Xyz) 

61 if X is not C: 

62 _xsubclassof(X, **{n: C}) 

63 ltp = _ltp._xLtp(ltp, self._ltp) 

64 return ltp._ecef2local(self._ecef9, *Xyz_) 

65 

66 def toAer(self, ltp=None, **Aer_and_kwds): 

67 '''Convert this instance to I{local} I{Azimuth, Elevation, slant Range} (AER) components. 

68 

69 @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this 

70 instance' L{LTP<pygeodesy.ecefLocals._EcefLocal.toLtp>}. 

71 @kwarg Aer_and_kwds: Optional AER class C{B{Aer}=}L{Aer<pygeodesy.ltpTuples.Aer>} 

72 to use and optionally, additional B{C{Aer}} keyword arguments. 

73 

74 @return: An B{C{Aer}} instance. 

75 

76 @raise TypeError: Invalid B{C{ltp}}. 

77 

78 @see: Method L{toLocal<pygeodesy.ecefLocals._EcefLocal.toLocal>}. 

79 ''' 

80 return self._ltp_ecef2local(ltp, Aer_and_kwds, Aer=_ltpTuples.Aer) 

81 

82 def toEnu(self, ltp=None, **Enu_and_kwds): 

83 '''Convert this instance to I{local} I{East, North, Up} (ENU) components. 

84 

85 @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this 

86 instance' L{LTP<pygeodesy.ecefLocals._EcefLocal.toLtp>}. 

87 @kwarg Enu_and_kwds: Optional ENU class C{B{Enu}=}L{Enu<pygeodesy.ltpTuples.Enu>} 

88 to use and optionally, additional B{C{Enu}} keyword arguments. 

89 

90 @return: An B{C{Enu}} instance. 

91 

92 @raise TypeError: Invalid B{C{ltp}}. 

93 

94 @see: Method L{toLocal<pygeodesy.ecefLocals._EcefLocal.toLocal>}. 

95 ''' 

96 return self._ltp_ecef2local(ltp, Enu_and_kwds, Enu=_ltpTuples.Enu) 

97 

98 def toLocal(self, Xyz=None, ltp=None, **Xyz_kwds): 

99 '''Convert this instance to I{local} components in a I{local tangent plane} (LTP) 

100 

101 @kwarg Xyz: Optional I{local} components class (L{XyzLocal}, L{Aer}, L{Enu}, 

102 L{Ned}) or C{None}. 

103 @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this 

104 cartesian's L{LTP<pygeodesy.ecefLocals._EcefLocal.toLtp>}. 

105 @kwarg Xyz_kwds: Optionally, additional B{C{Xyz}} keyword arguments, ignored 

106 if C{B{Xyz} is None}. 

107 

108 @return: An B{C{Xyz}} instance or a L{Local9Tuple}C{(x, y, z, lat, lon, 

109 height, ltp, ecef, M)} if C{B{Xyz} is None} (with C{M=None}). 

110 

111 @raise TypeError: Invalid B{C{ltp}}. 

112 ''' 

113 return self._ltp_ecef2local(ltp, Xyz_kwds, Xyz=Xyz, _None=Xyz) 

114 

115 def toLtp(self, Ecef=None, **name): 

116 '''Return the I{local tangent plane} (LTP) for this instance. 

117 

118 @kwarg Ecef: Optional ECEF I{class} (L{EcefKarney}, ... L{EcefYou}), overriding 

119 this instance' L{Ecef<pygeodesy.ecefLocals._EcefLocal.Ecef>}. 

120 @kwarg name: Optional C{B{name}=NN} (C{str}). 

121 

122 @return: An B{C{Ltp}} instance. 

123 ''' 

124 if _isin(Ecef, None, self.Ecef) and not name: 

125 ltp = self._ltp 

126 else: # like self._ltp 

127 ecef = (Ecef if Ecef else self.Ecef)(self._ecef9datum) 

128 ltp = _ltp.Ltp(self._ecef9, ecef=ecef, name=self._name__(name)) 

129 return ltp 

130 

131 def toNed(self, ltp=None, **Ned_and_kwds): 

132 '''Convert this instance to I{local} I{North, East, Down} (NED) components. 

133 

134 @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this 

135 instance' L{LTP<pygeodesy.ecefLocals._EcefLocal.toLtp>}. 

136 @kwarg Ned_and_kwds: Optional NED class C{B{Ned}=}L{Ned<pygeodesy.ltpTuples.Ned>} 

137 to use and optionally, additional B{C{Ned}} keyword arguments. 

138 

139 @return: An B{C{Ned}} instance. 

140 

141 @raise TypeError: Invalid B{C{ltp}}. 

142 

143 @see: Method L{toLocal<pygeodesy.ecefLocals._EcefLocal.toLocal>}. 

144 ''' 

145 return self._ltp_ecef2local(ltp, Ned_and_kwds, Ned=_ltpTuples.Ned) 

146 

147 def toXyz(self, ltp=None, **Xyz_and_kwds): 

148 '''Convert this instance to I{local} I{X, Y, Z} (XYZ) components. 

149 

150 @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this 

151 instance' L{LTP<pygeodesy.ecefLocals._EcefLocal.toLtp>}. 

152 @kwarg Xyz_and_kwds: Optional XYZ class C{B{Xyz}=}L{Xyz<pygeodesy.ltpTuples.XyzLocal>} 

153 to use and optionally, additional B{C{Xyz}} keyword arguments. 

154 

155 @return: An B{C{Xyz}} instance. 

156 

157 @raise TypeError: Invalid B{C{ltp}}. 

158 

159 @see: Method L{toLocal<pygeodesy.ecefLocals._EcefLocal.toLocal>}. 

160 ''' 

161 return self._ltp_ecef2local(ltp, Xyz_and_kwds, Xyz=_ltpTuples.XyzLocal) 

162 

163 

164__all__ += _ALL_DOCS(_EcefLocal) 

165 

166# **) MIT License 

167# 

168# Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved. 

169# 

170# Permission is hereby granted, free of charge, to any person obtaining a 

171# copy of this software and associated documentation files (the "Software"), 

172# to deal in the Software without restriction, including without limitation 

173# the rights to use, copy, modify, merge, publish, distribute, sublicense, 

174# and/or sell copies of the Software, and to permit persons to whom the 

175# Software is furnished to do so, subject to the following conditions: 

176# 

177# The above copyright notice and this permission notice shall be included 

178# in all copies or substantial portions of the Software. 

179# 

180# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 

181# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 

182# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 

183# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 

184# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 

185# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 

186# OTHER DEALINGS IN THE SOFTWARE.