๐Rect
an object that has origin (x, y) and size (width, height).
๐ custom
replit โฉ Rect (v1.1) , require -> Vector, Size
// (Rect 1.1)
// 2023.01.22 - 22:57 (+) .points
// (+) .topRight, .topLeft, .top, .bottom, .left, .right
// 2023.01.22 - 20:18 (+) .translate()
// 2023.01.21 - 13:38 (+) .inset()
// 2023.01.18 - 14:33 (+) .toString()
// 2023.01.18 - 09:01 (/) refactor rect()
// 2023.01.17 - 22:19 (โข) first draft
// -------------------------------------------------
const {min, abs} = Math;
// โญ๏ธ import
// -------------------------------------------------
import {vec} from './Vector.js'; // ๐ Vector
import {Size} from './Size.js'; // ๐ Size
// โญ๏ธ Rect
// -------------------------------------------------
// - new Rect(x, y, w, h)
// - rect(x, y, w, h)
// - rect(corner, offset)
// - rect(center, offset, true)
// -------------------------------------------------
// ๐ธ .x, .y, .width, .height
// ๐ธ .coords - [x, y, w, h]
// ๐ธ .size
// -------------------------------------------------
// ๐ธ .origin, .offset - vectors
// ๐ธ .center, .bottomLeft, .bottomRight
// ๐ธ .bottomLeft, .bottomRight, .topLeft, .topRight
// ๐ธ .top
// ๐ธ .points
// -------------------------------------------------
// .halfWidth, .halfHeight, .halfOffset
// -------------------------------------------------
// ๐น .inset()
// ๐น .translate()
// -------------------------------------------------
// ๐น .toString()
//
class Rect {
// init
constructor(
x, y, // a corner point, not necessarily the top-left corner
width, height // a "vector" pointing to the opposite corner
) {
// top-left corner
this.x = min(x, x + width);
this.y = min(y, y + height);
// always positive width/height
this.width = abs(width);
this.height = abs(height);
}
// ------------------------
// size related
// ------------------------
// ๐ธ .size
get size() {
return new Size(this.width, this.height) // ๐ Size
}
// ๐ธ .halfWidth, .halfHeight
get halfWidth() { return this.width / 2 }
get halfHeight() { return this.height / 2 }
// ------------------------
// vectors / points
// ------------------------
// ๐ธ .origin (topLeft)
get origin() { return vec(this.x, this.y) } // ๐ Vector
get topLeft() { return this.origin }
// ๐ธ .origin, .offset, .halfOffset
get offset() { return vec(this.width, this.height) } // ๐ Vector
get halfOffset() { return this.offset.times(1/2) } // ๐ Vector
// ๐ธ .center
get center() { return this.origin.plus(this.halfOffset) }
// ๐ธ .bottomLeft
get bottomLeft() {
const {halfWidth: w, halfHeight: h} = this; // ๐ Vector
return this.center.plus(-w, h);
}
// ๐ธ .bottomRight
get bottomRight() {
return this.origin.plus(this.offset); // ๐ Vector
}
// ๐ธ .topRight
get topRight() {
const {halfWidth: w, halfHeight: h} = this; // ๐ Vector
return this.center.plus(w, -h);
}
// ๐ธ .top
get top() {
return this.center.plus(0, -this.halfHeight);
}
// ๐ธ .bottom
get bottom() {
return this.center.plus(0, this.halfHeight);
}
// ๐ธ .left
get left() {
return this.center.plus(-this.halfWidth, 0);
}
// ๐ธ .right
get right() {
return this.center.plus(this.halfWidth, 0);
}
// ๐ธ .points
get points() {
const {
bottomLeft: p0, bottomRight: p1,
topRight: p2, topLeft: p3,
} = this;
return [p0, p1, p2, p3];
}
// ------------------------
// rect operations
// ------------------------
// ๐น .inset()
inset(dx, dy = dx) {
const v = vec(dx, dy);
// new origin: o + v
const origin = this.origin.plus(v);
// new corner: o + diag - v (diag = this.offset)
// new offset = (o + diag - v) - (o + v) = diag - 2v
const offset = this.offset.plus(v.times(-2));
return rect(origin, offset);
}
// ๐น .translate()
translate(...args) {
const v = vec(...args); // vec(v) or vec(x, y)
return rect(this.origin.plus(v), this.offset);
}
// ------------------------
// helpers / debug
// ------------------------
// rect.coords
get coords() {
const {x, y, width, height} = this;
return [x, y, width, height];
}
// ๐น .toString()
toString() {
return `(${this.coords})`;
}
}
// convenience factory functions
// ๐ธ rect()
function rect(...args) {
const len = args.length;
switch (len) {
// treat as (x, y, width, height)
case 4: return new Rect(...args);
// treat as (point, offset, center?)
case 2:
case 3:
const [point, offset, center] = args;
// `point` is corner
if (!center) return new Rect(...point.coords, ...offset.coords);
// `point` is center
const corner = point.plus(offset);
const offsetToOppositeCorner = offset.times(-2);
return rect(corner, offsetToOppositeCorner);
default:
const msg = [
`โ rect(${args})`,
`โข expecting 2/3/4 arguments, but got ${len}.`,
``,
`๐ก rect() syntax:`,
`------------------`,
`โข rect(x, y, width, height)`,
`โข rect(corner, offset): "corner" and "offset" are vectors.`,
`โข rect(center, offset, true): "true" means "center" is a center point.`,
];
throw new Error(msg.join('\n'));
}
}
// export
export {Rect, rect}; // ES module export
History
0: (?) first recorded
1: (+) refactor, .toString()
2: (+) .inset()
Last updated
Was this helpful?