Javascript Geometry: Polar to Cartesian and Back Again

74 views Asked by At

I'm trying to create a program that converts Polar values to Cartesian and back again. I need to be able to switch between the two types without any change in the data.

I've created class types for Polar and Cartesian with methods to convert between the two. But my math is off. Any help would be much appreciated!

class CartesianCoord {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  ToPolarCoord() {
    let p = new PolarCoord();
    p.radius = Math.sqrt(this.x * this.x + this.y * this.y);
    p.angle = Math.atan2(this.y, this.x);
    return p;
  }
}

class PolarCoord {
  constructor(radius, angle) {
    this.radius = radius;
    this.angle = angle;
    //this.angleDegree
  }
  set angleDegree(value) {
    this.angle = (value * 2 * Math.PI) / 360;
  }
  get angleDegree() {
    return (this.angle * 360) / (Math.PI * 2);
  }

  ToCartesianCoord() {
    let c = new CartesianCoord();
    c.x = this.radius * Math.cos(this.angle);
    c.y = this.radius * Math.sin(this.angle);
    return c;
  }
}

let polar = new PolarCoord(279, 18);
console.log(polar + "\n" + polar.radius + " " + polar.angle + " " + polar.angleDegree);

let cart = polar.ToCartesianCoord();
console.log(cart + "\n" + cart.x + " " + cart.y);

let polar2 = cart.ToPolarCoord();
console.log(polar2 + "\n" + polar2.radius + " " + polar2.angle + " " + polar2.angleDegree);

// I want polar and polar2 to be identical

2

There are 2 answers

0
James On

Since Math.atan2 can only return an angle between -Pi and Pi radians, starting angles outside that range won't work.

One way to solve this is to figure out how many extra multiples of 2Pi are included in the initial angle such that we reduce the angle to between -Pi and Pi, so that we can add that many full rotations to the output.

class CartesianCoord {
  constructor(x, y, extraCircles) {
    this.x = x;
    this.y = y;
    this.extraCircles = extraCircles;
  }

  ToPolarCoord() {
    let p = new PolarCoord();
    p.radius = Math.sqrt(this.x * this.x + this.y * this.y);
    p.angle = Math.atan2(this.y, this.x) + this.extraCircles * 2 * Math.PI;
    p.extraCircles = this.extraCircles;
    return p;
  }
}

class PolarCoord {
  constructor(radius, angle) {
    let currentAngle = angle;
    this.extraCircles = 0;
    while (currentAngle > Math.PI) {
      this.extraCircles++
      currentAngle -= 2 * Math.PI;
    }
    while (currentAngle < -Math.PI) {
      this.extraCircles--;
      currentAngle += 2 * Math.PI;
    }
    
    this.radius = radius;
    this.angle = angle;
  }
  set angleDegree(value) {
    this.angle = (value * 2 * Math.PI) / 360;
  }
  get angleDegree() {
    return (this.angle * 360) / (Math.PI * 2);
  }

  ToCartesianCoord() {
    let c = new CartesianCoord();
    c.x = this.radius * Math.cos(this.angle);
    c.y = this.radius * Math.sin(this.angle);
    c.extraCircles = this.extraCircles;
    return c;
  }
}

let polar = new PolarCoord(279, 18);
console.log(polar + "\n" + polar.radius + " " + polar.angle + " " + polar.angleDegree);

let cart = polar.ToCartesianCoord();
console.log(cart + "\n" + cart.x + " " + cart.y);

let polar2 = cart.ToPolarCoord();
console.log(polar2 + "\n" + polar2.radius + " " + polar2.angle + " " + polar2.angleDegree);

// I want polar and polar2 to be identical

0
cupofjoe On

Solved! I was storing my values as radius and degrees. So I needed to set my polar coordinate theta as degrees (not in radians). I've updated the code:

class CartesianCoord
    {
        constructor (x, y) {
            this.x = x;
            this.y = y;
        }

        ToPolarCoord() {
            let p = new PolarCoord();
            p.r = Math.sqrt(this.x * this.x + this.y * this.y);
            p.theta = Math.atan2(this.y, this.x);
            return p;
        }
    }

    class PolarCoord
    {
        // r = r of circle
        // theta = angle in radians, measured from positive X axis
        // thetaDegrees = angle in degrees
        constructor (r, theta, thetaDegrees) {
            this.r = r;
            this.theta = theta;
            this.thetaDegrees = thetaDegrees; 
        }
        
        set thetaDegrees(value) {
            this.theta = (value * 2 * Math.PI) / 360;
        }    
        get thetaDegrees() {
            return (this.theta * 360) / (Math.PI * 2);
        } 

        ToCartesianCoord() {
            let c = new CartesianCoord();
            c.x = this.r * Math.cos(this.theta);
            c.y = this.r * Math.sin(this.theta);
            return c;
        }
    }

    let polar = new PolarCoord();
    polar.r = 18;
    polar.thetaDegrees = 279;
    console.log(polar + "\n" + polar.r + " " + polar.theta + " " + polar.thetaDegrees);

    let cart = polar.ToCartesianCoord();
    console.log(cart + "\n" + cart.x + " " + cart.y);

    let polar2 = cart.ToPolarCoord();
    console.log(polar2 + "\n" + polar2.r + " " + polar2.theta + " " + polar.thetaDegrees);