Spherical coordinates

Hi there, please could somebody show me how to get the same x,y,z result but having the origin at c? I appreciate this is mainly a maths problem and sorry if has been answered before but I have been searching/trying to work this out for days now. Thank you

    PVector a; 
    PVector b;
    PVector c;

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

      a = new PVector(300, 154, 407);
      b = new PVector(0, 0, 0);  
      c = new PVector(55, 233, 82);    
    }

    void draw(){
      background(255); 

      float rad = PVector.dist(a, b);
      float theta = atan2(a.z, a.x);
      float phi = acos(a.y/rad);  

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

      println(x,y,z);
    }

Answers

  • Answer ✓

    The solution is to subtract the origin coordinates from the vector a before calculating the spherical coordinates.

    When transforming back to cartesian coordinates you need to add the origin coordinates after calculating the cartesian coordinates.

    If you are going to be doing a lot of these calculations then I suggest you creates functions to do it for you.

  • Out of curiosity I have created two functions to convert

    cartesian --> spherical coordinates, and
    spherical --> cartesian coordinates

    If you want, I will post them here provided you assure me that it is not part of some academic assessment.

  • Thanks very much quark,

    I assure you my academic years are well behind me and use processing purely as a hobby.

  • edited April 2018 Answer ✓

    OK well here is the code. Hopefully the comments explain what is happening but if you have any questions please ask.

    /**
     Cartesian <--> Spherical conversion methods about any origin.
    
     In the methods below :
     All angles are in radians.
     The PVector xyz represents the cartsian coordinates [x, y, z]
     The PVector rtp represents the spherical coordinates [radius, theta, phi]
    
     The methods are designed to avoid unneccesasry PVector object creation 
     for efficiancy reasons.
    
     These methods use the float datatype throughout so there will be some 
     rounding errors but will still be accurate to 7 significant digits. This
     will have no visible effect in the vast majority of sketches so is no 
     cause for concern.
    
     created by Quark 2018
     */
    
    void setup() {
      // Test using origin [0,0,0]
      testConversion(new PVector(300, 154, 407), null);
      // Test using origin [55, 233, 82]
      PVector org = new PVector(55, 233, 82);
      testConversion(new PVector(300, 154, 407), org);
    }
    
    void testConversion(PVector xyz, PVector origin) {
      PVector v0 = cartesianToSpherical(xyz, null, origin);
      PVector v1 = sphericalToCartesian(v0, null, origin);
      println(xyz, "->", v0, "->", v1);
    }
    
    /**
     Convert a set of cartesian coordinates to spherical coordinates.
     The cartesian coordinates are about the origin [0,0,0] unless 
     another origin is specified.
    
     @ param xyz cartesian coordinates to convert
     @ param rtp PVector to hold caculated spherical coordinates (optional)
     @ param origin the xyz coordinates origin in 3D space (optional)
     @ return a PVector holding the spherical coordinates
     */
    PVector cartesianToSpherical(PVector xyz, PVector rtp, PVector origin) {
      // Create a new PVector only if the user has not provided one
      if (rtp == null) {
        rtp = new PVector();
      }
      // In most cases the origin will be [0,0,0] this avoids the need to create a
      // PVector when an origin is not provided
      float ox = xyz.x, oy = xyz.y, oz = xyz.z;
      if (origin != null) {
        ox -= origin.x;
        oy -= origin.y;
        oz -= origin.z;
      }
      float rad = sqrt(ox*ox + oy*oy + oz*oz);
      if (rad != 0) {
        rtp.x = rad;
        rtp.y = atan2(oy, ox);
        rtp.z = acos(oz / rad);
      }
      return rtp;
    }
    
    /**
     Convert a set of spherical coordinates to cartesian coordinates.
     The spherical coordinates are about the origin [0,0,0] unless 
     another origin is specified.
    
     @ param rtp spherical coordinates to convert
     @ param xyz PVector to hold caculated cartesian coordinates (optional)
     @ param origin the xyz coordinates origin in 3D space (optional)
     @ return a PVector holding the cartesian coordinates
     */
    PVector sphericalToCartesian(PVector rtp, PVector xyz, PVector origin) {
      // Create a new PVector only if the user has not provided one
      if (xyz == null) {
        xyz = new PVector();
      }
      // In most cases the origin will be [0,0,0] this avoids the need to create a
      // PVector when an origin is not provided
      float ox=0, oy=0, oz=0;
      if (origin != null) {
        ox = origin.x;
        oy = origin.y;
        oz = origin.z;
      }
      float sin_p = sin(rtp.z);
      xyz.x = rtp.x * cos(rtp.y) * sin_p + ox;
      xyz.y = rtp.x * sin(rtp.y) * sin_p + oy;
      xyz.z = rtp.x * cos(rtp.z) + oz;
      return xyz;
    }
    
  • Thanks again quark :)

Sign In or Register to comment.