/* * === Geometory Two-Point Class === * * updated 2003/07/02 * * mail : peace@skipup.com * home : http://www.skipup.com/~peace/ */ /** * 2次元座標,2次元ベクトルを扱う. * インスタンス変数 * number x * number y */ function class__Point__(window) { var classId = Object.getClassName(arguments.callee); /** * void apply(Point p, Argument a) */ function apply(o, a) { switch (a.length) { case 0 : default : o.x = o.y = 0.0; return; case 1 : // Point || Array || Argument || Other var s = a[0]; if (typeof s == "object") { if (s.constructor === F) { // Point o.x = s.x; o.y = s.y; } else if (s.constructor === Array) { // Array o.x = s[0]; o.y = s[1]; } else if (s.callee !== void 0) { // Arguments apply(o, s); } else { // Other o.x = o.y = s; } } else { o.x = o.y = s; } return; case 2 : // number, number || other, other o.x = a[0]; o.y = a[1]; return; } } /** * コンストラクタ. * Point() * Point(number n) * Point(Point p) * Point(number[] ary) * Point(arguments arg) * Point(number x, number y) */ var F = window[classId] = function() { if (this.constructor !== F) this.constructor = F; apply(this, arguments); }; var FP = F.prototype; /** * void absolute() * void absolute(Point p) */ FP.absolute = function(p) { if (arguments.length == 0) { this.x = this.x >= 0.0 ? this.x : -this.x this.y = this.y >= 0.0 ? this.y : -this.y } else { this.x = p.x >= 0.0 ? p.x : -p.x this.y = p.y >= 0.0 ? p.y : -p.y } }; /** * void add(Point p) * void add(Point p0, Point p1) */ FP.add = function(p0, p1) { if (arguments.length == 1) { this.x += p0.x; this.y += p0.y; } else { this.x = p0.x + p1.x; this.y = p0.y + p1.y; } }; /** * boolean equals(Object p) */ FP.equals = function(p) { if (p == null || p.constructor !== F) return false; return this.x === p.x && this.y === p.y; }; /** * boolean epsilonEquals(Point p, double eps) */ FP.epsilonEquals = function(p, e) { var d = this.x - p.x; if ((d >= 0.0 ? d : -d) > e) return false; d = this.y - p.y; return (d >= 0.0 ? d : -d) <= e; }; /** * boolean intEquals(Point p) */ FP.intEquals = function(p) { return Math.floor(this.x) == Math.floor(p.x) && Math.floor(this.y) == Math.floor(p.y); }; /** * 内分点. * void interpolate(Point p, double d) * @param d 0.0 <= d <= 1.0. * * void interpolate(Point p0, Point p1, double d) * @param d 0.0 <= d <= 1.0. */ FP.interpolate = function(p0, p1, p2) { if (arguments.length == 2) { this.x = (1.0 - p1) * this.x + p1 * p0.x; this.y = (1.0 - p1) * this.y + p1 * p0.y; } else { this.x = (1.0 - p2) * p0.x + p2 * p1.x; this.y = (1.0 - p2) * p0.y + p2 * p1.y; } }; /** * void negate() * void negate(Point p) */ FP.negate = function(p) { if (p === void 0) p = this; this.x = -p.x; this.y = -p.y; }; /** * void scale(double v) * void scale(double v, Point p) */ FP.scale = function(p0, p1) { if (arguments.length == 1) { this.x *= p0; this.y *= p0; } else { this.x = p1.x * p0; this.y = p1.y * p0; } }; /** * void scaleAdd(double v, Point p) * void scaleAdd(double v, Point p0, Point p1) */ FP.scaleAdd = function(p0, p1, p2) { if (arguments.length == 2) { this.x = this.x * p0 + p1.x; this.y = this.y * p0 + p1.y; } else { this.x = p1.x * p0 + p2.x; this.y = p1.y * p0 + p2.y; } }; /** * void set(...) * 引数の形式,型はコンストラクタに同じ. */ FP.set = function() { apply(this, arguments); }; /** * 極座標でメンバをセット. * void setPolar(double radius, double theta) */ FP.setPolar = function(r, t) { this.x = r * Math.cos(t); this.y = r * Math.sin(t); }; /** * void sub(Point p) * void sub(Point p0, Point p1) */ FP.sub = function(p0, p1) { if (arguments.length == 1) { this.x -= p0.x; this.y -= p0.y; } else { this.x = p0.x - p1.x; this.y = p0.y - p1.y; } }; /** * string toString() */ FP.toString = function() { return "(" + this.x + "," + this.y + ")"; }; /** * 位置ベクトルとの距離. * double distance(Point p) */ FP.distance = function(p) { var x = this.x - p.x, y = this.y - p.y; return Math.sqrt(x * x + y * y); }; /** * double distance2(Point p) */ FP.distance2 = function(p) { var x = this.x - p.x, y = this.y - p.y; return x * x + y * y; }; /** * ベクトルとのなす角. * double angle(Point p) * @return 0.0以上π以下. */ FP.angle = function(p) { var d = (this.x * p.x + this.y * p.y) / Math.sqrt((this.x * this.x + this.y * this.y) * (p.x * p.x + p.y * p.y)); if (d < -1.0) d = -1.0; else if (d > 1.0) d = 1.0; return Math.acos(d); }; /** * 内積. * aベクトルとbベクトルの内積 ab = |a||b|cos(t) * double dot(Point p) */ FP.dot = function(p) { return this.x * p.x + this.y * p.y; }; /** * double length() */ FP.length = function() { return Math.sqrt(this.x * this.x + this.y * this.y); }; /** * double length2() */ FP.length2 = function() { return this.x * this.x + this.y * this.y; }; /** * ベクトルの正規化. * void normalize() * void normalize(Point p) */ FP.normalize = function(p) { if (arguments.length == 0) { var d = 1.0 / Math.sqrt(this.x * this.x + this.y * this.y); this.x *= d; this.y *= d; } else { var d = 1.0 / Math.sqrt(p.x * p.x + p.y * p.y); this.x = p.x * d; this.y = p.y * d; } }; /** * void integer() * void integer(Point p) */ FP.integer = function(p) { if (p === void 0) p = this; this.x = Math.floor(p.x); this.y = Math.floor(p.y); }; /** * number[] toArray() * number[] toArray(number[] ary) */ FP.toArray = function(a) { if (a === void 0) { return new Array(this.x, this.y); } else { a[0] = this.x; a[1] = this.y; return a; } }; /** * boolean isNaN() */ FP.isNaN = function() { return (isNaN(this.x) || isNaN(this.y)) || (this.x === "" || this.y === ""); }; /** * number max() */ FP.max = function() { return this.x > this.y ? this.x : this.y; }; /** * number min() */ FP.min = function() { return this.x < this.y ? this.x : this.y; }; /** * 原点に関して回転. * 回転方向は * X軸(水平方向右側+),Y軸(鉛直方向上側+)とし, * X軸+方向から,Y軸+方向に回す方向を正とする. * void rotate(double theta) * void rotate(double theta, Point p) */ FP.rotate = function(p0, p1) { var c = Math.cos(p0), s = Math.sin(p0); if (arguments.length == 1) { this.x = this.x * c - this.y * s; this.y = this.y * c + this.x * s; } else { this.x = p1.x * c - p1.y * s; this.y = p1.y * c + p1.x * s; } }; } class__Point__(window);