diff --git a/ui/src/components/rects/RectPad.vue b/ui/src/components/rects/RectPad.vue index 5bbb8e3..281c9a6 100644 --- a/ui/src/components/rects/RectPad.vue +++ b/ui/src/components/rects/RectPad.vue @@ -13,7 +13,7 @@ @dblclick.left="remove_rect" > @@ -56,35 +56,24 @@ export default class RectPad extends Vue { private dragging = false; private drag_rect?: Rectangle; private drag_origin = new Vector2D(); - private rectangles_array: Rectangle[] = []; + public rectangles: Rectangle[] = []; private get preview_visible(): boolean { return this.drawing || this.dragging; } private get preview_rectangle(): Rectangle { - return new Rectangle( - this.preview_corner1, - this.preview_corner2 - ).normalize(); - } - - public get rectangles(): Rectangle[] { - return this.rectangles_array; //.map((rect) => rect.normalize()); - } - - public set rectangles(rects: Rectangle[]) { - this.rectangles_array = rects; //.map((rect) => rect.normalize()); + return new Rectangle(this.preview_corner1, this.preview_corner2); } private pop_rectangle(point: Vector2D): Rectangle | undefined { - const idx = this.rectangles_array.findIndex((rect) => rect.contains(point)); + const idx = this.rectangles.findIndex((rect) => rect.contains(point)); if (idx === -1) { return; } - return this.rectangles_array.splice(idx, 1)[0]; + return this.rectangles.splice(idx, 1)[0]; } private draw_start(event: MouseEvent) { @@ -108,7 +97,7 @@ export default class RectPad extends Vue { return; } - this.rectangles_array.push(this.preview_rectangle); + this.rectangles.push(this.preview_rectangle); } private drag_start(event: MouseEvent) { @@ -136,7 +125,7 @@ export default class RectPad extends Vue { } this.dragging = false; - this.rectangles_array.push(this.preview_rectangle); + this.rectangles.push(this.preview_rectangle); } private on_mousemove(event: MouseEvent) { diff --git a/ui/src/components/rects/rectangles.ts b/ui/src/components/rects/rectangles.ts index 60649a6..9273cc0 100644 --- a/ui/src/components/rects/rectangles.ts +++ b/ui/src/components/rects/rectangles.ts @@ -1,39 +1,34 @@ export class Vector2D { - private _x: number; - private _y: number; + public readonly x: number; + public readonly y: number; constructor(x = 0, y = 0) { - this._x = x; - this._y = y; - } - - public get x(): number { - return this._x; - } - - public get y(): number { - return this._y; + this.x = x; + this.y = y; } public plus(other: Vector2D): Vector2D { - return new Vector2D(this._x + other._x, this._y + other._y); + return new Vector2D(this.x + other.x, this.y + other.y); } public minus(other: Vector2D): Vector2D { - return new Vector2D(this._x - other._x, this._y - other._y); + return new Vector2D(this.x - other.x, this.y - other.y); } } export class Rectangle { - private _corner_1: Vector2D; - private _corner_2: Vector2D; + private readonly corner_1: Vector2D; + private readonly corner_2: Vector2D; constructor(corner_1: Vector2D, corner_2: Vector2D) { - this._corner_1 = corner_1; - this._corner_2 = corner_2; + this.corner_1 = corner_1; + this.corner_2 = corner_2; } public get origin(): Vector2D { - return this._corner_1; + return new Vector2D( + Math.min(this.corner_1.x, this.corner_2.x), + Math.min(this.corner_1.y, this.corner_2.y), + ) } public get left(): number { @@ -45,11 +40,14 @@ export class Rectangle { } public get corner(): Vector2D { - return this._corner_2; + return new Vector2D( + Math.max(this.corner_1.x, this.corner_2.x), + Math.max(this.corner_1.y, this.corner_2.y), + ) } public get size(): Vector2D { - return this._corner_2.minus(this._corner_1); + return this.corner.minus(this.origin); } public get width(): number { @@ -65,33 +63,9 @@ export class Rectangle { } public contains(point: Vector2D): boolean { - const test_rect = this.normalize(); - - return point.x >= test_rect._corner_1.x && - point.y >= test_rect._corner_1.y && - point.x <= test_rect._corner_2.x && - point.y <= test_rect._corner_2.y - } - - public normalize(): Rectangle { - let left = this.left; - let top = this.top; - let width = this.width; - let height = this.height; - - if (width < 0) { - width *= -1; - left -= width; - } - - if (height < 0) { - height *= -1; - top -= height; - } - - const corner_tl = new Vector2D(left, top); - const size = new Vector2D(width, height); - - return new Rectangle(corner_tl, corner_tl.plus(size)); + return point.x >= this.origin.x && + point.y >= this.origin.y && + point.x <= this.corner.x && + point.y <= this.corner.y } } diff --git a/ui/tests/unit/rectangle.spec.ts b/ui/tests/unit/rectangle.spec.ts index 3988c6f..dc2c1fe 100644 --- a/ui/tests/unit/rectangle.spec.ts +++ b/ui/tests/unit/rectangle.spec.ts @@ -1,4 +1,4 @@ -import { Vector2D } from '@/components/rects/rectangles'; +import { Rectangle, Vector2D } from '@/components/rects/rectangles'; import { expect } from "chai"; describe("Vector Tests", () => { @@ -21,3 +21,53 @@ describe("Vector Tests", () => { expect(v2.y).to.equal(-2); }); }); + +describe("Vector Tests", () => { + const v1 = new Vector2D(1, 2); + const v2 = new Vector2D(4, 6); + + + const r1 = new Rectangle(v1, v2); + const r2 = new Rectangle(v2, v1); + + it("should create a rectangle", () => { + expect(r1.left).to.equal(1); + expect(r1.top).to.equal(2); + expect(r1.width).to.equal(3); + expect(r1.height).to.equal(4); + }); + + it("should create the same rectangle backwards", () => { + expect(r2.left).to.equal(1); + expect(r2.top).to.equal(2); + expect(r2.width).to.equal(3); + expect(r2.height).to.equal(4); + }); + + it("should create the same rectangle transposed", () => { + const v1t = new Vector2D(v1.x, v2.y); + const v2t = new Vector2D(v2.x, v1.y); + const rt = new Rectangle(v1t, v2t); + + expect(rt.left).to.equal(1); + expect(rt.top).to.equal(2); + expect(rt.width).to.equal(3); + expect(rt.height).to.equal(4); + }); + + it("should contain itself", () => { + expect(r1.contains(v1)).true; + expect(r1.contains(v2)).true; + + expect(r1.contains(r1.origin)).true; + expect(r1.contains(r1.corner)).true; + + const vmid = new Vector2D((v1.x + v2.x) / 2, (v1.y + v2.y) / 2); + expect(r1.contains(vmid)).true; + }); + + it("should not contain certain points", () => { + expect(r1.contains(new Vector2D(0, 0))).false; + expect(r1.contains(new Vector2D(100, 100))).false; + }); +}); \ No newline at end of file