Convert a single vector from Cartesian to spherical coordinates. For an n-dimensional vector, produces: - `r` (radius, = 1.0 for normalized vectors) - `n-1` angular coordinates (θ₁, θ₂, ..., θₙ₋₁) Angular coordinates are in [0, π] except the last which is in [0, 2π].
(cart: &[f32])
| 160 | /// |
| 161 | /// Angular coordinates are in [0, π] except the last which is in [0, 2π]. |
| 162 | fn cartesian_to_spherical(cart: &[f32]) -> Vec<f32> { |
| 163 | let n = cart.len(); |
| 164 | if n == 0 { |
| 165 | return Vec::new(); |
| 166 | } |
| 167 | if n == 1 { |
| 168 | return vec![cart[0]]; |
| 169 | } |
| 170 | |
| 171 | let mut spherical = Vec::with_capacity(n); |
| 172 | |
| 173 | // Radius. |
| 174 | let r: f32 = cart.iter().map(|x| x * x).sum::<f32>().sqrt(); |
| 175 | spherical.push(r); |
| 176 | |
| 177 | // Angular coordinates. |
| 178 | for i in 0..n - 1 { |
| 179 | let sum_sq: f32 = cart[i..].iter().map(|x| x * x).sum::<f32>(); |
| 180 | let denom = sum_sq.sqrt(); |
| 181 | if denom < 1e-30 { |
| 182 | spherical.push(0.0); |
| 183 | } else if i < n - 2 { |
| 184 | spherical.push((cart[i] / denom).acos()); |
| 185 | } else { |
| 186 | // Last angle: atan2 for full [0, 2π] range. |
| 187 | spherical.push(cart[n - 1].atan2(cart[n - 2])); |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | spherical |
| 192 | } |
| 193 | |
| 194 | /// Convert from spherical back to Cartesian coordinates. |
| 195 | fn spherical_to_cartesian(sph: &[f32]) -> Vec<f32> { |