javascriptprocessing.jskhan-academy

Khan Academy: Cannot read property of undefined


I am programming a library that can transform polygons on Khan Academy, however I keep getting this error:

Cannot read property 'x' of undefined

with no line numbers.

My code:

var Point = function(x,y) {
    this.x = x;
    this.y = y;
};

Point.prototype.rotate = function(around,degrees) {
    angleMode = "degrees";
    var aX = around.x;
    var aY = around.y;
    var cX = this.x;
    var cY = this.y;
    var dist = sqrt(sq(cX-aX)+sq(cY-aY));
    var currentTheta = asin(dist/cY);
    var gamma = degrees+currentTheta;
    this.x = cos(gamma)*dist+aX;
    this.y = sin(gamma)*dist+aY;
};

var Line = function(x1,y1,x2,y2) {
    this.f = new Point(x1,y1);
    this.s = new Point(x2,y2);
};

Line.prototype.draw = function() {
    line(this.f.x,this.f.y,this.s.x,this.s.y);
};

Line.prototype.rotate = function(around,degrees) {
    this.f = this.f.rotate(around,degrees);
    this.s = this.s.rotate(around,degrees);
};

var Polygon = function(x,y){
    if(x.length!==y.length){return;}
    this.sides = x.length;
    this.x = x;
    this.y = y;
    this.lines = new Array(this.sides);
    this.lines[0] = new Line(this.x[this.sides-1],this.y[this.sides-1],this.x[0],this.y[0]);
    for(var i=1;i<this.sides;i++){
        this.lines[i] = new Line(this.x[i-1],this.y[i-1]);
    }
};

Polygon.prototype.draw = function() {
    for(var i=0;i<this.sides;i++){
        this.lines[i].draw();
    }
};

Polygon.prototype.rotate = function(around,degrees) {
    for(var i=0;i<this.sides;i++){
        this.lines[i].rotate(around,degrees);
    }
};

var p = new Polygon([10,20,40],[40,20,15]);

var draw = function() {
    background(255,255,255);
    fill(0,0,0);
    stroke(0,0,0);
    p.rotate(new Point(20,20),1);
    p.draw();
};

I however still do not know why it throws the error, especially because it gives no direction to where the error is.

EDIT


Link to project: Transformation Library


Solution

  • Let's start with your Point class and its rotate() function:

    Point.prototype.rotate = function(around,degrees) {
        angleMode = "degrees";
        var aX = around.x;
        var aY = around.y;
        var cX = this.x;
        var cY = this.y;
        var dist = sqrt(sq(cX-aX)+sq(cY-aY));
        var currentTheta = asin(dist/cY);
        var gamma = degrees+currentTheta;
        this.x = cos(gamma)*dist+aX;
        this.y = sin(gamma)*dist+aY;
    };
    

    This function does some math and sets the this.x and this.y variables. So far so good (disclaimer: I haven't checked this math, but that's not the point). But notice that this function doesn't return anything.

    Now let's go to your Line class and its rotate() function:

    Line.prototype.rotate = function(around,degrees) {  
       this.f = this.f.rotate(around,degrees);
       this.s = this.s.rotate(around,degrees);
    };
    

    This sets the f and s variables to the value returned from the rotate() function. But wait, the rotate() function in the Point class doesn't return anything! So now this.f and this.s are undefined!

    You have a similar problem with your Polygon class calling the Line class's rotate() function.

    So to fix your problem, you either need the rotate() functions to return something, or you need to just call them instead of expecting a return value.

    Taking a step back, I wonder why you're doing all of this yourself. Processing has its own rotate() functions that do all of this for you. Why don't you just use them instead?