Files
blockly/tests/mocha/rect_test.js
Ben Henning 3a3e83fe44 Fix workspace clean up not considering immovables.
At a high-level, this change ensures that cleaning up a workspace
doesn't move blocks in a way that overlaps with immovable blocks. It
also adds missing testing coverage for both Rect (used for bounding box
calculations during workspace cleanup) and WorkspaceSvg (for verifying
the updated clean up functionality).

This also renames the clean up function to be 'tidyUp' since that better
suits what's happening (as opposed to other clean-up routines which are
actually deinitializing objects).
2024-08-21 17:41:38 +00:00

969 lines
39 KiB
JavaScript

/**
* @license
* Copyright 2024 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {assert} from '../../node_modules/chai/chai.js';
import {
sharedTestSetup,
sharedTestTeardown,
} from './test_helpers/setup_teardown.js';
suite('Rect', function () {
setup(function () {
sharedTestSetup.call(this);
this.createCoord = function(x, y) {
return new Blockly.utils.Coordinate(x, y);
};
});
teardown(function () {
sharedTestTeardown.call(this);
});
suite('Rect()', function () {
test('initializes properties correctly', function() {
const rect = new Blockly.utils.Rect(1, 2, 3, 4);
assert.equal(rect.top, 1, 'top should be initialized');
assert.equal(rect.bottom, 2, 'bottom should be initialized');
assert.equal(rect.left, 3, 'left should be initialized');
assert.equal(rect.right, 4, 'right should be initialized');
});
});
suite('createFromPoint()', function () {
test('initializes properties correctly', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
assert.equal(rect.top, 2, 'top should be initialized');
assert.equal(rect.bottom, 47, 'bottom should be initialized');
assert.equal(rect.left, 1, 'left should be initialized');
assert.equal(rect.right, 24, 'right should be initialized');
});
});
suite('clone()', function () {
test('copies properties correctly', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const clonedRect = rect.clone();
assert.equal(clonedRect.top, rect.top, 'top should be cloned');
assert.equal(clonedRect.bottom, rect.bottom, 'bottom should be cloned');
assert.equal(clonedRect.left, rect.left, 'left should be cloned');
assert.equal(clonedRect.right, rect.right, 'right should be cloned');
});
});
suite('equals()', function () {
test('same object instance should equal itself', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const areEqual = Blockly.utils.Rect.equals(rect, rect)
assert.isTrue(areEqual, 'an instance should equal itself');
});
test('null instances should be equal', function() {
const areEqual = Blockly.utils.Rect.equals(null, null)
assert.isTrue(areEqual, 'null should equal null');
});
test('an object and null should not be equal', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const areEqual = Blockly.utils.Rect.equals(rect, null)
assert.isFalse(areEqual, 'non-null should not equal null');
});
test('null and an object should not be equal', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const areEqual = Blockly.utils.Rect.equals(null, rect)
assert.isFalse(areEqual, 'null should not equal non-null');
});
test('object should equal its clone', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const areEqual = Blockly.utils.Rect.equals(rect, rect.clone())
assert.isTrue(areEqual, 'an instance and its clone should be equal');
});
test('object should equal its clone', function() {
const rect1 = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const rect2 = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const areEqual = Blockly.utils.Rect.equals(rect1, rect2)
assert.isTrue(areEqual, 'two objects constructed in the same way should be equal');
});
test('object should not equal object with different x position', function() {
const rect1 = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const rect2 = Blockly.utils.Rect.createFromPoint(this.createCoord(3, 2), 23, 45);
const areEqual = Blockly.utils.Rect.equals(rect1, rect2)
assert.isFalse(areEqual, 'two objects with different x positions should not be equal');
});
test('object should not equal object with different y position', function() {
const rect1 = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const rect2 = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 4), 23, 45);
const areEqual = Blockly.utils.Rect.equals(rect1, rect2)
assert.isFalse(areEqual, 'two objects with different y positions should not be equal');
});
test('object should not equal object with different x and y positions', function() {
const rect1 = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const rect2 = Blockly.utils.Rect.createFromPoint(this.createCoord(3, 4), 23, 45);
const areEqual = Blockly.utils.Rect.equals(rect1, rect2)
assert.isFalse(areEqual, 'two objects with different x/y positions should not be equal');
});
test('object should not equal object with different width', function() {
const rect1 = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const rect2 = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 46, 45);
const areEqual = Blockly.utils.Rect.equals(rect1, rect2)
assert.isFalse(areEqual, 'two objects with different widths should not be equal');
});
test('object should not equal object with different height', function() {
const rect1 = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const rect2 = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 89);
const areEqual = Blockly.utils.Rect.equals(rect1, rect2)
assert.isFalse(areEqual, 'two objects with different heights should not be equal');
});
test('object should not equal object with all different properties', function() {
const rect1 = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const rect2 = Blockly.utils.Rect.createFromPoint(this.createCoord(3, 4), 46, 89);
const areEqual = Blockly.utils.Rect.equals(rect1, rect2)
assert.isFalse(areEqual, 'two objects with all different properties should not be equal');
});
});
suite('getHeight()', function () {
test('computes zero height for empty rectangle', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(0, 0), 0, 0);
assert.equal(rect.getHeight(), 0, 'height should be 0');
});
test('computes height of 1 for unit square rectangle', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(0, 0), 1, 1);
assert.equal(rect.getHeight(), 1, 'height should be 1');
});
test('computes height of 1 for unit square rectangle not at origin', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 1, 1);
assert.equal(rect.getHeight(), 1, 'height should be 1');
});
test('computes height of 1 for unit square rectangle with negative position', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(-1, -2), 1, 1);
assert.equal(rect.getHeight(), 1, 'height should be 1');
});
test('computes decimal height for non-square rectangle not at origin', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1.1, 2.2), 3.3, 4.4);
assert.approximately(rect.getHeight(), 4.4, 1e-5, 'height should be 4.4');
});
});
suite('getWidth()', function () {
test('computes zero width for empty rectangle', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(0, 0), 0, 0);
assert.equal(rect.getWidth(), 0, 'width should be 0');
});
test('computes width of 1 for unit square rectangle', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(0, 0), 1, 1);
assert.equal(rect.getWidth(), 1, 'width should be 1');
});
test('computes width of 1 for unit square rectangle not at origin', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 1, 1);
assert.equal(rect.getWidth(), 1, 'width should be 1');
});
test('computes width of 1 for unit square rectangle with negative position', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(-1, -2), 1, 1);
assert.equal(rect.getWidth(), 1, 'width should be 1');
});
test('computes decimal width for non-square rectangle not at origin', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1.1, 2.2), 3.3, 4.4);
assert.approximately(rect.getWidth(), 3.3, 1e-5, 'width should be 3.3');
});
});
suite('contains()', function () {
suite('point contained within rect', function () {
test('origin for zero-sized square', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(0, 0), 0, 0);
const isContained = rect.contains(0, 0);
assert.isTrue(isContained, 'Rect contains (0, 0)');
});
test('whole number centroid for square at origin', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(0, 0), 2, 2);
const isContained = rect.contains(1, 1);
assert.isTrue(isContained, 'Rect contains (1, 1)');
});
test('decimal number centroid for square at origin', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(0, 0), 1, 1);
const isContained = rect.contains(0.5, 0.5);
assert.isTrue(isContained, 'Rect contains (0.5, 0.5)');
});
test('centroid for non-square not at origin', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(2.5, 4);
assert.isTrue(isContained, 'Rect contains (2.5, 4)');
});
test('negative centroid for non-square not at origin', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(-10, -20), 3, 5);
const isContained = rect.contains(-8.5, -17.5);
assert.isTrue(isContained, 'Rect contains (-8.5, -17.5)');
});
test('NW corner', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(1, 2);
assert.isTrue(isContained, 'Rect contains (1, 2)');
});
test('NE corner', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(4, 2);
assert.isTrue(isContained, 'Rect contains (4, 2)');
});
test('SW corner', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(1, 6);
assert.isTrue(isContained, 'Rect contains (1, 6)');
});
test('SE corner', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(4, 6);
assert.isTrue(isContained, 'Rect contains (4, 6)');
});
test('left edge midpoint', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(1, 4);
assert.isTrue(isContained, 'Rect contains (1, 4)');
});
test('right edge midpoint', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(4, 4);
assert.isTrue(isContained, 'Rect contains (4, 4)');
});
test('top edge midpoint', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(2.5, 2);
assert.isTrue(isContained, 'Rect contains (2.5, 2)');
});
test('bottom edge midpoint', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(2.5, 6);
assert.isTrue(isContained, 'Rect contains (2.5, 6)');
});
});
suite('point not contained within rect', function () {
test('non-origin for zero-sized square', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(0, 0), 0, 0);
const isContained = rect.contains(0.1, 0.1);
assert.isFalse(isContained, 'Rect does not contain (0.1, 0.1)');
});
test('point at midpoint x but above unit square', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const isContained = rect.contains(2, 0);
assert.isFalse(isContained, 'Rect does not contain (2, 0)');
});
test('point at midpoint x but below unit square', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const isContained = rect.contains(2, 4);
assert.isFalse(isContained, 'Rect does not contain (2, 4)');
});
test('point at midpoint y but left of unit square', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const isContained = rect.contains(0, 2);
assert.isFalse(isContained, 'Rect does not contain (0, 2)');
});
test('point at midpoint y but right of unit square', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const isContained = rect.contains(4, 2);
assert.isFalse(isContained, 'Rect does not contain (4, 2)');
});
test('positive point far outside positive rectangle', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(45, 89);
assert.isFalse(isContained, 'Rect does not contain (45, 89)');
});
test('negative point far outside positive rectangle', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(-45, -89);
assert.isFalse(isContained, 'Rect does not contain (-45, -89)');
});
test('positive point far outside negative rectangle', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(-10, -20), 3, 5);
const isContained = rect.contains(45, 89);
assert.isFalse(isContained, 'Rect does not contain (45, 89)');
});
test('negative point far outside negative rectangle', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(-10, -20), 3, 5);
const isContained = rect.contains(-45, -89);
assert.isFalse(isContained, 'Rect does not contain (-45, -89)');
});
test('Point just outside NW corner', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(0.9, 1.9);
assert.isFalse(isContained, 'Rect does not contain (0.9, 1.9)');
});
test('Point just outside NE corner', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(4.1, 1.9);
assert.isFalse(isContained, 'Rect does not contain (4.1, 1.9)');
});
test('Point just outside SW corner', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(0.9, 6.1);
assert.isFalse(isContained, 'Rect does not contain (0.9, 6.1)');
});
test('Point just outside SE corner', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(4.1, 6.1);
assert.isFalse(isContained, 'Rect does not contain (4.1, 6.1)');
});
test('Point just outside left edge midpoint', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(0.9, 4);
assert.isFalse(isContained, 'Rect does not contain (0.9, 4)');
});
test('Point just outside right edge midpoint', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(4.1, 4);
assert.isFalse(isContained, 'Rect does not contain (4.1, 4)');
});
test('Point just outside top edge midpoint', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(2.5, 1.9);
assert.isFalse(isContained, 'Rect does not contain (2.5, 1.9)');
});
test('Point just outside bottom edge midpoint', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 3, 4);
const isContained = rect.contains(2.5, 6.1);
assert.isFalse(isContained, 'Rect does not contain (2.5, 6.1)');
});
});
});
// NOTE TO DEVELOPER: For intersection tests, rects are either large (dimension size '2') or small
// (dimension size '1'). For compactness, the comments denoting the scenario being tested try to
// label larger rects with '2' where they can fit, but smaller rects are generally too small to
// fit any text.
suite('intersects()', function () {
suite('does intersect', function () {
test('rect and itself', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const doIntersect = rect.intersects(rect);
assert.isTrue(doIntersect, 'a rect always intersects with itself');
});
test('rect and its clone', function() {
const rect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const doIntersect = rect.intersects(rect.clone());
assert.isTrue(doIntersect, 'a rect always intersects with its clone');
});
test('two rects of the same positions and dimensions', function() {
const rect1 = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const rect2 = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 23, 45);
const doIntersect = rect1.intersects(rect2);
assert.isTrue(doIntersect, 'two rects with the same positions and dimensions intersect');
});
test('upper left/lower right', function() {
// ┌───┐
// │2┌───┐
// └─│─┘2│
// └───┘
const nwRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const seRect = Blockly.utils.Rect.createFromPoint(this.createCoord(2, 2), 2, 2);
const doIntersectOneWay = nwRect.intersects(seRect);
const doIntersectOtherWay = seRect.intersects(nwRect);
assert.isTrue(doIntersectOneWay, 'SE corner of NW rect intersects with SE rect');
assert.isTrue(doIntersectOtherWay, 'NW corner of SE rect intersects with NW rect');
});
test('upper right/lower left', function() {
// ┌───┐
// ┌───┐2│
// │2└─│─┘
// └───┘
const neRect = Blockly.utils.Rect.createFromPoint(this.createCoord(2, 1), 2, 2);
const swRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 2, 2);
const doIntersectOneWay = neRect.intersects(swRect);
const doIntersectOtherWay = swRect.intersects(neRect);
assert.isTrue(doIntersectOneWay, 'SW corner of NE rect intersects with SW rect');
assert.isTrue(doIntersectOtherWay, 'NE corner of SW rect intersects with NE rect');
});
test('small rect overlapping left side of big rect', function() {
// ┌────┐
// ┌───┐2 │
// └───┘ │
// └────┘
const bigRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const smallRect = Blockly.utils.Rect.createFromPoint(this.createCoord(0.5, 1.5), 1, 1);
const doIntersectOneWay = bigRect.intersects(smallRect);
const doIntersectOtherWay = smallRect.intersects(bigRect);
assert.isTrue(doIntersectOneWay, 'big rect intersects top/bottom sides of small rect');
assert.isTrue(doIntersectOtherWay, 'small rect intersects left side of big rect');
});
test('small rect overlapping right side of big rect', function() {
// ┌────┐
// │ 2┌───┐
// │ └───┘
// └────┘
const bigRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const smallRect = Blockly.utils.Rect.createFromPoint(this.createCoord(2.5, 1.5), 1, 1);
const doIntersectOneWay = bigRect.intersects(smallRect);
const doIntersectOtherWay = smallRect.intersects(bigRect);
assert.isTrue(doIntersectOneWay, 'big rect intersects top/bottom sides of small rect');
assert.isTrue(doIntersectOtherWay, 'small rect intersects right side of big rect');
});
test('small rect overlapping top side of big rect', function() {
// ┌─┐
// ┌│─│┐
// │└─┘│
// └───┘
const bigRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const smallRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1.5, 0.5), 1, 1);
const doIntersectOneWay = bigRect.intersects(smallRect);
const doIntersectOtherWay = smallRect.intersects(bigRect);
assert.isTrue(doIntersectOneWay, 'big rect intersects left/right sides of small rect');
assert.isTrue(doIntersectOtherWay, 'small rect intersects top side of big rect');
});
test('small rect overlapping bottom side of big rect', function() {
// ┌───┐
// │┌─┐│
// └│─│┘
// └─┘
const bigRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const smallRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1.5, 2.5), 1, 1);
const doIntersectOneWay = bigRect.intersects(smallRect);
const doIntersectOtherWay = smallRect.intersects(bigRect);
assert.isTrue(doIntersectOneWay, 'big rect intersects left/right sides of small rect');
assert.isTrue(doIntersectOtherWay, 'small rect intersects bottom side of big rect');
});
test('edge only intersection with all corners outside each rect', function() {
// ┌─┐
// │ │
// ┌─────┐
// └─────┘
// │ │
// └─┘
const tallRect = Blockly.utils.Rect.createFromPoint(this.createCoord(2, 1), 1, 2);
const wideRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 2, 1);
const doIntersectOneWay = tallRect.intersects(wideRect);
const doIntersectOtherWay = wideRect.intersects(tallRect);
assert.isTrue(doIntersectOneWay, 'tall rect intersects top/bottom of wide rect');
assert.isTrue(doIntersectOtherWay, 'wide rect intersects left/right of tall rect');
});
test('small rect within larger rect', function() {
// ┌─────┐
// │ ┌─┐ │
// │ └─┘ │
// └─────┘
const bigRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const smallRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1.5, 1.5), 1, 1);
const doIntersectOneWay = bigRect.intersects(smallRect);
const doIntersectOtherWay = smallRect.intersects(bigRect);
assert.isTrue(doIntersectOneWay, 'big rect intersects small rect since it is contained');
assert.isTrue(doIntersectOtherWay, 'small rect intersects big rect since it is contained');
});
test('rects overlapping on left/right sides', function() {
// ┌──┌────┐
// │ 2│ │2 │
// └──└────┘
const leftRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const rightRect = Blockly.utils.Rect.createFromPoint(this.createCoord(2, 1), 2, 2);
const doIntersectOneWay = leftRect.intersects(rightRect);
const doIntersectOtherWay = rightRect.intersects(leftRect);
assert.isTrue(doIntersectOneWay, 'Left rect\'s right overlaps with right rect\'s left');
assert.isTrue(doIntersectOtherWay, 'Right rect\'s left overlaps with left rect\'s right');
});
test('rects overlapping on top/bottom sides', function() {
// ┌───┐
// ┌───┐
// │───│
// └───┘
const topRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const bottomRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2), 2, 2);
const doIntersectOneWay = topRect.intersects(bottomRect);
const doIntersectOtherWay = bottomRect.intersects(topRect);
assert.isTrue(doIntersectOneWay, 'Top rect\'s bottom overlaps with bottom rect\'s top');
assert.isTrue(doIntersectOtherWay, 'Bottom rect\'s top overlaps with top rect\'s bottom');
});
test('rects adjacent on left/right sides', function() {
// ┌───┬───┐
// │ 2 │ 2 │
// └───┴───┘
const leftRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const rightRect = Blockly.utils.Rect.createFromPoint(this.createCoord(3, 1), 2, 2);
const doIntersectOneWay = leftRect.intersects(rightRect);
const doIntersectOtherWay = rightRect.intersects(leftRect);
assert.isTrue(doIntersectOneWay, 'Left rect\'s right intersects with right rect\'s left');
assert.isTrue(doIntersectOtherWay, 'Right rect\'s left intersects with left rect\'s right');
});
test('rects adjacent on top/bottom sides', function() {
// ┌───┐
// │ 2 │
// ├───┤
// │ 2 │
// └───┘
const topRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const bottomRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 3), 2, 2);
const doIntersectOneWay = topRect.intersects(bottomRect);
const doIntersectOtherWay = bottomRect.intersects(topRect);
assert.isTrue(doIntersectOneWay, 'Top rect\'s bottom intersects with bottom rect\'s top');
assert.isTrue(doIntersectOtherWay, 'Bottom rect\'s top intersects with top rect\'s bottom');
});
test('small left rect adjacent to big right rect', function() {
// ┌───┐
// ┌─┐ 2 │
// └─┘ │
// └───┘
const bigRect = Blockly.utils.Rect.createFromPoint(this.createCoord(2, 1), 2, 2);
const smallRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1.5), 1, 1);
const doIntersectOneWay = bigRect.intersects(smallRect);
const doIntersectOtherWay = smallRect.intersects(bigRect);
assert.isTrue(doIntersectOneWay, 'big rect\'s left intersects small rect\'s right');
assert.isTrue(doIntersectOtherWay, 'small rect\'s right intersects big rect\'s left');
});
test('small right rect adjacent to big left rect', function() {
// ┌───┐
// │ 2 ┌─┐
// │ └─┘
// └───┘
const bigRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const smallRect = Blockly.utils.Rect.createFromPoint(this.createCoord(3, 1.5), 1, 1);
const doIntersectOneWay = bigRect.intersects(smallRect);
const doIntersectOtherWay = smallRect.intersects(bigRect);
assert.isTrue(doIntersectOneWay, 'big rect\'s right intersects small rect\'s left');
assert.isTrue(doIntersectOtherWay, 'small rect\'s left intersects big rect\'s right');
});
test('small top rect adjacent to big bottom rect', function() {
// ┌─┐
// ┌└─┘┐
// │ 2 │
// └───┘
const bigRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const smallRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1.5, 0), 1, 1);
const doIntersectOneWay = bigRect.intersects(smallRect);
const doIntersectOtherWay = smallRect.intersects(bigRect);
assert.isTrue(doIntersectOneWay, 'big rect\'s top intersects small rect\'s bottom');
assert.isTrue(doIntersectOtherWay, 'small rect\'s bottom intersects big rect\'s top');
});
test('small bottom rect adjacent to big top rect', function() {
// ┌───┐
// │ 2 │
// └┌─┐┘
// └─┘
const bigRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const smallRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1.5, 3), 1, 1);
const doIntersectOneWay = bigRect.intersects(smallRect);
const doIntersectOtherWay = smallRect.intersects(bigRect);
assert.isTrue(doIntersectOneWay, 'big rect\'s bottom intersects small rect\'s top');
assert.isTrue(doIntersectOtherWay, 'small rect\'s top intersects big rect\'s bottom');
});
test('SW rect corner-adjacent to NE rect', function() {
// ┌───┐
// │ 2 │
// ┌───┐───┘
// │ 2 │
// └───┘
const swRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 3), 2, 2);
const neRect = Blockly.utils.Rect.createFromPoint(this.createCoord(3, 1), 2, 2);
const doIntersectOneWay = swRect.intersects(neRect);
const doIntersectOtherWay = neRect.intersects(swRect);
assert.isTrue(doIntersectOneWay, 'SW rect intersects with SW corner of NE rect');
assert.isTrue(doIntersectOtherWay, 'NE rect intersects with NE corner of SW rect');
});
test('NW rect corner-adjacent to SE rect', function() {
// ┌───┐
// │ 2 │
// └───┘───┐
// │ 2 │
// └───┘
const nwRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const seRect = Blockly.utils.Rect.createFromPoint(this.createCoord(3, 3), 2, 2);
const doIntersectOneWay = seRect.intersects(nwRect);
const doIntersectOtherWay = nwRect.intersects(seRect);
assert.isTrue(doIntersectOneWay, 'SE rect intersects with SE corner of NW rect');
assert.isTrue(doIntersectOtherWay, 'NW rect intersects with NW corner of SE rect');
});
});
suite('does not intersect', function () {
test('Same-size rects nearly side-adjacent', function() {
// ┌───┐ ┌───┐
// │ 2 │ │ 2 │
// └───┘ └───┘
const westRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const eastRect = Blockly.utils.Rect.createFromPoint(this.createCoord(3.5, 1), 2, 2);
const doIntersectOneWay = westRect.intersects(eastRect);
const doIntersectOtherWay = eastRect.intersects(westRect);
assert.isFalse(doIntersectOneWay, 'Western rect does not intersect with eastern rect');
assert.isFalse(doIntersectOtherWay, 'Eastern rect does not intersect with western rect');
});
test('Same-size rects nearly side-adjacent', function() {
// ┌───┐
// │ 2 │
// └───┘
// ┌───┐
// │ 2 │
// └───┘
const northRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const southRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 3.5), 2, 2);
const doIntersectOneWay = northRect.intersects(southRect);
const doIntersectOtherWay = southRect.intersects(northRect);
assert.isFalse(doIntersectOneWay, 'Northern rect does not intersect with southern rect');
assert.isFalse(doIntersectOtherWay, 'Southern rect does not intersect with northern rect');
});
test('Small rect left of big rect', function() {
// ┌───┐
// ┌─┐│ 2 │
// └─┘│ │
// └───┘
const westRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 1, 1);
const eastRect = Blockly.utils.Rect.createFromPoint(this.createCoord(2.5, 1), 2, 2);
const doIntersectOneWay = westRect.intersects(eastRect);
const doIntersectOtherWay = eastRect.intersects(westRect);
assert.isFalse(doIntersectOneWay, 'Western rect does not intersect with eastern rect');
assert.isFalse(doIntersectOtherWay, 'Eastern rect does not intersect with western rect');
});
test('Small rect right of big rect', function() {
// ┌───┐
// │ 2 │┌─┐
// │ │└─┘
// └───┘
const westRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const eastRect = Blockly.utils.Rect.createFromPoint(this.createCoord(3.5, 1), 1, 1);
const doIntersectOneWay = westRect.intersects(eastRect);
const doIntersectOtherWay = eastRect.intersects(westRect);
assert.isFalse(doIntersectOneWay, 'Western rect does not intersect with eastern rect');
assert.isFalse(doIntersectOtherWay, 'Eastern rect does not intersect with western rect');
});
test('Small rect above big rect', function() {
// ┌─┐
// └─┘
// ┌───┐
// │ 2 │
// └───┘
const northRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 1, 1);
const southRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2.5), 2, 2);
const doIntersectOneWay = northRect.intersects(southRect);
const doIntersectOtherWay = southRect.intersects(northRect);
assert.isFalse(doIntersectOneWay, 'Northern rect does not intersect with southern rect');
assert.isFalse(doIntersectOtherWay, 'Southern rect does not intersect with northern rect');
});
test('Small rect below big rect', function() {
// ┌───┐
// │ 2 │
// └───┘
// ┌─┐
// └─┘
const northRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const southRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 3.5), 1, 1);
const doIntersectOneWay = northRect.intersects(southRect);
const doIntersectOtherWay = southRect.intersects(northRect);
assert.isFalse(doIntersectOneWay, 'Northern rect does not intersect with southern rect');
assert.isFalse(doIntersectOtherWay, 'Southern rect does not intersect with northern rect');
});
test('Same-size rects diagonal (NE and SW) to each other', function() {
// ┌───┐
// │ 2 │
// └───┘
// ┌───┐
// │ 2 │
// └───┘
const neRect = Blockly.utils.Rect.createFromPoint(this.createCoord(3.5, 1), 2, 2);
const swRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 3.5), 2, 2);
const doIntersectOneWay = neRect.intersects(swRect);
const doIntersectOtherWay = swRect.intersects(neRect);
assert.isFalse(doIntersectOneWay, 'NE rect does not intersect with SW rect');
assert.isFalse(doIntersectOtherWay, 'SW rect does not intersect with NE rect');
});
test('Same-size rects diagonal (NW and SE) to each other', function() {
// ┌───┐
// │ 2 │
// └───┘
// ┌───┐
// │ 2 │
// └───┘
const nwRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const seRect = Blockly.utils.Rect.createFromPoint(this.createCoord(3.5, 3.5), 2, 2);
const doIntersectOneWay = nwRect.intersects(seRect);
const doIntersectOtherWay = seRect.intersects(nwRect);
assert.isFalse(doIntersectOneWay, 'NW rect does not intersect with SE rect');
assert.isFalse(doIntersectOtherWay, 'SE rect does not intersect with NW rect');
});
test('Small rect NE of big rect', function() {
// ┌─┐
// └─┘
// ┌───┐
// │ 2 │
// └───┘
const neRect = Blockly.utils.Rect.createFromPoint(this.createCoord(3.5, 1), 1, 1);
const swRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 2.5), 2, 2);
const doIntersectOneWay = neRect.intersects(swRect);
const doIntersectOtherWay = swRect.intersects(neRect);
assert.isFalse(doIntersectOneWay, 'NE rect does not intersect with SW rect');
assert.isFalse(doIntersectOtherWay, 'SW rect does not intersect with NE rect');
});
test('Small rect NW of big rect', function() {
// ┌─┐
// └─┘
// ┌───┐
// │ 2 │
// └───┘
const nwRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 1, 1);
const seRect = Blockly.utils.Rect.createFromPoint(this.createCoord(2.5, 2.5), 2, 2);
const doIntersectOneWay = nwRect.intersects(seRect);
const doIntersectOtherWay = seRect.intersects(nwRect);
assert.isFalse(doIntersectOneWay, 'NW rect does not intersect with SE rect');
assert.isFalse(doIntersectOtherWay, 'SE rect does not intersect with NW rect');
});
test('Small rect SW of big rect', function() {
// ┌───┐
// │ 2 │
// └───┘
// ┌─┐
// └─┘
const neRect = Blockly.utils.Rect.createFromPoint(this.createCoord(2.5, 1), 2, 2);
const swRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 3.5), 1, 1);
const doIntersectOneWay = neRect.intersects(swRect);
const doIntersectOtherWay = swRect.intersects(neRect);
assert.isFalse(doIntersectOneWay, 'NE rect does not intersect with SW rect');
assert.isFalse(doIntersectOtherWay, 'SW rect does not intersect with NE rect');
});
test('Small rect SE of big rect', function() {
// ┌───┐
// │ 2 │
// └───┘
// ┌─┐
// └─┘
const nwRect = Blockly.utils.Rect.createFromPoint(this.createCoord(1, 1), 2, 2);
const seRect = Blockly.utils.Rect.createFromPoint(this.createCoord(3.5, 3.5), 1, 1);
const doIntersectOneWay = nwRect.intersects(seRect);
const doIntersectOtherWay = seRect.intersects(nwRect);
assert.isFalse(doIntersectOneWay, 'NW rect does not intersect with SE rect');
assert.isFalse(doIntersectOtherWay, 'SE rect does not intersect with NW rect');
});
});
});
});