rustrust-ndarray

Converting an Array2 to Polar Coordinates


I am struggling to convert an Array2 of Cartesian Coordinates to Polar Coordinates. The two columns of each row have to be mutated based on each others values, and I can't figure out how to make it.

After different trials, I implemented the following code, but I think it is a dead end:

use ndarray::{array, Axis};
use num_traits::float::Float;

fn main() {
    let mut coords = array![[1., 0.], [1. / 2., (3.).sqrt() / 2.0], [0., 1.]];


    for mut row in coords.axis_iter_mut(Axis(0)) {
        let col_0 = row.get(0).unwrap();
        let col_1 = row.get(1).unwrap();

        let mut row_polar_coord = array![
            (col_0.powi(2) + col_1.powi(2)).sqrt(),
            (col_1 / col_0).atan()
        ];
        //row = row_polar_coord;
        // Error: mismatched types
        //   expected struct `ndarray::ArrayBase<ndarray::ViewRepr<&mut {float}>, _>`
        //   found struct `ndarray::ArrayBase<ndarray::OwnedRepr<{float}>, _>`
        row = row_polar_coord.view_mut();
        // Diagnostics:
        // `row_polar_coord` does not live long enough
        // borrowed value does not live long enough
    }

}

How should be handled these kinds of transformations in ndarray?


Solution

  • I would suggest not using an ndarray to store the real and imaginary part of your values but a tuple. This has way less overhead.

    For inplace mutation you can use map_inplace():

    use ndarray::{array, Axis};
    
    fn main() {
        let mut coords = array![(1_f32, 0_f32), (1. / 2., (3_f32).sqrt() / 2.0), (0., 1.)];
    
        coords.map_inplace(|(a,b)| {
            let c = (a.powi(2) + b.powi(2)).sqrt();
            let d =  (*b / *a).atan();
            *a = c;
            *b = d;
        });
        
        print!("{:?}", coords);
    
    }
    

    When you really need to stick to this input you can do

    use ndarray::{array, Axis};
    
    fn main() {
        let mut coords = array![[1_f32, 0_f32], [1. / 2., (3_f32).sqrt() / 2.0], [0., 1.]];
    
        coords.axis_iter_mut(Axis(0)).for_each(|mut x| {
            let a : f32 = *x.get(0).unwrap();
            let b : f32 = *x.get(1).unwrap();
        
            x[0] = (a.powi(2) + b.powi(2)).sqrt();
            x[1] =  (b / a).atan();
        });
        
        print!("{:?}", coords);
    
    }