Cartesian to Spherical coordinates conversion issue


#1

Hi everyone,

I am trying to convert the cartesian coordinates a PVector in 3D space, with coordinates (x, y, z) in spherical coordinates (so obtaining radius, theta and phi).

Below is the code I am testing, rarely it “works”, I guess there is something wrong so something is just inverted.

import peasy.*;
PeasyCam cam;

PVector p;

void setup() {
  size(600, 600, P3D);
  
  cam = new PeasyCam(this, 500);
  
  // the vector with cartesian coordinates
  p = PVector.random3D();
  p.mult(100);
}

void draw() {
  background(0);
  
  // lines for the coordinate axis
  stroke(100, 100, 255);
  line(-width, 0, 0, width, 0, 0);
  
  stroke(100, 255, 100);
  line(0, 0, width, 0, 0, -width);
  
  stroke(255, 100, 100);
  line(0, -height, 0, 0, height, 0);
  
  // the cube with cartesian coordinates
  pushMatrix();
  translate(p.x, p.y, p.z);
  fill(255);
  stroke(255, 100, 100);
  noFill();
  box(50);
  popMatrix();
  
  //conversion into spherical coordinates
  float radius = sqrt(sq(p.x) + sq(p.y) + sq(p.z));
  float theta = atan(p.y/p.x);
  float phi = acos(p.z/radius);
  
  float x = radius * cos(theta) * sin(phi);
  float y = radius * sin(theta) * sin(phi);
  float z = radius * cos(phi);
    
  pushMatrix();
  translate(x, y, z);
  stroke(100, 255, 100);
  noFill();
  box(25);
  popMatrix();
}

In the image, the red cube is the vector in cartesian coordinates, the green one the conversion in the code.

As a reference I am following the Spherical Coordinates page on Wolfram.

Where am I wrong?

Thank you in advance!


#2

i think there is a math problem,
i rearranged your code so it is more easy to play again ( key == ‘a’ )
and i see every time p.x - negative the result is wrong.
else it works.

so i limit p.x by

abs(p.x);

or use:

theta = atan2(p.y,p.x);

good practice is just to print the data!

import peasy.*;
PeasyCam cam;

PVector p;
float radius, theta, phi, x, y, z;

void setup() {
  size(600, 600, P3D);
  cam = new PeasyCam(this, 500);
  make_vector();   // the vector with cartesian coordinates
}

void make_vector() {
  p = PVector.random3D();
  p.mult(100);
  // http://mathworld.wolfram.com/SphericalCoordinates.html
  // https://en.wikipedia.org/wiki/Spherical_coordinate_system
  // https://en.wikipedia.org/wiki/Atan2
  // p.x = abs(p.x);           //kll way 1: limit x to first quadrant:
  radius = sqrt(sq(p.x) + sq(p.y) + sq(p.z));     //conversion into spherical coordinates

//  theta = atan(p.y/p.x);
  theta = atan2(p.y,p.x);

  phi = acos(p.z/radius);
  x = radius * cos(theta) * sin(phi);
  y = radius * sin(theta) * sin(phi);
  z = radius * cos(phi);
  println(" p.x "+nf(p.x,1,1)+" p.y "+nf(p.y,1,1)+" p.z "+nf(p.z,1,1)+
          " radius "+nf(radius,1,1)+" theta "+nf(theta,1,1)+" phi "+nf(phi,1,1)+
          " x "+nf(x,1,1)+" y "+nf(y,1,1)+" z "+nf(z,1,1));
}

void draw_axis() {
  background(0);
  // lines for the coordinate axis
  stroke(100, 100, 255);
  line(-width, 0, 0, width, 0, 0);
  stroke(100, 255, 100);
  line(0, 0, width, 0, 0, -width);
  stroke(255, 100, 100);
  line(0, -height, 0, 0, height, 0);
}

void draw_qcart() {            // the cube with cartesian coordinates
  pushMatrix();
  translate(p.x, p.y, p.z);
  fill(255);
  stroke(255, 100, 100);
  noFill();
  box(50);
  popMatrix();
}

void draw_qsphere() {        // spherical coordinates
pushMatrix();
translate(x, y, z);
stroke(100, 255, 100);
noFill();
box(25);
popMatrix();
}

void draw() {
  background(0);
  draw_axis();
  draw_qcart();
  draw_qsphere();
}

void keyPressed() {
  if ( key == 'a' ) make_vector();
}
  

http://mathworld.wolfram.com/SphericalCoordinates.html

The inverse tangent denoted in φ = arctan y / x must be suitably defined, taking into account the correct quadrant of ( x , y ).


#3

Great! Thanks @kll it worked!