| // Copyright (C) 2024 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| import {Vector2D, Rect2D, Bounds2D} from './geom'; |
| |
| describe('Vector2D', () => { |
| test('add', () => { |
| const vector1 = new Vector2D({x: 1, y: 2}); |
| const vector2 = new Vector2D({x: 3, y: 4}); |
| const result = vector1.add(vector2); |
| expect(result.x).toBe(4); |
| expect(result.y).toBe(6); |
| }); |
| |
| test('sub', () => { |
| const vector1 = new Vector2D({x: 5, y: 7}); |
| const vector2 = new Vector2D({x: 2, y: 3}); |
| const result = vector1.sub(vector2); |
| expect(result.x).toBe(3); |
| expect(result.y).toBe(4); |
| }); |
| |
| test('scale', () => { |
| const vector = new Vector2D({x: 2, y: 3}); |
| const result = vector.scale(2); |
| expect(result.x).toBe(4); |
| expect(result.y).toBe(6); |
| }); |
| }); |
| |
| describe('Rect2D', () => { |
| test('asPoint', () => { |
| const rect = new Rect2D({left: 1, top: 2, right: 3, bottom: 4}); |
| expect(rect).toMatchObject({x: 1, y: 2}); |
| }); |
| |
| test('asSize', () => { |
| const rect = new Rect2D({left: 1, top: 2, right: 3, bottom: 8}); |
| expect(rect).toMatchObject({width: 2, height: 6}); |
| }); |
| |
| test('intersect', () => { |
| const a = new Rect2D({left: 1, top: 1, right: 4, bottom: 4}); |
| const b = {left: 2, top: 2, right: 5, bottom: 5}; |
| const result = a.intersect(b); |
| expect(result).toMatchObject({left: 2, top: 2, right: 4, bottom: 4}); |
| // Note: Non-overlapping rects are UB and thus not tested |
| // TODO(stevegolton): Work out what to do here. |
| }); |
| |
| test('expand', () => { |
| const rect = new Rect2D({left: 1, top: 1, right: 3, bottom: 3}); |
| const result = rect.expand(1); |
| expect(result).toMatchObject({left: 0, top: 0, right: 4, bottom: 4}); |
| }); |
| |
| test('expand 2d', () => { |
| const rect = new Rect2D({left: 1, top: 1, right: 3, bottom: 3}); |
| const result = rect.expand({width: 1, height: 2}); |
| expect(result).toMatchObject({left: 0, top: -1, right: 4, bottom: 5}); |
| }); |
| |
| test('reframe', () => { |
| const rect = new Rect2D({left: 2, top: 2, right: 5, bottom: 5}); |
| const result = rect.reframe({x: 1, y: 1}); |
| expect(result).toMatchObject({left: 1, top: 1, right: 4, bottom: 4}); |
| }); |
| |
| test('size', () => { |
| const rect = new Rect2D({left: 1, top: 1, right: 4, bottom: 3}); |
| expect(rect).toMatchObject({width: 3, height: 2}); |
| }); |
| |
| it('translate', () => { |
| const rect = new Rect2D({left: 2, top: 2, right: 5, bottom: 5}); |
| const result = rect.translate({x: 3, y: 4}); |
| expect(result).toMatchObject({left: 5, top: 6, right: 8, bottom: 9}); |
| }); |
| |
| it('contains', () => { |
| const outerRect = new Rect2D({left: 0, top: 0, right: 10, bottom: 10}); |
| const innerRect: Bounds2D = {left: 2, top: 2, right: 8, bottom: 8}; |
| expect(outerRect.contains(innerRect)).toBe(true); |
| |
| const nonContainedRect: Bounds2D = {left: 2, top: 2, right: 12, bottom: 8}; |
| expect(outerRect.contains(nonContainedRect)).toBe(false); |
| }); |
| |
| test('fromPointAndSize', () => { |
| const rect = Rect2D.fromPointAndSize({ |
| x: 10, |
| y: 20, |
| width: 100, |
| height: 50, |
| }); |
| |
| expect(rect.left).toBe(10); |
| expect(rect.top).toBe(20); |
| expect(rect.right).toBe(110); |
| expect(rect.bottom).toBe(70); |
| expect(rect.width).toBe(100); |
| expect(rect.height).toBe(50); |
| }); |
| |
| test('fromPoints', () => { |
| const rect = Rect2D.fromPoints({x: 0, y: 0}, {x: 100, y: 100}); |
| |
| expect(rect.left).toBe(0); |
| expect(rect.top).toBe(0); |
| expect(rect.right).toBe(100); |
| expect(rect.bottom).toBe(100); |
| }); |
| |
| test('fromPoints reversed', () => { |
| const rect = Rect2D.fromPoints({x: 100, y: 100}, {x: 0, y: 0}); |
| |
| expect(rect.left).toBe(0); |
| expect(rect.top).toBe(0); |
| expect(rect.right).toBe(100); |
| expect(rect.bottom).toBe(100); |
| }); |
| |
| describe('containsPoint', () => { |
| let rect: Rect2D; |
| |
| beforeEach(() => { |
| rect = new Rect2D({left: 10, top: 20, right: 110, bottom: 70}); |
| }); |
| |
| test('inside the rectangle', () => { |
| expect(rect.containsPoint({x: 50, y: 50})).toBe(true); |
| }); |
| |
| test('outside the rectangle', () => { |
| expect(rect.containsPoint({x: 5, y: 50})).toBe(false); // Left of rect |
| expect(rect.containsPoint({x: 50, y: 75})).toBe(false); // Below rect |
| expect(rect.containsPoint({x: 150, y: 50})).toBe(false); // Right of rect |
| expect(rect.containsPoint({x: 50, y: 15})).toBe(false); // Above rect |
| }); |
| |
| test('boundary case', () => { |
| expect(rect.containsPoint({x: 10, y: 20})).toBe(true); // Top-left corner |
| expect(rect.containsPoint({x: 110, y: 20})).toBe(false); // On right edge |
| expect(rect.containsPoint({x: 10, y: 70})).toBe(false); // On bottom edge |
| }); |
| }); |
| }); |