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
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-16 22:49 +1300
1"""
2Coordinates System Transformations
3==================================
5Provide transformations between different coordinate systems.
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.
13The following transformations are available:
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.
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"""
37from __future__ import annotations
39import typing
41import numpy as np
43from colour.algebra import sdiv, sdiv_mode
45if typing.TYPE_CHECKING:
46 from colour.hints import ArrayLike, NDArrayFloat
48from colour.utilities import as_float_array, tsplit, tstack
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"
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]
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).
73 Parameters
74 ----------
75 a
76 Cartesian coordinates array :math:`xyz` to transform.
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.
86 References
87 ----------
88 :cite:`Wikipedia2006`, :cite:`Wikipedia2005a`
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 """
97 x, y, z = tsplit(a)
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)
104 return tstack([rho, theta, phi])
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`.
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.
121 Returns
122 -------
123 :class:`numpy.ndarray`
124 Cartesian coordinates array :math:`xyz`.
126 References
127 ----------
128 :cite:`Wikipedia2006`, :cite:`Wikipedia2005a`
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 """
137 rho, theta, phi = tsplit(a)
139 x = rho * np.sin(theta) * np.cos(phi)
140 y = rho * np.sin(theta) * np.sin(phi)
141 z = rho * np.cos(theta)
143 return tstack([x, y, z])
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).
152 Parameters
153 ----------
154 a
155 Cartesian coordinates array :math:`xy` to transform.
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.
164 References
165 ----------
166 :cite:`Wikipedia2006`, :cite:`Wikipedia2005a`
168 Examples
169 --------
170 >>> a = np.array([3, 1])
171 >>> cartesian_to_polar(a) # doctest: +ELLIPSIS
172 array([ 3.1622776..., 0.3217505...])
173 """
175 x, y = tsplit(a)
177 rho = np.hypot(x, y)
178 phi = np.arctan2(y, x)
180 return tstack([rho, phi])
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`.
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).
196 Returns
197 -------
198 :class:`numpy.ndarray`
199 Cartesian coordinates array :math:`xy`.
201 References
202 ----------
203 :cite:`Wikipedia2006`, :cite:`Wikipedia2005a`
205 Examples
206 --------
207 >>> a = np.array([3.16227766, 0.32175055])
208 >>> polar_to_cartesian(a) # doctest: +ELLIPSIS
209 array([ 3. , 0.9999999...])
210 """
212 rho, phi = tsplit(a)
214 x = rho * np.cos(phi)
215 y = rho * np.sin(phi)
217 return tstack([x, y])
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).
226 Parameters
227 ----------
228 a
229 Cartesian coordinates array :math:`xyz` to transform.
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].
238 References
239 ----------
240 :cite:`Wikipedia2006`, :cite:`Wikipedia2005a`
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 """
249 a = as_float_array(a)
251 rho, phi = tsplit(cartesian_to_polar(a[..., 0:2]))
253 return tstack([rho, phi, a[..., -1]])
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`.
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].
270 Returns
271 -------
272 :class:`numpy.ndarray`
273 Cartesian coordinates array :math:`xyz`.
275 References
276 ----------
277 :cite:`Wikipedia2006`, :cite:`Wikipedia2005a`
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 """
286 a = as_float_array(a)
288 x, y = tsplit(polar_to_cartesian(a[..., 0:2]))
290 return tstack([x, y, a[..., -1]])