mirror of
https://github.com/scratchfoundation/scratchjr.git
synced 2024-11-28 18:15:37 -05:00
Matrix and Rectangle modules
This commit is contained in:
parent
fdd74a411c
commit
535e61f628
2 changed files with 214 additions and 214 deletions
|
@ -2,90 +2,92 @@
|
|||
// Basic Matrix
|
||||
////////////////////////////////////////
|
||||
|
||||
var Matrix = function () {
|
||||
this.a = 1;
|
||||
this.b = 0;
|
||||
this.c = 0;
|
||||
this.d = 1;
|
||||
this.e = 0;
|
||||
this.f = 0;
|
||||
};
|
||||
|
||||
Matrix.prototype.identity = function () {
|
||||
this.a = 1;
|
||||
this.b = 0;
|
||||
this.c = 0;
|
||||
this.d = 1;
|
||||
this.e = 0;
|
||||
this.f = 0;
|
||||
};
|
||||
|
||||
Matrix.prototype.setMatrix = function (mtx) { // webKitMtrx
|
||||
this.a = mtx.a;
|
||||
this.b = mtx.b;
|
||||
this.c = mtx.c;
|
||||
this.d = mtx.d;
|
||||
this.e = mtx.e;
|
||||
this.f = mtx.f;
|
||||
};
|
||||
|
||||
Matrix.prototype.isIdentity = function () {
|
||||
return (this.a == 1 && this.b == 0 && this.c == 0 && this.d == 1 && this.e == 0 && this.f == 0);
|
||||
};
|
||||
|
||||
Matrix.prototype.rotate = function (angle) {
|
||||
var cos = Math.cos(angle * Math.PI / 180);
|
||||
var sin = Math.sin(angle * Math.PI / 180);
|
||||
this.a = cos;
|
||||
this.b = sin;
|
||||
this.c = -sin;
|
||||
this.d = cos;
|
||||
};
|
||||
|
||||
Matrix.prototype.scale = function (scalex, scaley) {
|
||||
this.a = scalex;
|
||||
this.d = scaley ? scaley : scalex;
|
||||
};
|
||||
|
||||
|
||||
Matrix.prototype.translate = function (dx, dy) {
|
||||
this.e = dx;
|
||||
this.f = dy;
|
||||
};
|
||||
|
||||
Matrix.prototype.transformPoint = function (pt) {
|
||||
return {
|
||||
x: this.a * pt.x + this.c * pt.y + this.e,
|
||||
y: this.b * pt.x + this.d * pt.y + this.f
|
||||
};
|
||||
};
|
||||
|
||||
Matrix.prototype.multiply = function (m2) {
|
||||
var zero = 1e-14;
|
||||
var m = new Matrix();
|
||||
m.a = this.a * m2.a + this.c * m2.b;
|
||||
m.b = this.b * m2.a + this.d * m2.b,
|
||||
m.c = this.a * m2.c + this.c * m2.d,
|
||||
m.d = this.b * m2.c + this.d * m2.d,
|
||||
m.e = this.a * m2.e + this.c * m2.f + this.e,
|
||||
m.f = this.b * m2.e + this.d * m2.f + this.f;
|
||||
if (Math.abs(m.a) < zero) {
|
||||
m.a = 0;
|
||||
export default class Matrix {
|
||||
constructor () {
|
||||
this.a = 1;
|
||||
this.b = 0;
|
||||
this.c = 0;
|
||||
this.d = 1;
|
||||
this.e = 0;
|
||||
this.f = 0;
|
||||
}
|
||||
if (Math.abs(m.b) < zero) {
|
||||
m.b = 0;
|
||||
|
||||
identity () {
|
||||
this.a = 1;
|
||||
this.b = 0;
|
||||
this.c = 0;
|
||||
this.d = 1;
|
||||
this.e = 0;
|
||||
this.f = 0;
|
||||
}
|
||||
if (Math.abs(m.c) < zero) {
|
||||
m.c = 0;
|
||||
|
||||
setMatrix (mtx) { // webKitMtrx
|
||||
this.a = mtx.a;
|
||||
this.b = mtx.b;
|
||||
this.c = mtx.c;
|
||||
this.d = mtx.d;
|
||||
this.e = mtx.e;
|
||||
this.f = mtx.f;
|
||||
}
|
||||
if (Math.abs(m.d) < zero) {
|
||||
m.d = 0;
|
||||
|
||||
isIdentity () {
|
||||
return (this.a == 1 && this.b == 0 && this.c == 0 && this.d == 1 && this.e == 0 && this.f == 0);
|
||||
}
|
||||
if (Math.abs(m.e) < zero) {
|
||||
m.e = 0;
|
||||
|
||||
rotate (angle) {
|
||||
var cos = Math.cos(angle * Math.PI / 180);
|
||||
var sin = Math.sin(angle * Math.PI / 180);
|
||||
this.a = cos;
|
||||
this.b = sin;
|
||||
this.c = -sin;
|
||||
this.d = cos;
|
||||
}
|
||||
if (Math.abs(m.f) < zero) {
|
||||
m.f = 0;
|
||||
|
||||
scale (scalex, scaley) {
|
||||
this.a = scalex;
|
||||
this.d = scaley ? scaley : scalex;
|
||||
}
|
||||
return m;
|
||||
};
|
||||
|
||||
|
||||
translate (dx, dy) {
|
||||
this.e = dx;
|
||||
this.f = dy;
|
||||
}
|
||||
|
||||
transformPoint (pt) {
|
||||
return {
|
||||
x: this.a * pt.x + this.c * pt.y + this.e,
|
||||
y: this.b * pt.x + this.d * pt.y + this.f
|
||||
};
|
||||
}
|
||||
|
||||
multiply (m2) {
|
||||
var zero = 1e-14;
|
||||
var m = new Matrix();
|
||||
m.a = this.a * m2.a + this.c * m2.b;
|
||||
m.b = this.b * m2.a + this.d * m2.b,
|
||||
m.c = this.a * m2.c + this.c * m2.d,
|
||||
m.d = this.b * m2.c + this.d * m2.d,
|
||||
m.e = this.a * m2.e + this.c * m2.f + this.e,
|
||||
m.f = this.b * m2.e + this.d * m2.f + this.f;
|
||||
if (Math.abs(m.a) < zero) {
|
||||
m.a = 0;
|
||||
}
|
||||
if (Math.abs(m.b) < zero) {
|
||||
m.b = 0;
|
||||
}
|
||||
if (Math.abs(m.c) < zero) {
|
||||
m.c = 0;
|
||||
}
|
||||
if (Math.abs(m.d) < zero) {
|
||||
m.d = 0;
|
||||
}
|
||||
if (Math.abs(m.e) < zero) {
|
||||
m.e = 0;
|
||||
}
|
||||
if (Math.abs(m.f) < zero) {
|
||||
m.f = 0;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,148 +1,146 @@
|
|||
////////////////////////////////////////
|
||||
// Basic Matrix
|
||||
////////////////////////////////////////
|
||||
export default class Rectangle {
|
||||
constructor (x, y, w, h) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
}
|
||||
|
||||
var Rectangle = function (x, y, w, h) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
};
|
||||
hitRect (pt) {
|
||||
var x = pt.x;
|
||||
var y = pt.y;
|
||||
if (x < this.x) {
|
||||
return false;
|
||||
}
|
||||
if (x > this.x + this.width) {
|
||||
return false;
|
||||
}
|
||||
if (y < this.y) {
|
||||
return false;
|
||||
}
|
||||
if (y > this.y + this.height) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Rectangle.prototype.hitRect = function (pt) {
|
||||
var x = pt.x;
|
||||
var y = pt.y;
|
||||
if (x < this.x) {
|
||||
intersects (r) {
|
||||
var x0 = Math.max(this.x, r.x);
|
||||
var x1 = Math.min(this.x + this.width, r.x + r.width);
|
||||
if (x0 <= x1) {
|
||||
var y0 = Math.max(this.y, r.y);
|
||||
var y1 = Math.min(this.y + this.height, r.y + r.height);
|
||||
if (y0 <= y1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (x > this.x + this.width) {
|
||||
return false;
|
||||
}
|
||||
if (y < this.y) {
|
||||
return false;
|
||||
}
|
||||
if (y > this.y + this.height) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
Rectangle.prototype.intersects = function (r) {
|
||||
var x0 = Math.max(this.x, r.x);
|
||||
var x1 = Math.min(this.x + this.width, r.x + r.width);
|
||||
if (x0 <= x1) {
|
||||
var y0 = Math.max(this.y, r.y);
|
||||
var y1 = Math.min(this.y + this.height, r.y + r.height);
|
||||
if (y0 <= y1) {
|
||||
return true;
|
||||
overlapElemBy (box2, percent) {
|
||||
return this.overlapElem(box2) >= percent;
|
||||
}
|
||||
|
||||
overlapElem (box2) {
|
||||
var boxi = this.intersection(box2);
|
||||
if (boxi.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
if (boxi.isEqual(box2)) {
|
||||
return 1;
|
||||
}
|
||||
if (boxi.isEqual(this)) {
|
||||
return 1;
|
||||
}
|
||||
return (boxi.width * boxi.height) / (box2.width * box2.height);
|
||||
}
|
||||
|
||||
intersection (box2) {
|
||||
var dx = Math.max(this.x, box2.x);
|
||||
var dw = Math.min(this.x + this.width, box2.x + box2.width);
|
||||
if (dx <= dw) {
|
||||
var dy = Math.max(this.y, box2.y);
|
||||
var dh = Math.min(this.y + this.height, box2.y + box2.height);
|
||||
if (dy > dh) {
|
||||
return new Rectangle(0, 0, 0, 0);
|
||||
}
|
||||
return new Rectangle(dx, dy, dw - dx, dh - dy);
|
||||
}
|
||||
return new Rectangle(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
union (box2) {
|
||||
var box = new Rectangle(0, 0, 0, 0);
|
||||
box.x = (this.x < box2.x) ? this.x : box2.x;
|
||||
box.y = (this.y < box2.y) ? this.y : box2.y;
|
||||
this.extentsw = (this.x == 9999999) ? 0 : this.x + this.width;
|
||||
this.extentsh = (this.y == 9999999) ? 0 : this.y + this.height;
|
||||
box2.extentsw = (box2.x == 9999999) ? 0 : box2.x + box2.width;
|
||||
box2.extentsh = (box2.y == 9999999) ? 0 : box2.y + box2.height;
|
||||
box.width = (this.extentsw > box2.extentsw) ? this.extentsw : box2.extentsw;
|
||||
box.height = (this.extentsh > box2.extentsh) ? this.extentsh : box2.extentsh;
|
||||
box.width -= box.x;
|
||||
box.height -= box.y;
|
||||
if (box.isEmpty()) {
|
||||
box = {
|
||||
x: 9999999,
|
||||
y: 9999999,
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
expandBy (sw) {
|
||||
this.x -= sw / 2;
|
||||
this.y -= sw / 2;
|
||||
this.width += sw;
|
||||
this.height += sw;
|
||||
return this;
|
||||
}
|
||||
|
||||
crop (box) {
|
||||
if (this.x < box.x) {
|
||||
this.x = box.x;
|
||||
}
|
||||
if (this.y < box.y) {
|
||||
this.y = box.y;
|
||||
}
|
||||
if ((this.width + this.x) > (box.width + box.x)) {
|
||||
this.width += ((box.width + box.x) - (this.width + this.x));
|
||||
}
|
||||
if ((this.height + this.y) > (box.height + box.y)) {
|
||||
this.height += ((box.height + box.y) - (this.height + this.y));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Rectangle.prototype.overlapElemBy = function (box2, percent) {
|
||||
return this.overlapElem(box2) >= percent;
|
||||
};
|
||||
|
||||
Rectangle.prototype.overlapElem = function (box2) {
|
||||
var boxi = this.intersection(box2);
|
||||
if (boxi.isEmpty()) {
|
||||
return 0;
|
||||
getArea () {
|
||||
return this.width * this.height;
|
||||
}
|
||||
if (boxi.isEqual(box2)) {
|
||||
return 1;
|
||||
|
||||
rounded () {
|
||||
return new Rectangle(
|
||||
Math.floor(this.x),
|
||||
Math.floor(this.y),
|
||||
Math.round(this.width) + 1,
|
||||
Math.round(this.height) + 1
|
||||
);
|
||||
}
|
||||
if (boxi.isEqual(this)) {
|
||||
return 1;
|
||||
|
||||
isEqual (box2) {
|
||||
return (this.x == box2.x) && (this.y == box2.y) &&
|
||||
(this.width == box2.width) && (this.height == box2.height);
|
||||
}
|
||||
return (boxi.width * boxi.height) / (box2.width * box2.height);
|
||||
};
|
||||
|
||||
Rectangle.prototype.intersection = function (box2) {
|
||||
var dx = Math.max(this.x, box2.x);
|
||||
var dw = Math.min(this.x + this.width, box2.x + box2.width);
|
||||
if (dx <= dw) {
|
||||
var dy = Math.max(this.y, box2.y);
|
||||
var dh = Math.min(this.y + this.height, box2.y + box2.height);
|
||||
if (dy > dh) {
|
||||
return new Rectangle(0, 0, 0, 0);
|
||||
}
|
||||
return new Rectangle(dx, dy, dw - dx, dh - dy);
|
||||
isEmpty () {
|
||||
return (this.x == 0) && (this.y == 0) && (this.width == 0) && (this.height == 0);
|
||||
}
|
||||
return new Rectangle(0, 0, 0, 0);
|
||||
};
|
||||
|
||||
Rectangle.prototype.union = function (box2) {
|
||||
var box = new Rectangle(0, 0, 0, 0);
|
||||
box.x = (this.x < box2.x) ? this.x : box2.x;
|
||||
box.y = (this.y < box2.y) ? this.y : box2.y;
|
||||
this.extentsw = (this.x == 9999999) ? 0 : this.x + this.width;
|
||||
this.extentsh = (this.y == 9999999) ? 0 : this.y + this.height;
|
||||
box2.extentsw = (box2.x == 9999999) ? 0 : box2.x + box2.width;
|
||||
box2.extentsh = (box2.y == 9999999) ? 0 : box2.y + box2.height;
|
||||
box.width = (this.extentsw > box2.extentsw) ? this.extentsw : box2.extentsw;
|
||||
box.height = (this.extentsh > box2.extentsh) ? this.extentsh : box2.extentsh;
|
||||
box.width -= box.x;
|
||||
box.height -= box.y;
|
||||
if (box.isEmpty()) {
|
||||
box = {
|
||||
x: 9999999,
|
||||
y: 9999999,
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
scale (sx, sy) {
|
||||
this.x *= sx;
|
||||
this.y *= sy;
|
||||
this.width *= sx;
|
||||
this.height *= sy;
|
||||
}
|
||||
return box;
|
||||
};
|
||||
|
||||
Rectangle.prototype.expandBy = function (sw) {
|
||||
this.x -= sw / 2;
|
||||
this.y -= sw / 2;
|
||||
this.width += sw;
|
||||
this.height += sw;
|
||||
return this;
|
||||
};
|
||||
|
||||
Rectangle.prototype.crop = function (box) {
|
||||
if (this.x < box.x) {
|
||||
this.x = box.x;
|
||||
}
|
||||
if (this.y < box.y) {
|
||||
this.y = box.y;
|
||||
}
|
||||
if ((this.width + this.x) > (box.width + box.x)) {
|
||||
this.width += ((box.width + box.x) - (this.width + this.x));
|
||||
}
|
||||
if ((this.height + this.y) > (box.height + box.y)) {
|
||||
this.height += ((box.height + box.y) - (this.height + this.y));
|
||||
}
|
||||
};
|
||||
|
||||
Rectangle.prototype.getArea = function () {
|
||||
return this.width * this.height;
|
||||
};
|
||||
|
||||
Rectangle.prototype.rounded = function () {
|
||||
return new Rectangle(
|
||||
Math.floor(this.x),
|
||||
Math.floor(this.y),
|
||||
Math.round(this.width) + 1,
|
||||
Math.round(this.height) + 1
|
||||
);
|
||||
};
|
||||
|
||||
Rectangle.prototype.isEqual = function (box2) {
|
||||
return (this.x == box2.x) && (this.y == box2.y) &&
|
||||
(this.width == box2.width) && (this.height == box2.height);
|
||||
};
|
||||
|
||||
Rectangle.prototype.isEmpty = function () {
|
||||
return (this.x == 0) && (this.y == 0) && (this.width == 0) && (this.height == 0);
|
||||
};
|
||||
|
||||
Rectangle.prototype.scale = function (sx, sy) {
|
||||
this.x *= sx;
|
||||
this.y *= sy;
|
||||
this.width *= sx;
|
||||
this.height *= sy;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue