Vector Maths - Cross vectors and a circle on a sphere

Right, I was trying to figure this out on my own for a couple of weeks, but I’ve given up and going to ask the forum. It’s more of a maths question, but hopefully someone can push me in the right direction. I’ve attached an image that should explain it?

I’ve got a ofvector3 that we’ll call v1 (the red dot in the picture)

From this I can easily get V2 (the Yellow dot in the image) by something like v2 = v1 + v1 * extension.

My question is how do I get V3 (the blue dot)?
It’s at right angles to the green line.
I’m eventually looking to generate a circle of vertices (via the for loop/cos/sin method)

I know it has something to do with cross vectors, but that always seems to return 0 for me (possibly because the centre of my sphere is 0,0,0)?

Things I’ve tried:

v3 = v2.getCrossed(v1)

v3.rotate(90,ofVec3f(0,0,1);

None of those seem to give me exactly what I want unfortunately.
Is anyone able to shed any light?

I would do that with ofNode. It will be a lot easier to solve.
there you can use things like: lookAt, orbit, rotateAround…
and if you don’t want to use that object you can get the math from there

Thanks for your replies, I’ll have a look.

Have to say that’s the first time I’m come across ofNode.
I don’t suppose you know of any examples?
It looks like it’s a bit like another matrix.

Hah second time lucky

Usually, the problem is given a plane how can i find a vector perpendicular to that plane, which is where the cross product comes in, usually it comes up when calculating normals for lighting. Indeed a normal is just a line perp to a plane.

In this case you have the vector (the green line) and you want to find the plane it is perpendicular to and then draw the circle (a 2d shape) on that plane, centered around the yellow point

Look at equation 4 here http://mathworld.wolfram.com/NormalVector.html and these
https://www.youtube.com/watch?v=gwk-XGfHR8U
https://www.youtube.com/watch?v=4tN2UCld3Qc

So you use the red and yellow points to find the vector normal, then that normal and the yellow point to find the plane.

Ah, Mr. pants!
Thanks so much. You are a fantastic human!

A lot to learn here for sure.
I’ll take a look through it all.

Had a bit of a weird error where the radius of the circle seems to get smaller when it’s close to (I think) the poles. But I’ll take a look through and try and find out why that happens.

Thanks loads.

Hi all!

I am very interested in this question as well, and I agree the approach by @pants makes a lot of sense.

This is how far I got:
If you take the position (vector) coordinate of a point on a sphere, you can normalize it to get the unit normal vector (the normalized normal vector if that makes sense :wink: of that coordinate (as long as your sphere is centered at the origin (0,0,0). Using the technique in the second video, one can derive the equation of the plane perpendicular to the normal vector.

The circle should now be drawn onto this plane, with the origin of the circle being the original coördinate on the surface of the sphere.
The equations for a circle are:
x = radius * cos(phi)
y = radius * sin(phi)
Somehow these x/y functions now have to be constrained by the equation of the plane we derived earlier (???). This is where I get stuck.

Eventually we should be able to figure this out :smile:

Thanks a lot for any further help!

To quickly add to my previous reply, I found another interesting approach on the following forum:

Check out reply no. 16 for the parametric equation of the circle we are after. I am going to play around with this more tomorrow - it is getting too late for me to be toying around with complex vector math :wink:

Hey yeah that was a good find. I also found this http://math.stackexchange.com/questions/73237/parametric-equation-of-a-circle-in-3d-space, together they explain how to draw a circle in a plane when you have the normal to that plane

The normal you calculate gives you the magnitude of the x/y/z direction. So if you have the normal of a line, you can find any point on that line just by multiplying your x and y coordinates by that normal.

Here is a little app to check, change p1/p2 and it should all work

The (1, 0, 0) vector is the i vector, its just a unit (length 1) vector in the direction of the x axis. You also see j and k vectors they just unit vectors in the y and z axis respectively so (0, 1, 0) and (0, 0, 1).

#include "testApp.h"

ofEasyCam cam;

ofVec3f p1(50, 50, 50);
ofVec3f p2(100, 100, 100);
ofVec3f norm;

ofSpherePrimitive sphere;

//--------------------------------------------------------------
void testApp::setup(){

    ofSetFrameRate(60);
    ofBackground(20);
    sphere.set(10, 10);
    
    norm = (p2 - p1).normalize();

}

//--------------------------------------------------------------
void testApp::update(){
}

//--------------------------------------------------------------
void testApp::draw(){

    ofEnableDepthTest();
    cam.begin();
    ofDrawAxis(100);
    ofSetColor(0, 255, 0);
 
    //draw line segments from p1 in direction of normal
    for (int x = 1; x < 20; x++) {
        ofPoint t1 = p1 + ofVec3f(norm * (x-1)) * 10;
        ofPoint t2 = p1 + ofVec3f(norm * x) * 10;
        ofLine(t1, t2);
    }

    sphere.setRadius(10);
    
    ofSetColor(255, 0, 0);
    sphere.setPosition(p1);
    sphere.draw();
    
    ofSetColor(255, 255, 0);
    sphere.setPosition(p2);
    sphere.draw();
    
    ofSetColor(0, 0, 255);

    sphere.setRadius(2);

    int r = 50; //radius of the circle
    
    //parametric equation of a circle radius r centered at point p2 in plane with normal norm
    //http://math.stackexchange.com/questions/73237/parametric-equation-of-a-circle-in-3d-space
    
    ofVec3f u = norm.crossed(ofVec3f(1, 0, 0)); //x axis unit vector
    ofVec3f v = norm.crossed(u);
    
    for (int t = 0; t < 360; t += 10) {
        float rad = ofDegToRad(t);
        float x = p2.x + r * cos(rad) * u.x + r * sin(rad) * v.x;
        float y = p2.y + r * cos(rad) * u.y + r * sin(rad) * v.y;
        float z = p2.z + r * cos(rad) * u.z + r * sin(rad) * v.z;
        sphere.setPosition(x, y, z);
        sphere.draw();
    }
    
    cam.end();
    ofDisableDepthTest();
}

Thank you very much @pants !
It works like a charm.

—EDIT—

One final addition to the code by Pants - in case other people want to use this too. I noticed the radius of the circle is not consistent and varies depending on the location of vector position p2.
The reason for this has to do with the explanation given here: http://www.physicsforums.com/showthread.php?t=123168

You need to normalize vectors u and v as well, before using them to draw the circle (so simply call u.normalize(); and v.normalize(); ). Then the circle will (always) have the exact radius r.

Hey thanks man, good catch.

You can also do the update in one line like this

    float rad = ofDegToRad(t);
    ofVec3f pt = p2 + r * cos(rad) * u + r * sin(rad) * v;
    sphere.setPosition(pt);