UPDATE 04/24/12: a little more robust (and “mildly” documented) version has been on github for a while, just forgot to update this post. Here’s the link: https://github.com/moagrius/Point/blob/master/Point.js. I have a *really* sugary-y version as well I’m considering posting, but haven’t had the time to debug as thoroughly as I’d like. Feel free to comment if you’d like to volunteer.

UPDATE 09/01/11: added 2 more sugar methods: .degreesTo, which gives back degrees from calling instance to another point, and .orbit, to obtain a position from passed distances and degrees.

port from the AS3 Point Class. Obviously, JS doesn’t have getters/setters so the .length property had to become a method. Also added two sugar methods, just adding .distance and .interpolate as instance methods (AS3 just has them as static methods that take two Points as arguments – the instance methods function the same way but take a single “other” Point instead of two distinct Point instances).

Param names, variables names, etc are the same as shown in the livedocs link above.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
function Point(x, y){ this.x = x || 0; this.y = y || 0; }; Point.prototype.x = null; Point.prototype.y = null; Point.prototype.add = function(v){ return new Point(this.x + v.x, this.y + v.y); }; Point.prototype.clone = function(){ return new Point(this.x, this.y); }; Point.prototype.degreesTo = function(v){ var dx = this.x - v.x; var dy = this.y - v.y; var angle = Math.atan2(dy, dx); // radians return angle * (180 / Math.PI); // degrees }; Point.prototype.distance = function(v){ var x = this.x - v.x; var y = this.y - v.y; return Math.sqrt(x * x + y * y); }; Point.prototype.equals = function(toCompare){ return this.x == toCompare.x && this.y == toCompare.y; }; Point.prototype.interpolate = function(v, f){ return new Point( v.x + (this.x - v.x) * f, v.y + (this.y - v.y) * f ); }; Point.prototype.length = function(){ return Math.sqrt(this.x * this.x + this.y * this.y); }; Point.prototype.normalize = function(thickness){ var l = this.length(); this.x = this.x / l * thickness; this.y = this.y / l * thickness; }; Point.prototype.orbit = function(origin, arcWidth, arcHeight, degrees){ var radians = degrees * (Math.PI / 180); this.x = origin.x + arcWidth * Math.cos(radians); this.y = origin.y + arcHeight * Math.sin(radians); }; Point.prototype.offset = function(dx, dy){ this.x += dx; this.y += dy; }; Point.prototype.subtract = function(v){ return new Point(this.x - v.x, this.y - v.y); }; Point.prototype.toString = function(){ return "(x=" + this.x + ", y=" + this.y + ")"; }; Point.interpolate = function(pt1, pt2, f){ return pt1.interpolate(pt2, f); }; Point.polar = function(len, angle){ return new Point(len * Math.cos(angle), len * Math.sin(angle)); }; Point.distance = function(pt1, pt2){ var x = pt1.x - pt2.x; var y = pt1.y - pt2.y; return Math.sqrt(x * x + y * y); }; |

Nice example, however JavaScript does have getters/setters. I suggest adding this replacement:

Object.defineProperty(Point.prototype, “length”, {

get: function() { return Math.sqrt(this.x * this.x + this.y * this.y); }

});

Hey Jon,

Thanks for the comment. Unfortunately, defineProperty is not broadly supported: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty#Browser_compatibility

Hi Jon.

I was about to start porting Point myself, now I don’t need to – nice one!

On the getter/setter debate, if it’s just a getter you want, could you not make the ‘length’ function self executing? like this –

Point.prototype.length = function(){

return Math.sqrt(this.x * this.x + this.y * this.y);

}();

Hi York,

You’ll notice that the length() method is already implemented, above.

Thanks for your comment.

Hey moagrius, looks like you misunderstood York’s comment. Notice the () at the end of function declaration. See http://markdalgleish.com/2011/03/self-executing-anonymous-functions/

Ah, you’re right, I didn’t notice that. Sorry York! Thanks for pointing that out Ricochet

Add these, love you’re work! was looking for this…

P.prototype.Add = function (p) {this.x += p.x;this.y += p.y;};

P.prototype.Sub = function (p) {this.x -= p.x;this.y -= p.y;};

P.prototype.Dev = function (p) {this.x /= p.x;this.y /= p.y;};

P.prototype.Mul = function (p) {this.x *= p.x;this.y *= p.y;};

P.prototype.Match = function (p) {return this.x == p.x || this.y == p.y;};

P.prototype.Greater = function (p) {return this.x > p.x && this.y > p.y;};

P.prototype.Above = function (p) {return this.x > p.x || this.y > p.y;};

P.prototype.Less = function (p) {return this.x < p.x || this.y < p.y;};

P.prototype.Beneath = function (p) {return this.x < p.x && this.y < p.y;};

P.prototype.Set = function (p) {this.x = p.x;this.y = p.y;};

This is very old, but that’s exactly what I needed, thank you.

However, I had different results with exact same data between AS3 & JS on the polar function.

x and y (cos and sin) seem interverted, looks like AS3 version is in fact:

return new Point(len * Math.cos(angle), len * Math.sin(angle));

Made the change and now I get the exact same results than with AS3, thank you very much.

GTK. I’ll make the updates soon – thanks for pointing it out

Forgive me for posting on such an old topic, but what license is this under? Can I use this for a project?

No problem, and yes you can use it. I just added an MIT license to the Github Repo.

Awesome, thank you!

Hi,

Thanks for your great work.

I think your implementation of interpolate is wrong. Definition of interpolate in AS3 is:

“Determines a point between two specified points. The parameter f determines where the new interpolated point is located relative to the two end points specified by parameters pt1 and pt2. The closer the value of the parameter f is to 1.0, the closer the interpolated point is to the first point (parameter pt1). The closer the value of the parameter f is to 0, the closer the interpolated point is to the second point (parameter pt2).”

Thus, correct implementation is:

return new Point( pt2.x + (pt1.x – pt2.x) * f, pt2.y + (pt1.y – pt2.y) * f )

or

return pt2.add(new Point( (pt1.x – pt2.x) * f, (pt1.y – pt2.y) * f ) )

You are correct, great catch, thanks. Updating now.