"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isIntersect = exports.isIntersectRect = void 0;
var tslib_1 = require("tslib");
var util_1 = require("@antv/util");
var matrix_util_1 = require("@antv/matrix-util");
var dot = matrix_util_1.vec2.dot;
/**
 * @private
 * 1. 获取投影轴
 */
function getAxes(points /** 多边形的关键点 */) {
    // 目前先处理 平行矩形 的场景, 其他多边形不处理
    if (points.length > 4) {
        return [];
    }
    // 获取向量
    var vector = function (start, end) {
        return [end.x - start.x, end.y - start.y];
    };
    // 由于 矩形的平行原理，所以只有 2 条投影轴: A -> B, B -> C
    var AB = vector(points[0], points[1]);
    var BC = vector(points[1], points[2]);
    return [AB, BC];
}
/**
 * @private
 * 绕指定点顺时针旋转后的点坐标
 * 默认绕原点旋转
 */
function rotateAtPoint(point, deg, origin) {
    if (deg === void 0) { deg = 0; }
    if (origin === void 0) { origin = { x: 0, y: 0 }; }
    var x = point.x, y = point.y;
    return {
        x: (x - origin.x) * Math.cos(-deg) + (y - origin.y) * Math.sin(-deg) + origin.x,
        y: (origin.x - x) * Math.sin(-deg) + (y - origin.y) * Math.cos(-deg) + origin.y,
    };
}
/**
 * @private
 * 转化为顶点坐标数组
 *
 * @param {Object} box
 */
function getRectPoints(box) {
    var points = [
        { x: box.x, y: box.y },
        { x: box.x + box.width, y: box.y },
        { x: box.x + box.width, y: box.y + box.height },
        { x: box.x, y: box.y + box.height },
    ];
    var rotation = box.rotation;
    if (rotation) {
        return [
            rotateAtPoint(points[0], rotation, points[0]),
            rotateAtPoint(points[1], rotation, points[0]),
            rotateAtPoint(points[2], rotation, points[0]),
            rotateAtPoint(points[3], rotation, points[0]),
        ];
    }
    return points;
}
/**
 * @private
 * 2. 获取多边形在投影轴上的投影
 *
 * 向量的点积的其中一个几何含义是：一个向量在平行于另一个向量方向上的投影的数值乘积。
 * 由于投影轴是单位向量（长度为1），投影的长度为 x1 * x2 + y1 * y2
 */
function getProjection(points /** 多边形的关键点 */, axis) {
    // 目前先处理矩形的场景
    if (points.length > 4) {
        return { min: 0, max: 0 };
    }
    var scalars = [];
    points.forEach(function (point) {
        scalars.push(dot([point.x, point.y], axis));
    });
    return { min: Math.min.apply(Math, scalars), max: Math.max.apply(Math, scalars) };
}
function isProjectionOverlap(projection1, projection2) {
    return projection1.max > projection2.min && projection1.min < projection2.max;
}
function isValidNumber(d) {
    return (0, util_1.isNumber)(d) && !Number.isNaN(d) && d !== Infinity && d !== -Infinity;
}
function isValidBox(box) {
    return Object.values(box).every(isValidNumber);
}
/**
 * 快速判断两个无旋转矩形是否遮挡
 */
function isIntersectRect(box1, box2, margin) {
    if (margin === void 0) { margin = 0; }
    return !(box2.x > box1.x + box1.width + margin ||
        box2.x + box2.width < box1.x - margin ||
        box2.y > box1.y + box1.height + margin ||
        box2.y + box2.height < box1.y - margin);
}
exports.isIntersectRect = isIntersectRect;
/**
 * detect whether two shape is intersected, useful when shape is been rotated
 * 判断两个矩形是否重叠（相交和包含, 是否旋转）
 *
 * - 原理: 分离轴定律
 */
function isIntersect(box1, box2) {
    // 如果两个 box 中有一个是不合法的 box，也就是不会被渲染出来的，那么它们就不相交。
    if (!isValidBox(box1) || !isValidBox(box2))
        return false;
    // 如果两个矩形没有旋转，使用快速判断
    if (!box1.rotation && !box2.rotation) {
        return isIntersectRect(box1, box2);
    }
    // 分别获取 4 个关键点
    var rect1Points = getRectPoints(box1);
    var rect2Points = getRectPoints(box2);
    // 获取所有投影轴
    var axes = (0, tslib_1.__spreadArray)((0, tslib_1.__spreadArray)([], getAxes(rect1Points), true), getAxes(rect2Points), true);
    for (var i = 0; i < axes.length; i++) {
        var axis = axes[i];
        var projection1 = getProjection(rect1Points, axis);
        var projection2 = getProjection(rect2Points, axis);
        // 判断投影轴上的投影是否存在重叠，若检测到存在间隙则立刻退出判断，消除不必要的运算。
        if (!isProjectionOverlap(projection1, projection2))
            return false;
    }
    return true;
}
exports.isIntersect = isIntersect;
//# sourceMappingURL=collision-detect.js.map