UNPKG

4.23 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.isIntersect = exports.isIntersectRect = void 0;
4var tslib_1 = require("tslib");
5var matrix_util_1 = require("@antv/matrix-util");
6var dot = matrix_util_1.vec2.dot;
7/**
8 * @private
9 * 1. 获取投影轴
10 */
11function getAxes(points /** 多边形的关键点 */) {
12 // 目前先处理 平行矩形 的场景, 其他多边形不处理
13 if (points.length > 4) {
14 return [];
15 }
16 // 获取向量
17 var vector = function (start, end) {
18 return [end.x - start.x, end.y - start.y];
19 };
20 // 由于 矩形的平行原理,所以只有 2 条投影轴: A -> B, B -> C
21 var AB = vector(points[0], points[1]);
22 var BC = vector(points[1], points[2]);
23 return [AB, BC];
24}
25/**
26 * @private
27 * 绕指定点顺时针旋转后的点坐标
28 * 默认绕原点旋转
29 */
30function rotateAtPoint(point, deg, origin) {
31 if (deg === void 0) { deg = 0; }
32 if (origin === void 0) { origin = { x: 0, y: 0 }; }
33 var x = point.x, y = point.y;
34 return {
35 x: (x - origin.x) * Math.cos(-deg) + (y - origin.y) * Math.sin(-deg) + origin.x,
36 y: (origin.x - x) * Math.sin(-deg) + (y - origin.y) * Math.cos(-deg) + origin.y,
37 };
38}
39/**
40 * @private
41 * 转化为顶点坐标数组
42 *
43 * @param {Object} box
44 */
45function getRectPoints(box) {
46 var points = [
47 { x: box.x, y: box.y },
48 { x: box.x + box.width, y: box.y },
49 { x: box.x + box.width, y: box.y + box.height },
50 { x: box.x, y: box.y + box.height },
51 ];
52 var rotation = box.rotation;
53 if (rotation) {
54 return [
55 rotateAtPoint(points[0], rotation, points[0]),
56 rotateAtPoint(points[1], rotation, points[0]),
57 rotateAtPoint(points[2], rotation, points[0]),
58 rotateAtPoint(points[3], rotation, points[0]),
59 ];
60 }
61 return points;
62}
63/**
64 * @private
65 * 2. 获取多边形在投影轴上的投影
66 *
67 * 向量的点积的其中一个几何含义是:一个向量在平行于另一个向量方向上的投影的数值乘积。
68 * 由于投影轴是单位向量(长度为1),投影的长度为 x1 * x2 + y1 * y2
69 */
70function getProjection(points /** 多边形的关键点 */, axis) {
71 // 目前先处理矩形的场景
72 if (points.length > 4) {
73 return { min: 0, max: 0 };
74 }
75 var scalars = [];
76 points.forEach(function (point) {
77 scalars.push(dot([point.x, point.y], axis));
78 });
79 return { min: Math.min.apply(Math, scalars), max: Math.max.apply(Math, scalars) };
80}
81function isProjectionOverlap(projection1, projection2) {
82 return projection1.max > projection2.min && projection1.min < projection2.max;
83}
84/**
85 * 快速判断两个无旋转矩形是否遮挡
86 */
87function isIntersectRect(box1, box2, margin) {
88 if (margin === void 0) { margin = 0; }
89 return !(box2.x > box1.x + box1.width + margin ||
90 box2.x + box2.width < box1.x - margin ||
91 box2.y > box1.y + box1.height + margin ||
92 box2.y + box2.height < box1.y - margin);
93}
94exports.isIntersectRect = isIntersectRect;
95/**
96 * detect whether two shape is intersected, useful when shape is been rotated
97 * 判断两个矩形是否重叠(相交和包含, 是否旋转)
98 *
99 * - 原理: 分离轴定律
100 */
101function isIntersect(box1, box2) {
102 // 如果两个矩形没有旋转,使用快速判断
103 if (!box1.rotation && !box2.rotation) {
104 return isIntersectRect(box1, box2);
105 }
106 // 分别获取 4 个关键点
107 var rect1Points = getRectPoints(box1);
108 var rect2Points = getRectPoints(box2);
109 // 获取所有投影轴
110 var axes = tslib_1.__spreadArrays(getAxes(rect1Points), getAxes(rect2Points));
111 for (var i = 0; i < axes.length; i++) {
112 var axis = axes[i];
113 var projection1 = getProjection(rect1Points, axis);
114 var projection2 = getProjection(rect2Points, axis);
115 // 判断投影轴上的投影是否存在重叠,若检测到存在间隙则立刻退出判断,消除不必要的运算。
116 if (!isProjectionOverlap(projection1, projection2))
117 return false;
118 }
119 return true;
120}
121exports.isIntersect = isIntersect;
122//# sourceMappingURL=collision-detect.js.map
\No newline at end of file