diff --git a/src/lib/calculateCollision/calculateCollision.js b/src/lib/calculateCollision/calculateCollision.js new file mode 100644 index 0000000..1ed41b9 --- /dev/null +++ b/src/lib/calculateCollision/calculateCollision.js @@ -0,0 +1,51 @@ +/** + * Вычисляет пересеклись ли два объекта по ААBB формуле в системе координат где ось X идет справа налево, ось Y идет сверху вних + * @param {Object} firstObject - первый объект + * @param {number} firstObject.left - Min X координата первого объекта + * @param {number} firstObject.right - Max X координата первого объекта + * @param {number} firstObject.top - Min Y координата первого объекта (ось смотрит вниз) + * @param {number} firstObject.bottom - Max Y координата первого объекта + * @param {Object} secondObject - второй объект + * @param {number} secondObject.left - Min X координата второго объекта + * @param {number} secondObject.right - Max X координата второго объекта + * @param {number} secondObject.top - Min Y координата второго объекта (ось смотрит вниз) + * @param {number} secondObject.bottom - Max Y координата второго объекта + * @returns {boolean} + */ +export function calculateCollision(firstObject, secondObject) { + try { + const coordinates = [ + firstObject.left, + firstObject.right, + firstObject.top, + firstObject.bottom, + secondObject.left, + secondObject.right, + secondObject.top, + secondObject.bottom, + ]; + + if (coordinates.some((element) => typeof element !== 'number')) { + throw new Error('Координаты должны являться числовыми значениями'); + } + + if ( + firstObject.left > firstObject.right || + firstObject.top > firstObject.bottom || + secondObject.left > secondObject.right || + secondObject.top > secondObject.bottom + ) { + throw new Error('Координаты должны быть корректными'); + } + + return ( + firstObject.left <= secondObject.right && + firstObject.right >= secondObject.left && + firstObject.top <= secondObject.bottom && + firstObject.bottom >= secondObject.top + ); + } catch (err) { + console.error(err); + return null; + } +} diff --git a/src/lib/calculateCollision/calculateCollision.test.js b/src/lib/calculateCollision/calculateCollision.test.js new file mode 100644 index 0000000..e6d5748 --- /dev/null +++ b/src/lib/calculateCollision/calculateCollision.test.js @@ -0,0 +1,130 @@ +import { describe, expect, it } from 'vitest'; +import { calculateCollision } from './calculateCollision'; + +describe('calculateCollision', () => { + it('Корректно обрабатывает невозможные кейсы (левая координата больше правой)', () => { + const firstObject = { + left: 0, + right: 20, + top: 0, + bottom: 20, + }; + + const secondObject = { + left: 10, + right: 0, + top: 0, + bottom: 10, + }; + + expect(calculateCollision(firstObject, secondObject)).toBeNull(); + }); + + it('Корректно обрабатывает неверный формат данных', () => { + const firstObject = { + left: 'wrong', + right: 20, + top: 0, + bottom: 20, + }; + + const secondObject = { + left: 0, + right: 10, + top: 0, + bottom: 10, + }; + + expect(calculateCollision(firstObject, secondObject)).toBeNull(); + }); + + it('Корректно обрабатывает отсутствие пересечения по X', () => { + const firstObject = { + left: 0, + right: 20, + top: 0, + bottom: 20, + }; + + const secondObject = { + left: 25, + right: 30, + top: 0, + bottom: 10, + }; + + expect(calculateCollision(firstObject, secondObject)).toBe(false); + }); + + it('Корректно обрабатывает отсутствие пересечения по Y', () => { + const firstObject = { + left: 0, + right: 20, + top: 0, + bottom: 20, + }; + + const secondObject = { + left: 0, + right: 30, + top: 25, + bottom: 30, + }; + + expect(calculateCollision(firstObject, secondObject)).toBe(false); + }); + + it('Корректно обрабатывает отсутствие пересечения по X и Y', () => { + const firstObject = { + left: 0, + right: 20, + top: 0, + bottom: 20, + }; + + const secondObject = { + left: 25, + right: 30, + top: 25, + bottom: 30, + }; + + expect(calculateCollision(firstObject, secondObject)).toBe(false); + }); + + it('Корректно обрабатывает пересечение', () => { + const firstObject = { + left: 0, + right: 20, + top: 0, + bottom: 20, + }; + + const secondObject = { + left: 10, + right: 30, + top: 10, + bottom: 30, + }; + + expect(calculateCollision(firstObject, secondObject)).toBe(true); + }); + + it('Корректно обрабатывает вхождение', () => { + const firstObject = { + left: 0, + right: 20, + top: 0, + bottom: 20, + }; + + const secondObject = { + left: 10, + right: 15, + top: 10, + bottom: 15, + }; + + expect(calculateCollision(firstObject, secondObject)).toBe(true); + }); +});