add sat
This commit is contained in:
@@ -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';
|
||||
|
@@ -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);
|
||||
|
123
packages/dooringx-lib/src/core/selectRange/sat.ts
Normal file
123
packages/dooringx-lib/src/core/selectRange/sat.ts
Normal 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);
|
||||
}
|
Reference in New Issue
Block a user