import { assert } from 'chai'; import { DOUBLE_EPSILON } from '../../../../lib/math/float'; import { radians } from '../../../../lib/math/units'; import { Vector2D } from '../../../../lib/graphics/Vector2D'; import { Vector2DArray } from '../../../../lib/graphics/Vector2DArray'; import { Matrix } from '../../../../lib/graphics/Matrix'; import { Shape } from '../../../../lib/graphics/shapes/Shape'; import { Point } from '../../../../lib/graphics/shapes/Point'; import { Line } from '../../../../lib/graphics/shapes/Line'; import { Circle } from '../../../../lib/graphics/shapes/Circle'; import { Rectangle } from '../../../../lib/graphics/shapes/Rectangle'; import { Polygon } from '../../../../lib/graphics/shapes/Polygon'; import { Polyline } from '../../../../lib/graphics/shapes/Polyline'; import { canvasRenderingContext2DSpy } from '../mock/CanvasRenderingContext2D'; const matrix = Matrix.create; const vector2d = Vector2D.create; const fuzzyDeepEqual = Vector2DArray.fuzzyDeepEqual; const point = Point.create; const line = Line.create; const circle = Circle.create; const rectangle = Rectangle.create; const polygon = Polygon.create; const polyline = Polyline.create; describe('graphics.shapes.Rectangle', () => { describe('constructor', () => { it('default constructor', () => { const r = new Rectangle(); assert.strictEqual(r.p.x, 0); assert.strictEqual(r.p.y, 0); assert.strictEqual(r.s.x, 0); assert.strictEqual(r.s.y, 0); }); it('topLeft constructor', () => { const r = new Rectangle(new Vector2D(1, 2)); assert.strictEqual(r.p.x, 1); assert.strictEqual(r.p.y, 2); assert.strictEqual(r.s.x, 0); assert.strictEqual(r.s.y, 0); }); it('topLeft, size constructor', () => { const r = new Rectangle(new Vector2D(1, 2), new Vector2D(3, 4)); assert.strictEqual(r.p.x, 1); assert.strictEqual(r.p.y, 2); assert.strictEqual(r.s.x, 3); assert.strictEqual(r.s.y, 4); }); it('instanceof', () => { const r = new Rectangle(); assert.isTrue(r instanceof Shape); assert.isTrue(r instanceof Rectangle); }); }); describe('clone', function () { it('clone', function () { const r1 = rectangle(vector2d(1, 2), vector2d(3, 4)); const r2 = r1.clone(); r1.p.x = 5; r1.p.y = 6; r1.s.x = 7; r1.s.y = 8; assert.isTrue(r2 instanceof Rectangle); assert.isTrue(r2.equals(rectangle(vector2d(1, 2), vector2d(3, 4)))); }); }); describe('getters/setters', () => { it('getters/setters', () => { const r = rectangle(vector2d(1, 2), vector2d(3, 4)); assert.strictEqual(r.x, 1); assert.strictEqual(r.y, 2); assert.strictEqual(r.width, 3); assert.strictEqual(r.height, 4); r.x = -1; r.y = -2; r.width = -3; r.height = -4; assert.strictEqual(r.x, -1); assert.strictEqual(r.y, -2); assert.strictEqual(r.width, -3); assert.strictEqual(r.height, -4); assert.strictEqual(r.size.x, -3); assert.strictEqual(r.size.y, -4); r.size = vector2d(2, 3); assert.strictEqual(r.size.x, 2); assert.strictEqual(r.size.y, 3); }); }); describe('left', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), 5], [rectangle(vector2d(5, 4), vector2d(-3, -2)), 5], ])('left#%#', (rect: Rectangle, result: number) => { assert.isTrue(rect.left() === result); }); }); describe('moveLeft', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), 4, rectangle(vector2d(4, 4), vector2d(3, 2))], [rectangle(vector2d(5, 4), vector2d(3, 2)), 11, rectangle(vector2d(11, 4), vector2d(3, 2))], ])('moveLeft#%#', (rect: Rectangle, y: number, result: Rectangle) => { rect.moveLeft(y); assert.isTrue(rect.equals(result)); }); }); describe('setLeft', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), 4, rectangle(vector2d(4, 4), vector2d(4, 2))], [rectangle(vector2d(5, 4), vector2d(3, 2)), 11, rectangle(vector2d(11, 4), vector2d(-3, 2))], ])('setLeft#%#', (rect: Rectangle, y: number, result: Rectangle) => { rect.setLeft(y); assert.isTrue(rect.equals(result)); }); }); describe('top', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), 4], [rectangle(vector2d(5, 4), vector2d(-3, -2)), 4], ])('top#%#', (rect: Rectangle, result: number) => { assert.isTrue(rect.top() === result); }); }); describe('moveTop', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), 1, rectangle(vector2d(5, 1), vector2d(3, 2))], [rectangle(vector2d(5, 4), vector2d(3, 2)), 7, rectangle(vector2d(5, 7), vector2d(3, 2))], ])('moveTop#%#', (rect: Rectangle, y: number, result: Rectangle) => { rect.moveTop(y); assert.isTrue(rect.equals(result)); }); }); describe('setTop', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), 1, rectangle(vector2d(5, 1), vector2d(3, 5))], [rectangle(vector2d(5, 4), vector2d(3, 2)), 7, rectangle(vector2d(5, 7), vector2d(3, -1))], ])('setTop#%#', (rect: Rectangle, y: number, result: Rectangle) => { rect.setTop(y); assert.isTrue(rect.equals(result)); }); }); describe('right', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), 8], [rectangle(vector2d(5, 4), vector2d(-3, -2)), 2], ])('right#%#', (rect: Rectangle, result: number) => { assert.isTrue(rect.right() === result); }); }); describe('moveRight', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), 11, rectangle(vector2d(8, 4), vector2d(3, 2))], [rectangle(vector2d(5, 4), vector2d(3, 2)), 1, rectangle(vector2d(-2, 4), vector2d(3, 2))], ])('moveRight#%#', (rect: Rectangle, y: number, result: Rectangle) => { rect.moveRight(y); assert.isTrue(rect.equals(result)); }); }); describe('setRight', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), 11, rectangle(vector2d(5, 4), vector2d(6, 2))], [rectangle(vector2d(5, 4), vector2d(3, 2)), 1, rectangle(vector2d(5, 4), vector2d(-4, 2))], ])('setRight#%#', (rect: Rectangle, y: number, result: Rectangle) => { rect.setRight(y); assert.isTrue(rect.equals(result)); }); }); describe('bottom', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), 6], [rectangle(vector2d(5, 4), vector2d(-3, -2)), 2], ])('bottom#%#', (rect: Rectangle, result: number) => { assert.isTrue(rect.bottom() === result); }); }); describe('moveBottom', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), 7, rectangle(vector2d(5, 5), vector2d(3, 2))], [rectangle(vector2d(5, 4), vector2d(3, 2)), 1, rectangle(vector2d(5, -1), vector2d(3, 2))], ])('moveBottom#%#', (rect: Rectangle, y: number, result: Rectangle) => { rect.moveBottom(y); assert.isTrue(rect.equals(result)); }); }); describe('setBottom', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), 7, rectangle(vector2d(5, 4), vector2d(3, 3))], [rectangle(vector2d(5, 4), vector2d(3, 2)), 1, rectangle(vector2d(5, 4), vector2d(3, -3))], ])('setBottom#%#', (rect: Rectangle, y: number, result: Rectangle) => { rect.setBottom(y); assert.isTrue(rect.equals(result)); }); }); describe('topLeft', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(5, 4)], ])('topLeft#%#', (rect: Rectangle, result: Vector2D) => { assert.isTrue(rect.topLeft().equals(result)); }); }); describe('setTopLeft#', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(4, 3), rectangle(vector2d(4, 3), vector2d(4, 3))], [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(11, 8), rectangle(vector2d(11, 8), vector2d(-3, -2))], ])('setTopLeft#%#', (rect: Rectangle, p: Vector2D, result: Rectangle) => { rect.setTopLeft(p); assert.isTrue(rect.equals(result)); }); }); describe('moveTopLeft#', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(4, 3), rectangle(vector2d(4, 3), vector2d(3, 2))], [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(11, 8), rectangle(vector2d(11, 8), vector2d(3, 2))], ])('moveTopLeft#%#', (rect: Rectangle, p: Vector2D, result: Rectangle) => { rect.moveTopLeft(p); assert.isTrue(rect.equals(result)); }); }); describe('topRight', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(8, 4)], ])('topRight#%#', (rect: Rectangle, result: Vector2D) => { assert.isTrue(rect.topRight().equals(result)); }); }); describe('setTopRight#', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(11, 3), rectangle(vector2d(5, 3), vector2d(6, 3))], [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(2, 8), rectangle(vector2d(5, 8), vector2d(-3, -2))], ])('setTopRight#%#', (rect: Rectangle, p: Vector2D, result: Rectangle) => { rect.setTopRight(p); assert.isTrue(rect.equals(result)); }); }); describe('moveTopRight#', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(11, 3), rectangle(vector2d(8, 3), vector2d(3, 2))], [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(2, 8), rectangle(vector2d(-1, 8), vector2d(3, 2))], ])('moveTopRight#%#', (rect: Rectangle, p: Vector2D, result: Rectangle) => { rect.moveTopRight(p); assert.isTrue(rect.equals(result)); }); }); describe('bottomRight', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(8, 6)], ])('bottomRight#%#', (rect: Rectangle, result: Vector2D) => { assert.isTrue(rect.bottomRight().equals(result)); }); }); describe('setBottomRight#', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(11, 8), rectangle(vector2d(5, 4), vector2d(6, 4))], [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(2, 2), rectangle(vector2d(5, 4), vector2d(-3, -2))], ])('setBottomRight#%#', (rect: Rectangle, p: Vector2D, result: Rectangle) => { rect.setBottomRight(p); assert.isTrue(rect.equals(result)); }); }); describe('moveBottomRight#', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(11, 8), rectangle(vector2d(8, 6), vector2d(3, 2))], [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(2, 2), rectangle(vector2d(-1, 0), vector2d(3, 2))], ])('moveBottomRight#%#', (rect: Rectangle, p: Vector2D, result: Rectangle) => { rect.moveBottomRight(p); assert.isTrue(rect.equals(result)); }); }); describe('bottomLeft', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(5, 6)], [rectangle(vector2d(5, 4), vector2d(-3, -2)), vector2d(5, 2)], ])('bottomLeft#%#', (rect: Rectangle, result: Vector2D) => { assert.isTrue(rect.bottomLeft().equals(result)); }); }); describe('setBottomLeft#', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(2, 8), rectangle(vector2d(2, 4), vector2d(6, 4))], [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(11, 2), rectangle(vector2d(11, 4), vector2d(-3, -2))], ])('setBottomLeft#%#', (rect: Rectangle, p: Vector2D, result: Rectangle) => { rect.setBottomLeft(p); assert.isTrue(rect.equals(result)); }); }); describe('moveBottomLeft#', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(2, 8), rectangle(vector2d(2, 6), vector2d(3, 2))], [rectangle(vector2d(5, 4), vector2d(3, 2)), vector2d(11, 2), rectangle(vector2d(11, 0), vector2d(3, 2))], ])('moveBottomLeft#%#', (rect: Rectangle, p: Vector2D, result: Rectangle) => { rect.moveBottomLeft(p); assert.isTrue(rect.equals(result)); }); }); describe('center', () => { test.each([ [rectangle(vector2d(3, 4), vector2d(4, 2)), vector2d(5, 5)], [rectangle(vector2d(7, 4), vector2d(-4, 2)), vector2d(5, 5)], [rectangle(vector2d(7, 6), vector2d(-4, -2)), vector2d(5, 5)], [rectangle(vector2d(3, 6), vector2d(4, -2)), vector2d(5, 5)], [rectangle(vector2d(3, 4), vector2d(4, 0)), vector2d(5, 4)], [rectangle(vector2d(3, 4), vector2d(0, 2)), vector2d(3, 5)], [rectangle(vector2d(3, 4)), vector2d(3, 4)], ])('center#%#', (rect: Rectangle, result: Vector2D) => { assert.isTrue(rect.center().equals(result)); }); }); describe('moveCenter#', () => { test.each([ [rectangle(vector2d(3, 4), vector2d(4, 2)), vector2d(5, 5), rectangle(vector2d(3, 4), vector2d(4, 2))], [rectangle(vector2d(3, 4), vector2d(4, 2)), vector2d(3, 4), rectangle(vector2d(1, 3), vector2d(4, 2))], ])('moveCenter#%#', (rect: Rectangle, p: Vector2D, result: Rectangle) => { rect.moveCenter(p); assert.isTrue(rect.equals(result)); }); }); describe('isNull', () => { test.each([ [rectangle(), true], [rectangle(vector2d()), true], [rectangle(vector2d(), vector2d()), true], [rectangle(vector2d(1, 1)), true], [rectangle(vector2d(), vector2d(1, 1)), false], [rectangle(vector2d(1, 1), vector2d(1, 1)), false], [rectangle(vector2d(1, 1), vector2d(1, 0)), false], [rectangle(vector2d(1, 1), vector2d(0, 1)), false], [rectangle(vector2d(1, 1), vector2d(-1, -1)), false], ])('isNull#%#', (rectangle: Rectangle, result: boolean) => { assert.isTrue(rectangle.isNull() === result); }); }); describe('fuzzyIsNull', () => { test.each([ [rectangle(), true, undefined], [rectangle(vector2d()), true, undefined], [rectangle(vector2d(), vector2d()), true, undefined], [rectangle(vector2d(1, 1)), true, undefined], [rectangle(vector2d(), vector2d(1, 1)), false, undefined], [rectangle(vector2d(1, 1), vector2d(1, 1)), false, undefined], [rectangle(vector2d(1, 1), vector2d(1, 0)), false, undefined], [rectangle(vector2d(1, 1), vector2d(0, 1)), false, undefined], [rectangle(vector2d(1, 1), vector2d(-1, -1)), false, undefined], [rectangle(vector2d(1, 1), vector2d(0, 0.000001)), true, undefined], [rectangle(vector2d(1, 1), vector2d(0.000001, 0)), true, undefined], [rectangle(vector2d(1, 1), vector2d(0, 0.000001)), false, DOUBLE_EPSILON], ])('fuzzyIsNull#%#', (rectangle: Rectangle, result: boolean, epsilon: number | undefined) => { assert.isTrue(rectangle.fuzzyIsNull(epsilon) === result); }); }); describe('equals', () => { test.each([ [rectangle(), rectangle(), true], [rectangle(vector2d(0, 0)), rectangle(), true], [rectangle(vector2d(0, 0), vector2d(0, 0)), rectangle(), true], [rectangle(undefined, vector2d(0, 0)), rectangle(), true], [rectangle(vector2d(1, 1)), rectangle(), false], [rectangle(vector2d(1, 1)), rectangle(vector2d(1, 1)), true], [rectangle(vector2d(1, 1)), rectangle(vector2d(1, 2)), false], [rectangle(vector2d(1, 2)), rectangle(vector2d(1, 2)), true], [rectangle(vector2d(0, 0), vector2d(1, 1)), rectangle(), false], [rectangle(vector2d(0, 0), vector2d(1, 1)), rectangle(vector2d(0, 0), vector2d(1, 1)), true], [rectangle(vector2d(0, 0), vector2d(1, 1)), rectangle(vector2d(0, 0), vector2d(1, 2)), false], [rectangle(vector2d(0, 1), vector2d(1, 1)), rectangle(vector2d(0, 0), vector2d(1, 1)), false], [rectangle(vector2d(0, 1), vector2d(1, 2)), rectangle(vector2d(0, 1), vector2d(1, 2)), true], ])('equals#%#', (rectangle1: Rectangle, rectangle2: Rectangle, result: boolean) => { assert.isTrue(rectangle1.equals(rectangle2) === result); }); }); describe('fuzzyEquals', () => { test.each([ [rectangle(), rectangle(), true, undefined], [rectangle(vector2d(0, 0)), rectangle(), true, undefined], [rectangle(vector2d(0, 0), vector2d(0, 0)), rectangle(), true, undefined], [rectangle(undefined, vector2d(0, 0)), rectangle(), true, undefined], [rectangle(vector2d(1, 1)), rectangle(), false, undefined], [rectangle(vector2d(1, 1)), rectangle(vector2d(1, 1)), true, undefined], [rectangle(vector2d(1, 1)), rectangle(vector2d(1, 2)), false, undefined], [rectangle(vector2d(1, 2)), rectangle(vector2d(1, 2)), true, undefined], [rectangle(vector2d(0, 0), vector2d(1, 1)), rectangle(), false, undefined], [rectangle(vector2d(0, 0), vector2d(1, 1)), rectangle(vector2d(0, 0), vector2d(1, 1)), true, undefined], [rectangle(vector2d(0, 0), vector2d(1, 1)), rectangle(vector2d(0, 0), vector2d(1, 2)), false, undefined], [rectangle(vector2d(0, 1), vector2d(1, 1)), rectangle(vector2d(0, 0), vector2d(1, 1)), false, undefined], [rectangle(vector2d(0, 1), vector2d(1, 2)), rectangle(vector2d(0, 1), vector2d(1, 2)), true, undefined], [rectangle(vector2d(1)), rectangle(vector2d(1.000001)), true, undefined], [rectangle(vector2d(), vector2d(1, -1)), rectangle(vector2d(), vector2d(1, -1.000001)), true, undefined], [rectangle(vector2d(1)), rectangle(vector2d(1.000001)), false, DOUBLE_EPSILON], ])('fuzzyEquals#%#', (rectangle1: Rectangle, rectangle2: Rectangle, result: boolean, epsilon: number | undefined) => { assert.isTrue(rectangle1.fuzzyEquals(rectangle2, epsilon) === result); }); }); describe('isValid', () => { test.each([ [rectangle(), false], [rectangle(vector2d()), false], [rectangle(vector2d(), vector2d()), false], [rectangle(vector2d(1, 1)), false], [rectangle(vector2d(1, 1), vector2d(1, 1)), true], [rectangle(vector2d(1, 1), vector2d(1, 1)), true], [rectangle(vector2d(), vector2d(1)), false], [rectangle(vector2d(), vector2d(0, 1)), false], [rectangle(vector2d(), vector2d(-1, -1)), false], [rectangle(vector2d(), vector2d(0, -1)), false], ])('isValid#%#', (rectangle: Rectangle, result: boolean) => { assert.isTrue(rectangle.isValid() === result); }); }); describe('adjusted', () => { test.each([ [rectangle(vector2d(1, 1), vector2d(3, 2)), 1, 1, 1, 1, rectangle(vector2d(2, 2), vector2d(3, 2))], [rectangle(vector2d(1, 1), vector2d(3, 2)), 0, 0, 0, 0, rectangle(vector2d(1, 1), vector2d(3, 2))], [rectangle(vector2d(1, 1), vector2d(3, 2)), 1, 1, 2, 2, rectangle(vector2d(2, 2), vector2d(4, 3))], ])('adjusted#%#', (rect: Rectangle, dx1: number, dy1: number, dx2: number, dy2: number, result: Rectangle) => { assert.isTrue(rect.adjusted(dx1, dy1, dx2, dy2).equals(result)); }); }); describe('united', () => { test.each([ [rectangle(vector2d(3, 2), vector2d(3, 2)), rectangle(vector2d(5, 3), vector2d(2, 3)), rectangle(vector2d(3, 2), vector2d(4, 4))], [rectangle(vector2d(6, 2), vector2d(-3, 2)), rectangle(vector2d(7, 3), vector2d(-2, 3)), rectangle(vector2d(3, 2), vector2d(4, 4))], [rectangle(vector2d(6, 4), vector2d(-3, -2)), rectangle(vector2d(7, 6), vector2d(-2, -3)), rectangle(vector2d(3, 2), vector2d(4, 4))], [rectangle(vector2d(3, 4), vector2d(3, -2)), rectangle(vector2d(5, 6), vector2d(2, -3)), rectangle(vector2d(3, 2), vector2d(4, 4))], [rectangle(vector2d(3, 2), vector2d(3, 2)), rectangle(vector2d(3, 2), vector2d(3, 2)), rectangle(vector2d(3, 2), vector2d(3, 2))], [rectangle(vector2d(3, 2), vector2d(3, 2)), rectangle(vector2d(4, 3), vector2d(1, 1)), rectangle(vector2d(3, 2), vector2d(3, 2))], [rectangle(vector2d(4, 3), vector2d(1, 1)), rectangle(vector2d(3, 2), vector2d(3, 2)), rectangle(vector2d(3, 2), vector2d(3, 2))], [rectangle(vector2d(3, 2), vector2d(3, 2)), rectangle(vector2d(5, 3)), rectangle(vector2d(3, 2), vector2d(3, 2))], [rectangle(vector2d(3, 2), vector2d(3, 2)), rectangle(vector2d(7, 5)), rectangle(vector2d(3, 2), vector2d(4, 3))], [rectangle(vector2d(3, 2)), rectangle(vector2d(7, 5), vector2d(2, 2)), rectangle(vector2d(3, 2), vector2d(6, 5))], [rectangle(vector2d(7, 5), vector2d(2, 2)), rectangle(vector2d(3, 2)), rectangle(vector2d(3, 2), vector2d(6, 5))], [rectangle(vector2d(3, 2)), rectangle(vector2d(7, 5)), rectangle(vector2d(3, 2), vector2d(4, 3))], [rectangle(vector2d(7, 5)), rectangle(vector2d(3, 2)), rectangle(vector2d(3, 2), vector2d(4, 3))], ])('united#%#', (r1: Rectangle, r2: Rectangle, result: Rectangle) => { assert.isTrue(r1.united(r2).equals(result)); }); }); describe('intersected', () => { test.each([ [rectangle(vector2d(2, 3), vector2d(4, 3)), rectangle(vector2d(4, 4), vector2d(3, 4)), rectangle(vector2d(4, 4), vector2d(2, 2))], [rectangle(vector2d(6, 3), vector2d(-4, 3)), rectangle(vector2d(7, 4), vector2d(-3, 4)), rectangle(vector2d(4, 4), vector2d(2, 2))], [rectangle(vector2d(6, 6), vector2d(-4, -3)), rectangle(vector2d(7, 8), vector2d(-3, -4)), rectangle(vector2d(4, 4), vector2d(2, 2))], [rectangle(vector2d(2, 6), vector2d(4, -3)), rectangle(vector2d(4, 8), vector2d(3, -4)), rectangle(vector2d(4, 4), vector2d(2, 2))], [rectangle(vector2d(2, 3), vector2d(4, 3)), rectangle(vector2d(2, 3), vector2d(4, 3)), rectangle(vector2d(2, 3), vector2d(4, 3))], [rectangle(vector2d(2, 3), vector2d(4, 3)), rectangle(vector2d(7, 8), vector2d(2, 3)), rectangle()], [rectangle(vector2d(2, 3), vector2d(4, 3)), rectangle(vector2d(4, 4)), rectangle(vector2d(4, 4))], [rectangle(vector2d(2, 3)), rectangle(vector2d(4, 4)), rectangle()], [rectangle(vector2d(2, 3)), rectangle(vector2d(2, 3)), rectangle(vector2d(2, 3))], [rectangle(vector2d(1, 1), vector2d(3, 2)), rectangle(vector2d(1, 5), vector2d(3, 2)), rectangle()], [rectangle(vector2d(1, 5), vector2d(3, 2)), rectangle(vector2d(1, 1), vector2d(3, 2)), rectangle()], ])('intersected#%#', (r1: Rectangle, r2: Rectangle, result: Rectangle) => { assert.isTrue(r1.intersected(r2).equals(result)); }); }); describe('normalized', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), rectangle(vector2d(5, 4), vector2d(3, 2))], [rectangle(vector2d(8, 4), vector2d(-3, 2)), rectangle(vector2d(5, 4), vector2d(3, 2))], [rectangle(vector2d(8, 6), vector2d(-3, -2)), rectangle(vector2d(5, 4), vector2d(3, 2))], [rectangle(vector2d(5, 6), vector2d(3, -2)), rectangle(vector2d(5, 4), vector2d(3, 2))], [rectangle(vector2d(5, 4), vector2d(3, 0)), rectangle(vector2d(5, 4), vector2d(3, 0))], [rectangle(vector2d(8, 4), vector2d(-3, 0)), rectangle(vector2d(5, 4), vector2d(3, 0))], [rectangle(vector2d(5, 4), vector2d(0, 2)), rectangle(vector2d(5, 4), vector2d(0, 2))], [rectangle(vector2d(5, 6), vector2d(0, -2)), rectangle(vector2d(5, 4), vector2d(0, 2))], [rectangle(vector2d(5, 4)), rectangle(vector2d(5, 4))], ])('normalized#%#', (rect: Rectangle, result: Rectangle) => { assert.isTrue(rect.normalized().equals(result)); }); }); describe('boundingRectangle', () => { test.each([ [rectangle(vector2d(5, 4), vector2d(3, 2)), rectangle(vector2d(5, 4), vector2d(3, 2))], [rectangle(vector2d(8, 4), vector2d(-3, 2)), rectangle(vector2d(5, 4), vector2d(3, 2))], [rectangle(vector2d(8, 6), vector2d(-3, -2)), rectangle(vector2d(5, 4), vector2d(3, 2))], [rectangle(vector2d(5, 6), vector2d(3, -2)), rectangle(vector2d(5, 4), vector2d(3, 2))], [rectangle(vector2d(5, 4), vector2d(3, 0)), rectangle(vector2d(5, 4), vector2d(3, 0))], [rectangle(vector2d(8, 4), vector2d(-3, 0)), rectangle(vector2d(5, 4), vector2d(3, 0))], [rectangle(vector2d(5, 4), vector2d(0, 2)), rectangle(vector2d(5, 4), vector2d(0, 2))], [rectangle(vector2d(5, 6), vector2d(0, -2)), rectangle(vector2d(5, 4), vector2d(0, 2))], [rectangle(vector2d(5, 4)), rectangle(vector2d(5, 4))], ])('boundingRectangle#%#', (rect: Rectangle, result: Rectangle) => { assert.isTrue(rect.boundingRectangle().equals(result)); }); }); describe('translate', () => { test.each([ [rectangle(), vector2d(1, 1), rectangle(vector2d(1, 1))], [rectangle(vector2d(1, 2), vector2d(3, 4)), vector2d(), rectangle(vector2d(1, 2), vector2d(3, 4))], [rectangle(vector2d(1, 2), vector2d(3, 4)), vector2d(1, 1), rectangle(vector2d(2, 3), vector2d(3, 4))], ])('translate#%#', (rect: Rectangle, offset: Vector2D, result: Rectangle) => { assert.isTrue(rect.translate(offset.x, offset.y) === rect); assert.isTrue(rect.equals(result)); }); }); describe('translated', () => { test.each([ [rectangle(), vector2d(1, 1), rectangle(vector2d(1, 1))], [rectangle(vector2d(1, 2), vector2d(3, 4)), vector2d(), rectangle(vector2d(1, 2), vector2d(3, 4))], [rectangle(vector2d(1, 2), vector2d(3, 4)), vector2d(1, 1), rectangle(vector2d(2, 3), vector2d(3, 4))], ])('translated#%#', (rect: Rectangle, offset: Vector2D, result: Rectangle) => { assert.isTrue(rect.translated(offset.x, offset.y).equals(result)); }); }); describe('transform', () => { test.each([ [rectangle(vector2d(2, 2), vector2d(3, -2)), matrix().translate(2, 2).scale(2).rotate(radians(90)), rectangle(vector2d(-2, 6), vector2d(4, 6))], [rectangle(vector2d(2, 2), vector2d(3, 2)), matrix().translate(2, 2), rectangle(vector2d(4, 4), vector2d(3, 2))], [rectangle(vector2d(2, 2), vector2d(-3, -2)), matrix().translate(2, 2), rectangle(vector2d(1, 2), vector2d(3, 2))], ])('transform#%#', (r: Rectangle, m: Matrix, result: Rectangle) => { assert.isTrue(r.transform(m) === r); assert.isTrue(r.fuzzyEquals(result)); }); }); describe('transformed', () => { test.each([ [rectangle(vector2d(2, 2), vector2d(3, -2)), matrix().translate(2, 2).scale(2).rotate(radians(90)), rectangle(vector2d(-2, 6), vector2d(4, 6))], [rectangle(vector2d(2, 2), vector2d(3, 2)), matrix().translate(2, 2), rectangle(vector2d(4, 4), vector2d(3, 2))], [rectangle(vector2d(2, 2), vector2d(-3, -2)), matrix().translate(2, 2), rectangle(vector2d(1, 2), vector2d(3, 2))], ])('transformed#%#', (r1: Rectangle, m: Matrix, result: Rectangle) => { const r2 = r1.transformed(m); assert.isTrue(r2 instanceof Rectangle); assert.isTrue(r2.fuzzyEquals(result)); }); }); describe('map', () => { it('map', () => { const r = rectangle(vector2d(2.3, 3.6), vector2d(-1.1, 0.5)); const bind2nd = (fn: (arg1: T1, arg2: T2) => R, boundArg: T2) => (arg: T1) => fn(arg, boundArg); assert.isTrue(r.map(p => p.map(Math.ceil)).equals(rectangle(r.p.map(Math.ceil), r.s.map(Math.ceil)))); assert.isTrue(r.map(p => p.map(bind2nd(Math.pow, 2))).equals(rectangle(r.p.map(bind2nd(Math.pow, 2)), r.s.map(bind2nd(Math.pow, 2))))); }); }); describe('containsPoint', () => { test.each([ [rectangle(), point(), false], [rectangle(vector2d(1, 1)), point(), false], [rectangle(), point(1, 1), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(1, 1), false], [rectangle(vector2d(9, 8), vector2d(-6, -4)), point(1, 1), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(6, 6), true], [rectangle(vector2d(9, 8), vector2d(-6, -4)), point(6, 6), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(3, 4), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(6, 4), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(3, 6), false], [rectangle(vector2d(3, 4)), point(3, 4), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), point(6, 4), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), point(11, 4), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), point(6, 5), false], ])('containsPoint#%#', (rectangle: Rectangle, point: Point, result: boolean) => { assert.isTrue(rectangle.containsPoint(point) === result); }); }); describe('containsLine', () => { test.each([ [rectangle(), line(), false], [rectangle(vector2d(1, 1)), line(), false], [rectangle(), line(vector2d(1, 1), vector2d(1, 1)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(4, 7), vector2d(8, 5)), true], [rectangle(vector2d(9, 8), vector2d(-6, -4)), line(vector2d(4, 7), vector2d(8, 5)), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(3, 8), vector2d(9, 4)), false], [rectangle(vector2d(9, 8), vector2d(-6, -4)), line(vector2d(3, 8), vector2d(9, 4)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(2, 9), vector2d(9, 4)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(2, 9), vector2d(10, 3)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(0, 0), vector2d(2, 2)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(6, 6), vector2d(11, 1)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(6, 6), vector2d(6, 6)), true], [rectangle(vector2d(3, 4), vector2d(6, 0)), line(vector2d(4, 4), vector2d(8, 4)), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), line(vector2d(4, 3), vector2d(8, 4)), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), line(vector2d(3, 5), vector2d(3, 7)), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), line(vector2d(3, 5), vector2d(4, 7)), false], ])('containsLine#%#', (rect: Rectangle, line: Line, result: boolean) => { assert.isTrue(rect.containsLine(line) === result); }); }); describe('containsCircle', () => { test.each([ [rectangle(), circle(), false], [rectangle(), circle(vector2d(0, 0), 1), false], [rectangle(), circle(vector2d(1, 1)), false], [rectangle(vector2d(1, 1)), circle(), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6)), true], [rectangle(vector2d(9, 8), vector2d(-6, -4)), circle(vector2d(6, 6)), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6), 1), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6), 2), false], [rectangle(vector2d(9, 8), vector2d(-6, -4)), circle(vector2d(6, 6), 2), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6), 3), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6), 4), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 1), 3), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), circle(vector2d(6, 4), 0), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), circle(vector2d(6, 4), 1), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), circle(vector2d(3, 6), 0), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), circle(vector2d(3, 6), 1), false], ])('containsCircle#%#', (rectangle: Rectangle, circle: Circle, result: boolean) => { assert.isTrue(rectangle.containsCircle(circle) === result); }); }); describe('containsRectangle', () => { test.each([ [rectangle(), rectangle(), false], [rectangle(), rectangle(vector2d(1, 1)), false], [rectangle(vector2d(1, 1)), rectangle(), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(4, 5), vector2d(4, 2)), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(8, 7), vector2d(-4, -2)), true], [rectangle(vector2d(9, 4), vector2d(-6, 4)), rectangle(vector2d(4, 5), vector2d(4, 2)), true], [rectangle(vector2d(9, 8), vector2d(-6, -4)), rectangle(vector2d(4, 5), vector2d(4, 2)), true], [rectangle(vector2d(3, 8), vector2d(6, -4)), rectangle(vector2d(4, 5), vector2d(4, 2)), true], [rectangle(vector2d(4, 5), vector2d(4, 2)), rectangle(vector2d(3, 4), vector2d(6, 4)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(8, 7), vector2d(4, 2)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(8, 7), vector2d(1, 1)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(8, 7), vector2d(0, 0)), true], [rectangle(vector2d(3, 4), vector2d(6, 0)), rectangle(vector2d(6, 4), vector2d(2, 0)), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), rectangle(vector2d(6, 4), vector2d(2, 1)), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), rectangle(vector2d(6, 4), vector2d(4, 0)), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), rectangle(vector2d(3, 6), vector2d(0, 2)), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), rectangle(vector2d(3, 6), vector2d(1, 2)), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), rectangle(vector2d(3, 6), vector2d(0, 3)), false], ])('containsRectangle#%#', (rect1: Rectangle, rect2: Rectangle, result: boolean) => { assert.isTrue(rect1.containsRectangle(rect2) === result); }); }); describe('containsPolygon', () => { test.each([ [rectangle(), polygon(), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon(), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(6, 5), vector2d(6, 7), vector2d(4, 6)]), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(6, 5), vector2d(6, 7)]), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(6, 5)]), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(9, 5), vector2d(9, 7), vector2d(7, 6)]), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(4, 5), vector2d(4, 7), vector2d(2, 6)]), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(6, 1), vector2d(7, 3), vector2d(5, 3)]), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(2, 3), vector2d(10, 3), vector2d(10, 9), vector2d(2, 9)]), false], ])('containsPolygon#%#', (rectangle: Rectangle, polygon: Polygon, result: boolean) => { assert.isTrue(rectangle.containsPolygon(polygon) === result); }); }); describe('containsPolyline', () => { test.each([ [rectangle(), polyline(), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polyline(), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polyline([vector2d(6, 5), vector2d(6, 7), vector2d(4, 6)]), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), polyline([vector2d(6, 5), vector2d(6, 7)]), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), polyline([vector2d(6, 5)]), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), polyline([vector2d(9, 5), vector2d(9, 7), vector2d(7, 6)]), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polyline([vector2d(4, 5), vector2d(4, 7), vector2d(2, 6)]), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polyline([vector2d(6, 1), vector2d(7, 3), vector2d(5, 3)]), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polyline([vector2d(2, 3), vector2d(10, 3), vector2d(10, 9), vector2d(2, 9)]), false], ])('containsPolyline#%#', (rectangle: Rectangle, polyline: Polyline, result: boolean) => { assert.isTrue(rectangle.containsPolyline(polyline) === result); }); }); describe('contains', () => { test.each([ [rectangle(), point(), false], [rectangle(vector2d(1, 1)), point(), false], [rectangle(), point(1, 1), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(1, 1), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(6, 6), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(3, 4), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(6, 4), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(3, 6), false], [rectangle(vector2d(3, 4)), point(3, 4), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), point(6, 4), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), point(11, 4), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), point(6, 5), false], [rectangle(), line(), false], [rectangle(vector2d(1, 1)), line(), false], [rectangle(), line(vector2d(1, 1), vector2d(1, 1)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(4, 7), vector2d(8, 5)), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(3, 8), vector2d(9, 4)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(2, 9), vector2d(9, 4)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(2, 9), vector2d(10, 3)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(0, 0), vector2d(2, 2)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(6, 6), vector2d(11, 1)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(6, 6), vector2d(6, 6)), true], [rectangle(vector2d(3, 4), vector2d(6, 0)), line(vector2d(4, 4), vector2d(8, 4)), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), line(vector2d(4, 3), vector2d(8, 4)), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), line(vector2d(3, 5), vector2d(3, 7)), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), line(vector2d(3, 5), vector2d(4, 7)), false], [rectangle(), circle(), false], [rectangle(), circle(vector2d(0, 0), 1), false], [rectangle(), circle(vector2d(1, 1)), false], [rectangle(vector2d(1, 1)), circle(), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6)), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6), 1), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6), 2), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6), 3), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6), 4), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 1), 3), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), circle(vector2d(6, 4), 0), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), circle(vector2d(6, 4), 1), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), circle(vector2d(3, 6), 0), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), circle(vector2d(3, 6), 1), false], [rectangle(), rectangle(), false], [rectangle(), rectangle(vector2d(1, 1)), false], [rectangle(vector2d(1, 1)), rectangle(), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(4, 5), vector2d(4, 2)), true], [rectangle(vector2d(9, 4), vector2d(-6, 4)), rectangle(vector2d(4, 5), vector2d(4, 2)), true], [rectangle(vector2d(9, 8), vector2d(-6, -4)), rectangle(vector2d(4, 5), vector2d(4, 2)), true], [rectangle(vector2d(3, 8), vector2d(6, -4)), rectangle(vector2d(4, 5), vector2d(4, 2)), true], [rectangle(vector2d(4, 5), vector2d(4, 2)), rectangle(vector2d(3, 4), vector2d(6, 4)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(8, 7), vector2d(4, 2)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(8, 7), vector2d(1, 1)), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(8, 7), vector2d(0, 0)), true], [rectangle(vector2d(3, 4), vector2d(6, 0)), rectangle(vector2d(6, 4), vector2d(2, 0)), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), rectangle(vector2d(6, 4), vector2d(2, 1)), false], [rectangle(vector2d(3, 4), vector2d(6, 0)), rectangle(vector2d(6, 4), vector2d(4, 0)), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), rectangle(vector2d(3, 6), vector2d(0, 2)), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), rectangle(vector2d(3, 6), vector2d(1, 2)), false], [rectangle(vector2d(3, 4), vector2d(0, 4)), rectangle(vector2d(3, 6), vector2d(0, 3)), false], [rectangle(), polygon(), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon(), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(6, 5), vector2d(6, 7), vector2d(4, 6)]), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(6, 5), vector2d(6, 7)]), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(6, 5)]), true], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(9, 5), vector2d(9, 7), vector2d(7, 6)]), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(4, 5), vector2d(4, 7), vector2d(2, 6)]), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(6, 1), vector2d(7, 3), vector2d(5, 3)]), false], [rectangle(vector2d(3, 4), vector2d(6, 4)), polygon([vector2d(2, 3), vector2d(10, 3), vector2d(10, 9), vector2d(2, 9)]), false], ])('contains#%#', (shape1: Shape, shape2: Shape, result: boolean) => { assert.isTrue(shape2.contains(shape1) === result); }); }); describe('intersectsPoint', () => { test.each([ [rectangle(vector2d(3, 4), vector2d(6, 4)), point(6, 4), true, [vector2d(6, 4)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(9, 6), true, [vector2d(9, 6)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(6, 8), true, [vector2d(6, 8)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(3, 6), true, [vector2d(3, 6)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(6, 6), false, undefined], ])('intersectsPoint#%#', (rectangle: Rectangle, point: Point, result: boolean, points: Vector2D[] | undefined) => { assert.isTrue(rectangle.intersectsPoint(point) === result); const intersection: any = {}; rectangle.intersectsPoint(point, function (this: any, points, thisShape, otherShape) { assert.isTrue(rectangle === thisShape); assert.isTrue(point === otherShape); this.points = this.points === undefined ? points : this.points.concat(points); return false; }, intersection); assert.isTrue(fuzzyDeepEqual(intersection.points, points), `${intersection.points} !== ${points}`); }); it('intersectsPoint#callbackReturnsTrue', () => { assert.isTrue(rectangle(vector2d(3, 4), vector2d(6, 4)).intersectsPoint(point(6, 4), function () { return true; })); assert.isFalse(rectangle(vector2d(3, 4), vector2d(6, 4)).intersectsPoint(point(6, 6), function () { return true; })); }); }); describe('intersectsLine', () => { test.each([ [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(6, 6), vector2d(6, 2)), true, [vector2d(6, 4)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(6, 6), vector2d(12, 6)), true, [vector2d(9, 6)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(6, 6), vector2d(6, 10)), true, [vector2d(6, 8)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(6, 6), vector2d(0, 6)), true, [vector2d(3, 6)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(5, 5), vector2d(7, 7)), false, undefined], ])('intersectsLine#%#', (rectangle: Rectangle, line: Line, result: boolean, points: Vector2D[] | undefined) => { assert.isTrue(rectangle.intersectsLine(line) === result); const intersection: any = {}; rectangle.intersectsLine(line, function (this: any, points, thisShape, otherShape) { assert.isTrue(rectangle === thisShape); assert.isTrue(line === otherShape); this.points = this.points === undefined ? points : this.points.concat(points); return false; }, intersection); assert.isTrue(fuzzyDeepEqual(intersection.points, points), `${intersection.points} !== ${points}`); }); it('intersectsLine#callbackReturnsTrue', () => { assert.isTrue(rectangle(vector2d(3, 4), vector2d(6, 4)).intersectsLine(line(vector2d(6, 6), vector2d(6, 2)), function () { return true; })); assert.isFalse(rectangle(vector2d(3, 4), vector2d(6, 4)).intersectsLine(line(vector2d(5, 5), vector2d(7, 7)), function () { return true; })); }); }); describe('intersectsCircle', () => { test.each([ [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 4), 1), true, [vector2d(5, 4), vector2d(7, 4)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(9, 6), 1), true, [vector2d(9, 5), vector2d(9, 7)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 8), 1), true, [vector2d(7, 8), vector2d(5, 8)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(3, 6), 1), true, [vector2d(3, 7), vector2d(3, 5)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6), 1), false, undefined], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6), 10), false, undefined], ])('intersectsCircle#%#', (rectangle: Rectangle, circle: Circle, result: boolean, points: Vector2D[] | undefined) => { assert.isTrue(rectangle.intersectsCircle(circle) === result); const intersection: any = {}; rectangle.intersectsCircle(circle, function (this: any, points, thisShape, otherShape) { assert.isTrue(rectangle === thisShape); assert.isTrue(circle === otherShape); this.points = this.points === undefined ? points : this.points.concat(points); return false; }, intersection); assert.isTrue(fuzzyDeepEqual(intersection.points, points), `${intersection.points} !== ${points}`); }); it('intersectsCircle#callbackReturnsTrue', () => { assert.isTrue(rectangle(vector2d(3, 4), vector2d(6, 4)).intersectsCircle(circle(vector2d(6, 4), 1), function () { return true; })); assert.isFalse(rectangle(vector2d(3, 4), vector2d(6, 4)).intersectsCircle(circle(vector2d(6, 6), 1), function () { return true; })); }); }); describe('intersectsRectangle', () => { test.each([ [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(5, 3), vector2d(2, 2)), true, [vector2d(7, 4), vector2d(5, 4)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(8, 5), vector2d(2, 2)), true, [vector2d(9, 5), vector2d(9, 7)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(5, 7), vector2d(2, 2)), true, [vector2d(7, 8), vector2d(5, 8)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(2, 5), vector2d(2, 2)), true, [vector2d(3, 5), vector2d(3, 7)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(2, 3), vector2d(8, 2)), true, [vector2d(9, 5), vector2d(3, 5)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(8, 3), vector2d(2, 6)), true, [vector2d(8, 4), vector2d(8, 8)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(5, 5), vector2d(2, 2)), false, undefined], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(2, 3), vector2d(12, 8)), false, undefined], ])('intersectsRectangle#%#', (rect1: Rectangle, rect2: Rectangle, result: boolean, points: Vector2D[] | undefined) => { assert.isTrue(rect1.intersectsRectangle(rect2) === result); const intersection: any = {}; rect1.intersectsRectangle(rect2, function (this: any, points, thisShape, otherShape) { assert.isTrue(rect1 === thisShape); assert.isTrue(rect2 === otherShape); this.points = this.points === undefined ? points : this.points.concat(points); return false; }, intersection); assert.isTrue(fuzzyDeepEqual(intersection.points, points), `${intersection.points} !== ${points}`); }); it('intersectsRectangle#callbackReturnsTrue', () => { assert.isTrue(rectangle(vector2d(3, 4), vector2d(6, 4)).intersectsRectangle(rectangle(vector2d(5, 3), vector2d(2, 2)), function () { return true; })); assert.isFalse(rectangle(vector2d(3, 4), vector2d(6, 4)).intersectsRectangle(rectangle(vector2d(2, 3), vector2d(12, 8)), function () { return true; })); }); }); describe('intersects', () => { test.each([ [rectangle(vector2d(3, 4), vector2d(6, 4)), point(6, 4), true, [vector2d(6, 4)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(9, 6), true, [vector2d(9, 6)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(6, 8), true, [vector2d(6, 8)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(3, 6), true, [vector2d(3, 6)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), point(6, 6), false, undefined], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(6, 6), vector2d(6, 2)), true, [vector2d(6, 4)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(6, 6), vector2d(12, 6)), true, [vector2d(9, 6)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(6, 6), vector2d(6, 10)), true, [vector2d(6, 8)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(6, 6), vector2d(0, 6)), true, [vector2d(3, 6)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), line(vector2d(5, 5), vector2d(7, 7)), false, undefined], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 4), 1), true, [vector2d(5, 4), vector2d(7, 4)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(9, 6), 1), true, [vector2d(9, 5), vector2d(9, 7)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 8), 1), true, [vector2d(7, 8), vector2d(5, 8)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(3, 6), 1), true, [vector2d(3, 7), vector2d(3, 5)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6), 1), false, undefined], [rectangle(vector2d(3, 4), vector2d(6, 4)), circle(vector2d(6, 6), 10), false, undefined], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(5, 3), vector2d(2, 2)), true, [vector2d(7, 4), vector2d(5, 4)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(8, 5), vector2d(2, 2)), true, [vector2d(9, 5), vector2d(9, 7)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(5, 7), vector2d(2, 2)), true, [vector2d(7, 8), vector2d(5, 8)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(2, 5), vector2d(2, 2)), true, [vector2d(3, 5), vector2d(3, 7)]], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(5, 5), vector2d(2, 2)), false, undefined], [rectangle(vector2d(3, 4), vector2d(6, 4)), rectangle(vector2d(2, 3), vector2d(12, 8)), false, undefined], [rectangle(vector2d(5, 5), vector2d(2, 2)), polygon([vector2d(2, 7), vector2d(6, 1), vector2d(10, 7)]), true, [vector2d(7, 7), vector2d(7, 7), vector2d(5, 7), vector2d(5, 7)]], [rectangle(vector2d(5, 4), vector2d(2, 2)), polygon([vector2d(2, 7), vector2d(6, 1), vector2d(10, 7)]), false, undefined], [rectangle(vector2d(4, 4), vector2d(2, 2)), polyline([vector2d(2, 7), vector2d(6, 1), vector2d(10, 7)]), true, [vector2d(4, 4), vector2d(4, 4)]], [rectangle(vector2d(5, 5), vector2d(2, 2)), polyline([vector2d(2, 7), vector2d(6, 1), vector2d(10, 7)]), false, undefined], ])('intersects#%#', (s1: Shape, s2: Shape, result: boolean, points: Vector2D[] | undefined) => { assert.isTrue(s2.intersects(s1) === result); const intersection: any = {}; s2.intersects(s1, function (this: any, points, thisShape, otherShape) { assert.isTrue(intersection === this); assert.isTrue(s1 === thisShape); assert.isTrue(s2 === otherShape); this.points = this.points === undefined ? points : this.points.concat(points); return false; }, intersection); assert.isTrue(fuzzyDeepEqual(intersection.points, points), `${intersection.points} !== ${points}`); }); }); describe('render', () => { const end = [ { set: 'strokeStyle', value: undefined, }, { set: 'fillStyle', value: undefined, } ]; test.each([ [ rectangle(), undefined, undefined, [ { apply: 'beginPath', args: [] }, { apply: 'rect', args: [0, 0, 0, 0] }, { apply: 'stroke', args: [] }, ...end ] ], [ rectangle(vector2d(1, 2), vector2d(3, 4)), undefined, undefined, [ { apply: 'beginPath', args: [] }, { apply: 'rect', args: [1, 2, 3, 4] }, { apply: 'stroke', args: [] }, ...end ] ], [ rectangle(vector2d(1, 2), vector2d(3, 4)), 'yellow', undefined, [ { set: 'strokeStyle', value: 'yellow', }, { apply: 'beginPath', args: [] }, { apply: 'rect', args: [1, 2, 3, 4] }, { apply: 'stroke', args: [] }, ...end ] ], [ rectangle(vector2d(1, 2), vector2d(3, 4)), undefined, 'yellow', [ { set: 'fillStyle', value: 'yellow', }, { apply: 'fillRect', args: [1, 2, 3, 4] }, ...end ] ], [ rectangle(vector2d(1, 2), vector2d(3, 4)), 'yellow', 'black', [ { set: 'strokeStyle', value: 'yellow', }, { set: 'fillStyle', value: 'black', }, { apply: 'fillRect', args: [1, 2, 3, 4] }, { apply: 'beginPath', args: [] }, { apply: 'rect', args: [1, 2, 3, 4] }, { apply: 'stroke', args: [] }, ...end ] ], ])('render#%#', (r: Rectangle, strokeStyle: string | undefined, fillStyle: string | undefined, result: any[]) => { const interceptions: any[] = []; const context = canvasRenderingContext2DSpy(interceptions); r.render(context, strokeStyle, fillStyle); assert.deepEqual(interceptions, result); }); }); describe('Rectangle.create', () => { it('default constructor', () => { const r = Rectangle.create(); assert.strictEqual(r.p.x, 0); assert.strictEqual(r.p.y, 0); assert.strictEqual(r.s.x, 0); assert.strictEqual(r.s.y, 0); }); it('topLeft constructor', () => { const r = Rectangle.create(new Vector2D(1, 2)); assert.strictEqual(r.p.x, 1); assert.strictEqual(r.p.y, 2); assert.strictEqual(r.s.x, 0); assert.strictEqual(r.s.y, 0); }); it('topLeft, size constructor', () => { const r = Rectangle.create(new Vector2D(1, 2), new Vector2D(3, 4)); assert.strictEqual(r.p.x, 1); assert.strictEqual(r.p.y, 2); assert.strictEqual(r.s.x, 3); assert.strictEqual(r.s.y, 4); }); }); });