Coverage for algebra/coordinates/transformations.py: 58%

43 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-16 22:49 +1300

1""" 

2Coordinates System Transformations 

3================================== 

4 

5Provide transformations between different coordinate systems. 

6 

7This module implements transformations between Cartesian coordinates and 

8various other coordinate systems commonly used in colour science and 

9computer graphics applications. The transformations preserve the spatial 

10relationships while expressing positions in different mathematical 

11representations. 

12 

13The following transformations are available: 

14 

15- :func:`colour.algebra.cartesian_to_spherical`: Transform from Cartesian 

16 to spherical coordinate system. 

17- :func:`colour.algebra.spherical_to_cartesian`: Transform from spherical 

18 to Cartesian coordinate system. 

19- :func:`colour.algebra.cartesian_to_polar`: Transform from Cartesian to 

20 polar coordinate system. 

21- :func:`colour.algebra.polar_to_cartesian`: Transform from polar to 

22 Cartesian coordinate system. 

23- :func:`colour.algebra.cartesian_to_cylindrical`: Transform from 

24 Cartesian to cylindrical coordinate system. 

25- :func:`colour.algebra.cylindrical_to_cartesian`: Transform from 

26 cylindrical to Cartesian coordinate system. 

27 

28References 

29---------- 

30- :cite:`Wikipedia2005a` : Wikipedia. (2005). ISO 31-11. Retrieved July 31, 

31 2016, from https://en.wikipedia.org/wiki/ISO_31-11 

32- :cite:`Wikipedia2006` : Wikipedia. (2006). List of common coordinate 

33 transformations. Retrieved July 18, 2014, from 

34 http://en.wikipedia.org/wiki/List_of_common_coordinate_transformations 

35""" 

36 

37from __future__ import annotations 

38 

39import typing 

40 

41import numpy as np 

42 

43from colour.algebra import sdiv, sdiv_mode 

44 

45if typing.TYPE_CHECKING: 

46 from colour.hints import ArrayLike, NDArrayFloat 

47 

48from colour.utilities import as_float_array, tsplit, tstack 

49 

50__author__ = "Colour Developers" 

51__copyright__ = "Copyright 2013 Colour Developers" 

52__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause" 

53__maintainer__ = "Colour Developers" 

54__email__ = "colour-developers@colour-science.org" 

55__status__ = "Production" 

56 

57__all__ = [ 

58 "cartesian_to_spherical", 

59 "spherical_to_cartesian", 

60 "cartesian_to_polar", 

61 "polar_to_cartesian", 

62 "cartesian_to_cylindrical", 

63 "cylindrical_to_cartesian", 

64] 

65 

66 

67def cartesian_to_spherical(a: ArrayLike) -> NDArrayFloat: 

68 """ 

69 Transform specified cartesian coordinates array :math:`xyz` to spherical 

70 coordinates array :math:`\\rho\\theta\\phi` (radial distance, inclination 

71 or elevation and azimuth). 

72 

73 Parameters 

74 ---------- 

75 a 

76 Cartesian coordinates array :math:`xyz` to transform. 

77 

78 Returns 

79 ------- 

80 :class:`numpy.ndarray` 

81 Spherical coordinates array :math:`\\rho\\theta\\phi`, :math:`\\rho` 

82 is in range [0, +inf], :math:`\\theta` is in range [0, pi] radians, 

83 i.e., [0, 180] degrees, and :math:`\\phi` is in range [-pi, pi] 

84 radians, i.e., [-180, 180] degrees. 

85 

86 References 

87 ---------- 

88 :cite:`Wikipedia2006`, :cite:`Wikipedia2005a` 

89 

90 Examples 

91 -------- 

92 >>> a = np.array([3, 1, 6]) 

93 >>> cartesian_to_spherical(a) # doctest: +ELLIPSIS 

94 array([ 6.7823299..., 0.4850497..., 0.3217505...]) 

95 """ 

96 

97 x, y, z = tsplit(a) 

98 

99 rho = np.linalg.norm(a, axis=-1) 

100 with sdiv_mode(): 

101 theta = np.arccos(sdiv(z, rho)) 

102 phi = np.arctan2(y, x) 

103 

104 return tstack([rho, theta, phi]) 

105 

106 

107def spherical_to_cartesian(a: ArrayLike) -> NDArrayFloat: 

108 """ 

109 Transform specified spherical coordinates array :math:`\\rho\\theta\\phi` 

110 (radial distance, inclination or elevation and azimuth) to cartesian 

111 coordinates array :math:`xyz`. 

112 

113 Parameters 

114 ---------- 

115 a 

116 Spherical coordinates array :math:`\\rho\\theta\\phi` to transform, 

117 :math:`\\rho` is in range [0, +inf], :math:`\\theta` is in range 

118 [0, pi] radians, i.e., [0, 180] degrees, and :math:`\\phi` is in 

119 range [-pi, pi] radians, i.e., [-180, 180] degrees. 

120 

121 Returns 

122 ------- 

123 :class:`numpy.ndarray` 

124 Cartesian coordinates array :math:`xyz`. 

125 

126 References 

127 ---------- 

128 :cite:`Wikipedia2006`, :cite:`Wikipedia2005a` 

129 

130 Examples 

131 -------- 

132 >>> a = np.array([6.78232998, 0.48504979, 0.32175055]) 

133 >>> spherical_to_cartesian(a) # doctest: +ELLIPSIS 

134 array([ 3.0000000..., 0.9999999..., 5.9999999...]) 

135 """ 

136 

137 rho, theta, phi = tsplit(a) 

138 

139 x = rho * np.sin(theta) * np.cos(phi) 

140 y = rho * np.sin(theta) * np.sin(phi) 

141 z = rho * np.cos(theta) 

142 

143 return tstack([x, y, z]) 

144 

145 

146def cartesian_to_polar(a: ArrayLike) -> NDArrayFloat: 

147 """ 

148 Transform specified cartesian coordinates array :math:`xy` to polar 

149 coordinates array :math:`\\rho\\phi` (radial coordinate, angular 

150 coordinate). 

151 

152 Parameters 

153 ---------- 

154 a 

155 Cartesian coordinates array :math:`xy` to transform. 

156 

157 Returns 

158 ------- 

159 :class:`numpy.ndarray` 

160 Polar coordinates array :math:`\\rho\\phi`, :math:`\\rho` is in range 

161 [0, +inf], :math:`\\phi` is in range [-pi, pi] radians, i.e., [-180, 

162 180] degrees. 

163 

164 References 

165 ---------- 

166 :cite:`Wikipedia2006`, :cite:`Wikipedia2005a` 

167 

168 Examples 

169 -------- 

170 >>> a = np.array([3, 1]) 

171 >>> cartesian_to_polar(a) # doctest: +ELLIPSIS 

172 array([ 3.1622776..., 0.3217505...]) 

173 """ 

174 

175 x, y = tsplit(a) 

176 

177 rho = np.hypot(x, y) 

178 phi = np.arctan2(y, x) 

179 

180 return tstack([rho, phi]) 

181 

182 

183def polar_to_cartesian(a: ArrayLike) -> NDArrayFloat: 

184 """ 

185 Transform specified polar coordinates array :math:`\\rho\\phi` (radial 

186 coordinate, angular coordinate) to Cartesian coordinates array :math:`xy`. 

187 

188 Parameters 

189 ---------- 

190 a 

191 Polar coordinates array :math:`\\rho\\phi` to transform where 

192 :math:`\\rho` is the radial coordinate in range [0, +inf] and 

193 :math:`\\phi` is the angular coordinate in range [-pi, pi] radians 

194 (i.e., [-180, 180] degrees). 

195 

196 Returns 

197 ------- 

198 :class:`numpy.ndarray` 

199 Cartesian coordinates array :math:`xy`. 

200 

201 References 

202 ---------- 

203 :cite:`Wikipedia2006`, :cite:`Wikipedia2005a` 

204 

205 Examples 

206 -------- 

207 >>> a = np.array([3.16227766, 0.32175055]) 

208 >>> polar_to_cartesian(a) # doctest: +ELLIPSIS 

209 array([ 3. , 0.9999999...]) 

210 """ 

211 

212 rho, phi = tsplit(a) 

213 

214 x = rho * np.cos(phi) 

215 y = rho * np.sin(phi) 

216 

217 return tstack([x, y]) 

218 

219 

220def cartesian_to_cylindrical(a: ArrayLike) -> NDArrayFloat: 

221 """ 

222 Transform specified cartesian coordinates array :math:`xyz` to cylindrical 

223 coordinates array :math:`\\rho\\phi z` (radial distance, azimuth and 

224 height). 

225 

226 Parameters 

227 ---------- 

228 a 

229 Cartesian coordinates array :math:`xyz` to transform. 

230 

231 Returns 

232 ------- 

233 :class:`numpy.ndarray` 

234 Cylindrical coordinates array :math:`\\rho\\phi z`, :math:`\\rho` is 

235 in range [0, +inf], :math:`\\phi` is in range [-pi, pi] radians 

236 i.e., [-180, 180] degrees, :math:`z` is in range [0, +inf]. 

237 

238 References 

239 ---------- 

240 :cite:`Wikipedia2006`, :cite:`Wikipedia2005a` 

241 

242 Examples 

243 -------- 

244 >>> a = np.array([3, 1, 6]) 

245 >>> cartesian_to_cylindrical(a) # doctest: +ELLIPSIS 

246 array([ 3.1622776..., 0.3217505..., 6. ]) 

247 """ 

248 

249 a = as_float_array(a) 

250 

251 rho, phi = tsplit(cartesian_to_polar(a[..., 0:2])) 

252 

253 return tstack([rho, phi, a[..., -1]]) 

254 

255 

256def cylindrical_to_cartesian(a: ArrayLike) -> NDArrayFloat: 

257 """ 

258 Transform specified cylindrical coordinates array :math:`\\rho\\phi z` 

259 (radial distance, azimuth and height) to cartesian coordinates array 

260 :math:`xyz`. 

261 

262 Parameters 

263 ---------- 

264 a 

265 Cylindrical coordinates array :math:`\\rho\\phi z` to transform, 

266 where :math:`\\rho` is in range [0, +inf], :math:`\\phi` is in 

267 range [-pi, pi] radians i.e., [-180, 180] degrees, and :math:`z` 

268 is in range [0, +inf]. 

269 

270 Returns 

271 ------- 

272 :class:`numpy.ndarray` 

273 Cartesian coordinates array :math:`xyz`. 

274 

275 References 

276 ---------- 

277 :cite:`Wikipedia2006`, :cite:`Wikipedia2005a` 

278 

279 Examples 

280 -------- 

281 >>> a = np.array([3.16227766, 0.32175055, 6.00000000]) 

282 >>> cylindrical_to_cartesian(a) # doctest: +ELLIPSIS 

283 array([ 3. , 0.9999999..., 6. ]) 

284 """ 

285 

286 a = as_float_array(a) 

287 

288 x, y = tsplit(polar_to_cartesian(a[..., 0:2])) 

289 

290 return tstack([x, y, a[..., -1]])