@valeera/mathx
Version:
A math library written in TS.
224 lines (180 loc) • 5.74 kB
text/typescript
import { Vector2, Vector2Like } from "../vector/Vector2";
import { IRectangle2 } from "./interfaces/IRectangle2";
const DIRTY_TAG_SIZE = 1;
const DIRTY_TAG_CENTER = 2;
const DIRTY_TAG_AREA = 4;
const DIRTY_TAG_ALL = 7;
const vec2 = new Vector2();
const halpVec = [0.5, 0.5];
export class Rectangle2 implements IRectangle2 {
public static area = (a: IRectangle2): number => {
return (a.max[0] - a.min[0]) * (a.max[1] - a.min[1]);
};
public static center = (a: IRectangle2, out: Vector2 = new Vector2()): Vector2 => {
return Vector2.add(a.min, Vector2.multiplyScalar(Rectangle2.size(a, out), 0.5, out), out);
};
public static containsPoint = (rect: IRectangle2, a: Float32Array): boolean => {
return a[0] >= rect.min[0] && a[0] <= rect.max[0] && a[1] >= rect.min[1] && a[1] <= rect.max[1];
};
public static containsRectangle = (rect: IRectangle2, box: IRectangle2): boolean => {
return (
rect.min[0] <= box.min[0] &&
box.max[0] <= rect.max[0] &&
rect.min[1] <= box.min[1] &&
box.max[1] <= rect.max[1]
);
};
public static create = (
a: Vector2Like = Vector2.VECTOR2_ZERO,
b: Vector2Like = Vector2.VECTOR2_ONE,
): Rectangle2 => {
return new Rectangle2(a, b);
};
public static equals = (a: IRectangle2, b: IRectangle2): boolean => {
return Vector2.equals(a.min, b.min) && Vector2.equals(a.max, b.max);
};
public static getCenter = (a: IRectangle2, out: Vector2 = Vector2.create()): Vector2 => {
Vector2.add(a.min, a.max, out);
return Vector2.multiplyScalar(out, 0.5, out);
};
public static getSize = (a: IRectangle2, out: Vector2 = Vector2.create()): Vector2 => {
return Vector2.minus(a.max, a.min, out);
};
public static height = (a: IRectangle2): number => {
return a.max[1] - a.min[1];
};
public static intersect = (a: IRectangle2, b: IRectangle2, out: Rectangle2 = new Rectangle2()): Rectangle2 => {
Vector2.max(a.min, b.min, out.min);
Vector2.min(a.max, b.max, out.max);
return out;
};
public static size = (a: IRectangle2, out: Vector2 = new Vector2()): Vector2 => {
return Vector2.minus(a.max, a.min, out);
};
public static split = (
a: IRectangle2,
rateBottomLeft: Vector2Like = halpVec,
bottomLeft = new Rectangle2(),
bottomRight = new Rectangle2(),
topLeft = new Rectangle2(),
topRight = new Rectangle2(),
): Rectangle2[] => {
Rectangle2.size(a, vec2);
Vector2.multiply(vec2, rateBottomLeft, vec2);
bottomLeft.min.set(a.min);
Vector2.add(a.min, vec2, bottomLeft.max);
topRight.min.set(bottomLeft.max);
topRight.max.set(a.max);
bottomRight.min.x = bottomLeft.max.x;
bottomRight.max.x = a.max[0];
bottomRight.min.y = a.min[1];
bottomRight.max.y = bottomLeft.max[1];
topLeft.min.x = a.min[0];
topLeft.min.y = bottomLeft.max[1];
topLeft.max.x = bottomLeft.max[0];
topLeft.max.y = a.max[1];
topLeft.dirty = topRight.dirty = bottomRight.dirty = bottomLeft.dirty = DIRTY_TAG_ALL;
return [bottomLeft, bottomRight, topLeft, topRight];
};
public static splitHerizontal = (
a: IRectangle2,
rateLeft: number = 0.5,
left: Rectangle2 = new Rectangle2(),
right: Rectangle2 = new Rectangle2(),
) => {
Rectangle2.size(a, vec2);
left.min.set(a.min);
vec2.x *= rateLeft;
Vector2.add(left.min, vec2, left.max);
right.min.x = left.max.x;
right.min.y = left.min.y;
right.max.set(a.max);
left.dirty = right.dirty = DIRTY_TAG_ALL;
return [left, right];
};
public static splitVertical = (
a: IRectangle2,
rateBottom: number = 0.5,
bottom: Rectangle2 = new Rectangle2(),
top: Rectangle2 = new Rectangle2(),
) => {
Rectangle2.size(a, vec2);
bottom.min.set(a.min);
vec2.y *= rateBottom;
Vector2.add(bottom.min, vec2, bottom.max);
top.min.x = bottom.min.x;
top.min.y = bottom.max.y;
top.max.set(a.max);
bottom.dirty = top.dirty = DIRTY_TAG_ALL;
return [bottom, top];
};
public static stretch = (
a: IRectangle2,
b: Vector2Like,
c: Vector2Like,
out: Rectangle2 = new Rectangle2(),
): Rectangle2 => {
Vector2.add(a.min, b, out.min);
Vector2.add(a.max, c, out.max);
return out;
};
public static translate = (a: IRectangle2, b: Vector2Like, out: Rectangle2 = new Rectangle2()): Rectangle2 => {
Vector2.add(a.min, b, out.min);
Vector2.add(a.max, b, out.max);
return out;
};
public static union = (a: IRectangle2, b: IRectangle2, out: Rectangle2 = new Rectangle2()): Rectangle2 => {
Vector2.min(a.min, b.min, out.min);
Vector2.max(a.max, b.max, out.max);
return out;
};
public static width = (a: IRectangle2): number => {
return a.max[0] - a.min[0];
};
#min: Vector2 = new Vector2();
#max: Vector2 = new Vector2();
#size: Vector2 = new Vector2();
#center: Vector2 = new Vector2();
dirty: number;
#area: number = 0;
public constructor(a: Vector2Like = Vector2.VECTOR2_ZERO, b: Vector2Like = Vector2.VECTOR2_ONE) {
Vector2.min(a, b, this.#min);
Vector2.max(a, b, this.#max);
this.dirty = DIRTY_TAG_ALL;
}
get area(): number {
if (this.dirty & DIRTY_TAG_AREA) {
this.#area = Vector2.area(this.size);
this.dirty -= DIRTY_TAG_AREA;
}
return this.#area;
}
get center(): Vector2 {
if (this.dirty & DIRTY_TAG_CENTER) {
Vector2.add(this.#min, Vector2.multiplyScalar(this.size, 0.5), this.#center);
this.dirty -= DIRTY_TAG_CENTER;
}
return this.#center;
}
get size() {
if (this.dirty & DIRTY_TAG_SIZE) {
Vector2.minus(this.#max, this.#min, this.#size);
this.dirty -= DIRTY_TAG_SIZE;
}
return this.#size;
}
set max(vec2: Vector2Like) {
this.#max.set(vec2);
this.dirty = DIRTY_TAG_ALL;
}
get max(): Vector2 {
return this.#max;
}
set min(vec2: Vector2Like) {
this.#min.set(vec2);
this.dirty = DIRTY_TAG_ALL;
}
get min(): Vector2 {
return this.#min;
}
}