199 lines
4.1 KiB
JavaScript
199 lines
4.1 KiB
JavaScript
'use strict';
|
|
function Rectangle(x, y, w, h) { // new Rectangle(bounds) or new Rectangle(x, y, w, h)
|
|
if (!(this instanceof Rectangle)) {
|
|
return new Rectangle(x, y, w, h);
|
|
}
|
|
var x2, y2, p;
|
|
|
|
if (x.x) {
|
|
w = x.w;
|
|
h = x.h;
|
|
y = x.y;
|
|
if (x.w !== 0 && !x.w && x.x2) {
|
|
w = x.x2 - x.x;
|
|
h = x.y2 - x.y;
|
|
}
|
|
else {
|
|
w = x.w;
|
|
h = x.h;
|
|
}
|
|
x = x.x;
|
|
// For extra fastitude
|
|
x2 = x + w;
|
|
y2 = y + h;
|
|
p = (h + w) ? false : true;
|
|
}
|
|
else {
|
|
// For extra fastitude
|
|
x2 = x + w;
|
|
y2 = y + h;
|
|
p = (h + w) ? false : true;
|
|
}
|
|
|
|
this.x1 = this.x = function () {
|
|
return x;
|
|
};
|
|
this.y1 = this.y = function () {
|
|
return y;
|
|
};
|
|
this.x2 = function () {
|
|
return x2;
|
|
};
|
|
this.y2 = function () {
|
|
return y2;
|
|
};
|
|
this.w = function () {
|
|
return w;
|
|
};
|
|
this.h = function () {
|
|
return h;
|
|
};
|
|
this.p = function () {
|
|
return p;
|
|
};
|
|
|
|
this.overlap = function (a) {
|
|
if (p || a.p()) {
|
|
return x <= a.x2() && x2 >= a.x() && y <= a.y2() && y2 >= a.y();
|
|
}
|
|
return x < a.x2() && x2 > a.x() && y < a.y2() && y2 > a.y();
|
|
};
|
|
|
|
this.expand = function (a) {
|
|
var nx, ny;
|
|
var ax = a.x();
|
|
var ay = a.y();
|
|
var ax2 = a.x2();
|
|
var ay2 = a.y2();
|
|
if (x > ax) {
|
|
nx = ax;
|
|
}
|
|
else {
|
|
nx = x;
|
|
}
|
|
if (y > ay) {
|
|
ny = ay;
|
|
}
|
|
else {
|
|
ny = y;
|
|
}
|
|
if (x2 > ax2) {
|
|
w = x2 - nx;
|
|
}
|
|
else {
|
|
w = ax2 - nx;
|
|
}
|
|
if (y2 > ay2) {
|
|
h = y2 - ny;
|
|
}
|
|
else {
|
|
h = ay2 - ny;
|
|
}
|
|
x = nx;
|
|
y = ny;
|
|
return this;
|
|
};
|
|
|
|
//End of RTree.Rectangle
|
|
}
|
|
|
|
|
|
/* returns true if rectangle 1 overlaps rectangle 2
|
|
* [ boolean ] = overlapRectangle(rectangle a, rectangle b)
|
|
* @static function
|
|
*/
|
|
Rectangle.overlapRectangle = function (a, b) {
|
|
//if(!((a.h||a.w)&&(b.h||b.w))){ not faster resist the urge!
|
|
if ((a.h === 0 && a.w === 0) || (b.h === 0 && b.w === 0)) {
|
|
return a.x <= (b.x + b.w) && (a.x + a.w) >= b.x && a.y <= (b.y + b.h) && (a.y + a.h) >= b.y;
|
|
}
|
|
else {
|
|
return a.x < (b.x + b.w) && (a.x + a.w) > b.x && a.y < (b.y + b.h) && (a.y + a.h) > b.y;
|
|
}
|
|
};
|
|
|
|
/* returns true if rectangle a is contained in rectangle b
|
|
* [ boolean ] = containsRectangle(rectangle a, rectangle b)
|
|
* @static function
|
|
*/
|
|
Rectangle.containsRectangle = function (a, b) {
|
|
return (a.x + a.w) <= (b.x + b.w) && a.x >= b.x && (a.y + a.h) <= (b.y + b.h) && a.y >= b.y;
|
|
};
|
|
|
|
/* expands rectangle A to include rectangle B, rectangle B is untouched
|
|
* [ rectangle a ] = expandRectangle(rectangle a, rectangle b)
|
|
* @static function
|
|
*/
|
|
Rectangle.expandRectangle = function (a, b) {
|
|
var nx, ny;
|
|
var axw = a.x + a.w;
|
|
var bxw = b.x + b.w;
|
|
var ayh = a.y + a.h;
|
|
var byh = b.y + b.h;
|
|
if (a.x > b.x) {
|
|
nx = b.x;
|
|
}
|
|
else {
|
|
nx = a.x;
|
|
}
|
|
if (a.y > b.y) {
|
|
ny = b.y;
|
|
}
|
|
else {
|
|
ny = a.y;
|
|
}
|
|
if (axw > bxw) {
|
|
a.w = axw - nx;
|
|
}
|
|
else {
|
|
a.w = bxw - nx;
|
|
}
|
|
if (ayh > byh) {
|
|
a.h = ayh - ny;
|
|
}
|
|
else {
|
|
a.h = byh - ny;
|
|
}
|
|
a.x = nx;
|
|
a.y = ny;
|
|
return a;
|
|
};
|
|
|
|
/* generates a minimally bounding rectangle for all rectangles in
|
|
* array 'nodes'. If rect is set, it is modified into the MBR. Otherwise,
|
|
* a new rectangle is generated and returned.
|
|
* [ rectangle a ] = makeMBR(rectangle array nodes, rectangle rect)
|
|
* @static function
|
|
*/
|
|
Rectangle.makeMBR = function (nodes, rect) {
|
|
if (!nodes.length) {
|
|
return {
|
|
x: 0,
|
|
y: 0,
|
|
w: 0,
|
|
h: 0
|
|
};
|
|
}
|
|
rect = rect || {};
|
|
rect.x = nodes[0].x;
|
|
rect.y = nodes[0].y;
|
|
rect.w = nodes[0].w;
|
|
rect.h = nodes[0].h;
|
|
|
|
for (var i = 1, len = nodes.length; i < len; i++) {
|
|
Rectangle.expandRectangle(rect, nodes[i]);
|
|
}
|
|
|
|
return rect;
|
|
};
|
|
Rectangle.squarifiedRatio = function (l, w, fill) {
|
|
// Area of new enlarged rectangle
|
|
var lperi = (l + w) / 2.0; // Average size of a side of the new rectangle
|
|
var larea = l * w; // Area of new rectangle
|
|
// return the ratio of the perimeter to the area - the closer to 1 we are,
|
|
// the more 'square' a rectangle is. conversly, when approaching zero the
|
|
// more elongated a rectangle is
|
|
var lgeo = larea / (lperi * lperi);
|
|
return larea * fill / lgeo;
|
|
};
|
|
module.exports = Rectangle; |