This commit is contained in:
yehuozhili
2022-05-01 19:21:52 +08:00
parent 8ccf5289e5
commit a018116728
3 changed files with 140 additions and 11 deletions

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili
* @Date: 2021-03-14 05:42:13
* @LastEditors: yehuozhili
* @LastEditTime: 2022-04-29 23:36:45
* @LastEditTime: 2022-04-30 23:07:13
* @FilePath: \dooringx\packages\dooringx-lib\src\components\rightConfig.tsx
*/
import { CreateOptionsRes } from '../core/components/formTypes';

View File

@@ -2,7 +2,7 @@ import { IStoreData } from '../store/storetype';
import { deepCopy } from '../utils';
import style from '../../index.less';
import UserConfig from '../../config';
import { getComponentRotatedStyle } from '../markline/calcRender';
import { Sat } from './sat';
export interface SelectDataProps {
selectDiv: HTMLDivElement | null;
posx: number;
@@ -60,8 +60,6 @@ function selectFocus(left: number, top: number, width: number, height: number, c
const focusState = config.getFocusState();
const blocks = clonedata.block;
let change = false;
const maxleft = left + width;
const maxtop = top + height;
blocks.forEach((v) => {
const l = v.left;
const t = v.top;
@@ -74,13 +72,21 @@ function selectFocus(left: number, top: number, width: number, height: number, c
typeof h === 'number' &&
v.canDrag === true
) {
const style = getComponentRotatedStyle(v.rotate.value, w, h, l, t);
if (
style.left >= left &&
style.right <= maxleft &&
style.top >= top &&
style.bottom <= maxtop
) {
const curItem = {
left: l,
top: t,
width: w,
height: h,
rotate: v.rotate.value,
};
const res = Sat(curItem, {
left,
width,
height,
top,
rotate: 0,
});
if (res) {
change = true;
v.focus = true;
focusState.blocks.push(v);

View File

@@ -0,0 +1,123 @@
/*
* @Author: yehuozhili
* @Date: 2022-04-30 23:25:05
* @LastEditors: yehuozhili
* @LastEditTime: 2022-05-01 19:16:08
* @FilePath: \dooringx\packages\dooringx-lib\src\core\selectRange\sat.ts
*/
import { angleToRadian } from '../utils';
interface BlockItem {
width: number;
left: number;
top: number;
height: number;
rotate: number;
}
function getCenter(item: BlockItem) {
return { x: item.left + item.width / 2, y: item.top + item.height / 2 };
}
function revert({ x, y }: { x: number; y: number }) {
return { x: y, y: -x };
}
function substract(a: { x: number; y: number }, b: { x: number; y: number }) {
return { x: a.x - b.x, y: a.y - b.y };
}
function getSides(list: { x: number; y: number }[]) {
let len = list.length;
let res = [];
for (let j = 1, pre = list[0]; j < len; j++) {
let p = list[j];
res.push(substract(p, pre));
pre = p;
}
res.push(substract(list[0], list[len - 1]));
return res;
}
function len(axis: { x: number; y: number }) {
return Math.sqrt(axis.x * axis.x + axis.y * axis.y);
}
function dot(a: { x: number; y: number }, b: { x: number; y: number }) {
return a.x * b.x + a.y * b.y;
}
function getProjection(axis: { x: number; y: number }, list: { x: number; y: number }[]) {
let min = null;
let max = null;
for (let i = 0, l = list.length; i < l; i++) {
let p = list[i];
let pro = dot(p, axis) / len(axis);
if (min === null || pro < min) {
min = pro;
}
if (max === null || pro > max) {
max = pro;
}
}
return { min: min, max: max };
}
function getOriginPoint(item: BlockItem) {
const center = getCenter(item);
let a = center.x;
let b = center.y;
const transfer = [
{ x: item.left, y: item.top },
{ x: item.left + item.width, y: item.top },
{ x: item.left + item.width, y: item.top + item.height },
{ x: item.left, y: item.top + item.height },
];
const relativePoint: { x: number; y: number }[] = [];
const rootPoint = transfer.map((v) => {
const x0 = v.x;
const y0 = v.y;
const rx =
a +
(x0 - a) * Math.cos(angleToRadian(item.rotate)) -
(y0 - b) * Math.sin(angleToRadian(item.rotate));
const ry =
b +
(x0 - a) * Math.sin(angleToRadian(item.rotate)) +
(y0 - b) * Math.cos(angleToRadian(item.rotate));
relativePoint.push({ x: a - rx, y: b - ry });
return { x: rx, y: ry };
});
return { rootPoint, relativePoint };
}
function polygonsCollisionTest(A: BlockItem, B: BlockItem) {
const resa = getOriginPoint(A);
const resb = getOriginPoint(B);
const sidesa = getSides(resa.relativePoint);
const sidesb = getSides(resb.relativePoint);
const sides = sidesa.concat(sidesb);
for (let j = 0, l = sides.length; j < l; j++) {
let axis = revert(sides[j]);
let proA = getProjection(axis, resa.rootPoint),
proB = getProjection(axis, resb.rootPoint);
if (isOverlay(proA, proB)) {
return false;
}
}
return true;
}
function isOverlay(proA: any, proB: any) {
let min, max;
if (proA.min < proB.min) {
min = proA.min;
} else {
min = proB.min;
}
if (proA.max > proB.max) {
max = proA.max;
} else {
max = proB.max;
}
return proA.max - proA.min + (proB.max - proB.min) < max - min;
}
export function Sat(v: BlockItem, select: BlockItem) {
return polygonsCollisionTest(v, select);
}