已知元素坐标和框选区域(ptl, ptr, pbr, pbl),判断选择框是否触碰到元素。
**解:**
由元素坐标可得4个顶点(point_tl, point_tr, point_bl, point_br)
1. 两多边形是否相交 -> 线段相交
1. 判断元素某边与框选区域某边是否相交(即证: 线与线相交[向量叉乘])如果两个线段相交,则一条线段的两个端点位于另一条线段的两边.
2.
2. 元素在选择框内
3. 选择框在元素内 -> 选择框某顶点在元素内
```
// 两多边形是否碰撞||包含
utils.checkPolygonIsTouch = (polygon1, polygon2) => {
// 判断线与线是否相交....orz...
const isThrowItem = () => {
return utils.checkCross(polygon1[0], polygon1[1], polygon2[0], polygon2[1]) ||
utils.checkCross(polygon1[0], polygon1[1], polygon2[1], polygon2[2]) ||
utils.checkCross(polygon1[0], polygon1[1], polygon2[2], polygon2[3]) ||
utils.checkCross(polygon1[0], polygon1[1], polygon2[3], polygon2[0]) ||
utils.checkCross(polygon1[1], polygon1[2], polygon2[0], polygon2[1]) ||
utils.checkCross(polygon1[1], polygon1[2], polygon2[1], polygon2[2]) ||
utils.checkCross(polygon1[1], polygon1[2], polygon2[2], polygon2[3]) ||
utils.checkCross(polygon1[1], polygon1[2], polygon2[3], polygon2[0]) ||
utils.checkCross(polygon1[2], polygon1[3], polygon2[0], polygon2[1]) ||
utils.checkCross(polygon1[2], polygon1[3], polygon2[1], polygon2[2]) ||
utils.checkCross(polygon1[2], polygon1[3], polygon2[2], polygon2[3]) ||
utils.checkCross(polygon1[2], polygon1[3], polygon2[3], polygon2[0]) ||
utils.checkCross(polygon1[3], polygon1[0], polygon2[0], polygon2[1]) ||
utils.checkCross(polygon1[3], polygon1[0], polygon2[1], polygon2[2]) ||
utils.checkCross(polygon1[3], polygon1[0], polygon2[2], polygon2[3]) ||
utils.checkCross(polygon1[3], polygon1[0], polygon2[3], polygon2[0])
}
return isThrowItem() ||
// 判断是否在多边形内
utils.checkPIsInPolygon({ polygon: polygon1, point: polygon2[0] }) ||
utils.checkPIsInPolygon({ polygon: polygon1, point: polygon2[1] }) ||
utils.checkPIsInPolygon({ polygon: polygon1, point: polygon2[2] }) ||
utils.checkPIsInPolygon({ polygon: polygon1, point: polygon2[3] }) ||
// 选择框4顶点 是否在元素内
utils.checkPIsInPolygon({ polygon: polygon2, point: polygon1[0] }) ||
utils.checkPIsInPolygon({ polygon: polygon2, point: polygon1[1] }) ||
utils.checkPIsInPolygon({ polygon: polygon2, point: polygon1[2] }) ||
utils.checkPIsInPolygon({ polygon: polygon2, point: polygon1[3] })
}
// 判断点是否在多边形内...orz...
utils.checkPIsInPolygon = function ({ point, polygon }) {
let p3, p4
const p1 = point
const p2 = { x: -10000, y: point.y }
let count = 0
// 对每条边都和射线作对比
for (let i = 0; i < polygon.length - 1; i++) {
p3 = polygon[i]
p4 = polygon[i + 1]
if (utils.checkCross(p1, p2, p3, p4) == true) {
count++
}
}
p3 = polygon[polygon.length - 1]
p4 = polygon[0]
if (utils.checkCross(p1, p2, p3, p4) == true) {
count++
}
return count % 2 != 0;
}
// 判断两直线是否相交 判断两条线相交 => 同理判断两点在直线两边 orz...
utils.checkCross = (p1, p2, p3, p4) => {
// 计算向量叉乘
const crossMul = (v1, v2) => {
return v1.x * v2.y - v1.y * v2.x;
};
let v1 = { x: p1.x - p3.x, y: p1.y - p3.y };
let v2 = { x: p2.x - p3.x, y: p2.y - p3.y };
let v3 = { x: p4.x - p3.x, y: p4.y - p3.y };
const v = crossMul(v1, v3) * crossMul(v2, v3);
v1 = { x: p3.x - p1.x, y: p3.y - p1.y };
v2 = { x: p4.x - p1.x, y: p4.y - p1.y };
v3 = { x: p2.x - p1.x, y: p2.y - p1.y };
return !!((v <= 0 && crossMul(v1, v3) * crossMul(v2, v3) <= 0));
}
```
附: 旋转点计算
```
/**
* 计算旋转后的点坐标
* @param {Object: {x: number, y: number}} point 坐标点
* @param {Object: {x: number, y: number}} point_origin 旋转中心点
* @param {Array} matrixArr transform矩阵值
* @return {x, y} 保留2位小数
*/
utils.GetRotatePoint = ({ point, matrixArr, point_origin }) => {
const [cosθ, sinθ] = matrixArr;
const x = (point.x - point_origin.x) * cosθ - (point.y - point_origin.y) * sinθ + point_origin.x;
const y = (point.x - point_origin.x) * sinθ + (point.y - point_origin.y) * cosθ + point_origin.y;
return {
x: Math.round(x * 100) / 100,
y: Math.round(y * 100) / 100
}
}
```
「技术实现篇」元素触碰框选设计方案