Help needed pivoting a line in 3D

edited October 2013 in How To...

I need to figure out how to manipulate few equations that I have to rotate a single line in a 3D space using Processing.

I am getting the xyz coordinate values from a real gyroscope that I can rotate freely.

For the purposes of my application, the first point of the line is fixed to the origin, thus, my line function is now:

line(0, 0, 0, x, y, z);

I need to rotate my line in a manner that reaches any possible position.

For the distance, I am using the known formula of the distance:

d = sqrt(x*x + y*y + z*z);

Before continue, let me clarify something very important regarding how I am reading the x, y and z coordinate values from the gyroscope.

Each coordinate contains circular values between 0 to 360 degrees. In other words, if I rotate 360 degrees the gyro laying on my table, the z coordinate will change from 0 to 360. Similarly for the other two axis.

So far I can rotate the line perfectly but one axis at a time. I.e.

For rotating around the axis z, I am using:

    x = d * cos(z)
    y = d * sin(z)

For rotating around the axis y, I am using:

    z = d * cos(y)
    x = d * sin(y)

For rotating around the axis x, I am using:

    y = d * cos(x)
    z = d * sin(x)

My problem starts when I try to put them together:

I have tried the following:

y1 = d * sin(z);
x2 = d * cos(z);
x1 = d * sin(y);
z2 = d * cos(y);
z1 = d * sin(x);
y2 = d * cos(x);

x = (x2+x1);
y = (y1+y2);
z = (z1+z2);

When I rotate the line using the above equations, the line pivots almost correctly but at some positions its length starts to change or even becomes zero.

Again, what I just need is to find a way to generate x, y and z that permits the line to rotate freely (with the distance fixed of course).

As you may have noticed, my problem is more related to a Math approach than programming. That is why I have pot posted any code yet.

Thank you very much in advance for any comment.

Answers

  • _vk_vk
    edited October 2013

    I think it may be:

    x = x + cos(a)*fixedLength

    same for others...

  • edited October 2013

    Note that Processing has a built-in dist() function...

    Also, moved this topic to the How to... section as it is more appropriate there.

  • Thank you _vk and calsign for your comments.

    After running some tests I have found out why the length of my line changes (greater or lesser). The reason is that in my formulas the second point of the line (x,y,z) does not depend upon the distance but on the value of the sine and cosine functions, therefore, when the gyro at different planes generates complementary angles that make the sine value equals but opposite to the cosine value, then, when I totalize them I get any coordinate value (greater or lesser).

    For example, at certain position of the gyro I get: y=224 and z=314 then

    x1 = d * sin(y) = d * sin(224) = -0.69d
    x2 = d * cos(z) = d * cos(314) =  0.69d
    

    Consequently

    x = x1 + x2 = -0.69d + 0.69d = 0.

    Therefore, the addition of the partial axis from different planes is no longer appropriate. That is why I don't have problems when combining one plane at a time.

    So I need to redefine my formulas in order to achieve my goal.

  • I think your best bet would be to use Matrices. You could then multiply the coordinates of the "free" end of the line by a rotation matrix which could have the angle from the gyro in it. This will allow you to simply multiply the x,y,and z rotations of the point and the length of the line will remain fixed. Google "3d rotation about origin". It is really not as difficult as it looks at first. Hope this helps.

  • edited November 2013

    here is a code that takes mouseX and mouseY (so only two angles (simulated) and not three as in your case)

    but the results are weird, he is rotating but....

    maybe somebody can clarify this.

    When I have the mouseY in the middle (=height/2) and rotate by going right with my mouseX, all looks fine (rotates around Y-axis)

    but:

    when I go with the mouseY down, it's still ok

    but when I change the mouseX then, he's not rotating around the Y-axis anymore but around the current angle invoked by mouseY

    how can I solve this?

    I rather want that also in the 2nd case he always rotates around the y-axis (fixed y-axis when moving mouseX left and right)

    //  ======================== 
    
    float CameraX;
    float CameraY;
    float angle;
    
    float thetaxz;
    float thetaxy;
    
    //
    
    void setup()
    {
      size( 800, 800, P3D );
      CameraX = width / 2.0;
      CameraY = 50;
      //
    } // setup
    
    
    
    void draw()
    {
      background(0);
      lights();
      // camera
      camera(
      CameraX, CameraY, 700, 
      0, 0, 0, 
      0, 1, 0);
    
      // Floor
      drawFloor();
      // ==================================================
      // sphere 
      fill(222, 111, 111);
      noStroke();
      sphere (32);
      // ==================================================
    
      // http://stackoverflow.com/questions/8602408/3d-rotation-around-the-origin
    
      float d = 211;
      float theta= map(mouseX, 0, width, 0, 2*PI);         // mouse x rotates around the y-axis
      float phi  = map(mouseY, 0, height, +PI/2, -PI/2);   // mouse y rotates around the z-axis
    
    
    
      float x = d*cos(theta)*cos(phi);
      float y = d*cos(theta)*sin(phi);
      float z = d*sin(theta);
    
    
      MyBox(0, 0, 0, 
      x, y, z, 
      14, 
      color(0, 0, 244));
    
    
    
      // ==================================================
    } // draw
    
    void keyPressed() {
      if (key == CODED) {
        //
        if (keyCode == UP) {
          CameraY-=10;
          // println("UP");
        }
        else if (keyCode == DOWN) {
          CameraY+=10;
        }
        else if (keyCode == RIGHT) {
          CameraX+=10;
        }
        else if (keyCode == LEFT) {
          CameraX-=10;
        }
        else {
          // nothing
        }
      }
      else {  
        // not key == CODED
        //
      }
    }
    
    void MyBox(float x1, float y1, float z1, 
    float x2, float y2, float z2, 
    float weight, 
    color strokeColour)
    // was called drawLine; programmed by James Carruthers
    // see http://processing.org/discourse/yabb2/YaBB.pl?num=1262458611/0#9
    {
      PVector p1 = new PVector(x1, y1, z1);
      PVector p2 = new PVector(x2, y2, z2);
      PVector v1 = new PVector(x2-x1, y2-y1, z2-z1);
      float rho = sqrt(pow(v1.x, 2)+pow(v1.y, 2)+pow(v1.z, 2));
      float phi = acos(v1.z/rho);
      float the = atan2(v1.y, v1.x);
      v1.mult(0.5);
      pushMatrix();
      translate(x1, y1, z1);
      translate(v1.x, v1.y, v1.z);
      rotateZ(the);
      rotateY(phi);
      noStroke();
      fill(strokeColour);
      box(weight, weight, p1.dist(p2)*1.2);
      popMatrix();
    }
    
    void drawFloor() {
      stroke(255);
      // draw floor: 
      float floorY=600;
      // to right (background)
      line ( -200, floorY, -200, 
      width-20, floorY, -200);
      // to right (in the front)
      line ( -200, floorY, -0, 
      width-20, floorY, -0);
      // left side 
      line ( 20, floorY, -200, 
      20, floorY, -0);
      // right side   
      line ( width-20, floorY, -200, 
      width-20, floorY, -0);
    }
    //
    
  • edited November 2013

    In reference to my initial question about pivoting a line in 3D, I just resolved it. I only needed two angles: theta (polar angle) and phi (azimuth) which corresponded to my y and z values from the gyro angles. Then, I use the following formulas (spherical coordinate system to Cartesian coordinates) to calculate the second point:

    x = d * sin(radians(y)) * cos(radians(z));
    y = d * sin(radians(y)) * sin(radians(z));
    z = d * cos(radians(y));
    

    I took the formulas from here: en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates

    Regards!

Sign In or Register to comment.