Spherical Coordinates and Angle back to Origin?

Alright, so I’ve been Googling for several days and cannot figure how to solve what I think is rather simple…? I’ve also searched the forum here and will list at the end some of the links I’ve explored.

Context: In 2D I can find the angle from one point to another using atan2 and create a line from one point in the direction of the other point with any desired length. I have some sample code below that has an origin at the center of the window and a secondary point that is essentially the mouseX and mouseY values. A line points from mouseX and mouseY towards the origin.x and origin.y.

Problem: My question is what is the equivalent to the above 2D solution in 3D? Create a line from one point with a given radius towards another in 3D space. From my searching I can place a point with x, y, and z values on the surface of a sphere given an origin, radius, theta, and phi. I believe this is called spherical to Cartesian coordinates. However, I cannot seem to be able to draw a line from a 3D point on the sphere surface back to the origin. I can seem to get theta and phi from a point on a sphere surface that when converted to Cartesian coordinates returns the origin point.

2D example:

``````PVector origin;      // center of window
PVector target;      // mouse position

void setup() {
size(500, 500, P3D);
origin = new PVector(width/2, height/2);
target = new PVector();
}

void draw() {
background(255);

// set target to mouse position
target.x = mouseX;
target.y = mouseY;
target.z = 100;

// calculate angle from target/mouse to origin point
float angle = atan2(origin.y - target.y, origin.x - target.x);

// caluclate new point form target towards origin with length radius
float x = target.x + cos(angle) * radius;
float y = target.y + sin(angle) * radius;

// display origin and angle
fill(0);
stroke(0);
strokeWeight(10);
point(origin.x, origin.y, origin.z);
strokeWeight(5);
line(target.x, target.y, x, y);

// what is the equivalent in 3D?
// how can i draw a line with radius 50 from target pointing towards origin?
}
``````

From my searching I’ve found the following:

``````float dx = origin.x - target.x;
float dy = origin.y - target.y;
float dz = origin.z - target.z;

float theta = atan2(dz, dx);
float phi = atan2(sqrt(sq(dz) + sq(dx)), dy)
// or:
float phi = atan2(sqrt(sq(dz) + sq(dx)), dy) * PI

// this can be converted to new points
// however this does not point back to origin
float x = target.x + radius * sin(phi) * cos(theta);
float y = target.y + radius * sin(phi) * sin(theta);
float z = target.z + radius * cos(phi);

``````

I tried exploring the code from this question as well to no success:

Any tips or suggestions would be greatly appreciated.

1 Like

Hi @ASHER,

Welcome to the forum!

Thanks for the well written post!

First thing I would like to point out is that the 2D example can be simplified with vector math (without using atan2). In fact you can do the following:

(pseudocode below)

``````PVector mouseToCenter = center - mouse
PVector directionNormalized = mouseToCenter.normalize()
PVector lineEnd = center + directionNormalized * lineLength
``````
``````float lineLength = 50;

void setup() {
size(500, 500);
}

void draw() {
background(255);

PVector mouse = new PVector(mouseX, mouseY);
PVector center = new PVector(width / 2, height / 2);

PVector direction = PVector.sub(center, mouse).normalize();
PVector lineEnd = PVector.add(mouse, PVector.mult(direction, lineLength));

strokeWeight(5);
line(mouse.x, mouse.y, lineEnd.x, lineEnd.y);
}
``````

And in 3D this is the same computation but with one more dimension. Here with an animation around a sphere with a radius:

``````float lineLength = 50;
float time = 0;

void setup() {
size(500, 500, P3D);
}

void draw() {
background(255);

translate(width / 2, height / 2);

PVector center = new PVector(0, 0, 0);

PVector direction = PVector.sub(center, lineOrigin).normalize();
PVector lineEnd = PVector.add(lineOrigin, PVector.mult(direction, lineLength));

strokeWeight(5);
line(lineOrigin.x, lineOrigin.y, lineOrigin.z, lineEnd.x, lineEnd.y, lineEnd.z);

time += 0.1;
}
``````

Of course you can still use spherical coordinates and convert it to cartesian but I find the above solution simpler (if it suits your needs)

3 Likes

Hello @ASHER ,

Some code I wrote to convert:

• spherical to Cartesian
• Cartesian to spherical < To compare to above!
``````// Spherical Coordinate System
// v1.0.0
// GLV 2022-11-19

// Reference:
// https://en.wikipedia.org/wiki/Spherical_coordinate_system

void setup()
{
size(500, 500, P3D);
background(255);
frameRate(60); //Default
}

float theta;
float phi;

void draw()
{
//background(255);

translate(width/2, height/2);

//phi = random(0, TAU);
phi = random(-TAU/2, TAU/2);
theta = random(0, TAU/2);
println( nf(degrees(phi), 3, 1), nf(degrees(theta), 3, 1) );
//println(nf((degrees((phi + TAU)%TAU)), 3, 1), nf(degrees(theta), 3, 1)); // Converts to 0 to TAU

float x = radius * sin(theta) * cos(phi);
float y = radius * sin(theta) * sin(phi);
float z = radius * cos(theta);

theta = acos(z/200);
phi = atan2(y, x);

// See atan2() reference
// Values returned are PI to -PI
println( nf(degrees(phi), 3, 1), nf(degrees(theta), 3, 1) );
//println(nf((degrees((phi + TAU)%TAU)), 3, 1), nf(degrees(theta), 3, 1)); // Converts to 0 to TAU
println();

strokeWeight(1);
stroke(128);
line(0, 0, 0, x, y, z);

strokeWeight(4);
stroke(0, 255, 0);
line(x, y, z, x-x/4, y-y/4, z-z/4);

strokeWeight(10);
stroke(255, 0, 0);
point(x, y, z);

strokeWeight(10);
stroke(255, 0, 0);
point(0, 0, 0);
}
``````

`:)`