|
@@ -1,8 +1,14 @@
|
|
|
import {
|
|
|
eqPoint,
|
|
|
getDiffPolygons,
|
|
|
+ getLEJLineAngle,
|
|
|
+ getLineEdgeJoinInfo,
|
|
|
+ getLineEdges,
|
|
|
getVectorLine,
|
|
|
isPolygonPointInner,
|
|
|
+ LEJInfo,
|
|
|
+ LEJLine,
|
|
|
+ line2IncludedAngle,
|
|
|
lineCenter,
|
|
|
lineInner,
|
|
|
lineIntersection,
|
|
@@ -13,8 +19,8 @@ import {
|
|
|
vector2IncludedAngle,
|
|
|
verticalVector,
|
|
|
} from "@/utils/math";
|
|
|
-import { LineData } from ".";
|
|
|
-import { getJoinLine } from "./attach-server";
|
|
|
+import { LineData, LineDataLine } from ".";
|
|
|
+import { getJoinLine, getLinePoints } from "./attach-server";
|
|
|
import { MathUtils } from "three";
|
|
|
import { diffArrayChange, rangMod } from "@/utils/shared";
|
|
|
import { globalWatch, installGlobalVar } from "@/core/hook/use-global-vars";
|
|
@@ -24,137 +30,122 @@ import { Transform } from "konva/lib/Util";
|
|
|
import { sortFn } from "@/core/store/store";
|
|
|
import { getLineIconEndpoints, getSnapLine } from "../line-icon";
|
|
|
import { useDrawIngData } from "@/core/hook/use-draw";
|
|
|
-import { useTestPoints } from "@/core/hook/use-debugger";
|
|
|
-
|
|
|
-const minAngle = MathUtils.degToRad(0.1);
|
|
|
-const palAngle = MathUtils.degToRad(20);
|
|
|
-
|
|
|
-const getLineRect = (points: Pos[], strokeWidth: number) => {
|
|
|
- const v = lineVector(points);
|
|
|
- const vv = verticalVector(v);
|
|
|
- const offset = vv.clone().multiplyScalar(strokeWidth / 2);
|
|
|
- const top = points.map((p) => offset.clone().add(p));
|
|
|
- offset.multiplyScalar(-1);
|
|
|
- const bottom = points.map((p) => offset.clone().add(p));
|
|
|
- return [...top, bottom[1], bottom[0]];
|
|
|
-};
|
|
|
|
|
|
export const useGetExtendPolygon = installGlobalVar(() => {
|
|
|
- return (data: LineData, line: LineData["lines"][0], useJoin = true) => {
|
|
|
- const getJoinInfo = (
|
|
|
- joinLine: LineData["lines"][0],
|
|
|
- joinPoints: Pos[],
|
|
|
- getNdx: number
|
|
|
- ) => {
|
|
|
- const jNdx = joinPoints.indexOf(linePoints[getNdx]);
|
|
|
- if ((getNdx === 0 && jNdx === 0) || (getNdx === 1 && jNdx === 1)) {
|
|
|
- joinPoints.reverse();
|
|
|
- }
|
|
|
- const direInv = getNdx === 0 && jNdx === 0;
|
|
|
- const joinv = lineVector(joinPoints).multiplyScalar(-1);
|
|
|
- const angle = vector2IncludedAngle(
|
|
|
- direInv ? joinv : linev,
|
|
|
- direInv ? linev : joinv
|
|
|
- );
|
|
|
- const checkAngle = rangMod(Math.abs(angle), Math.PI);
|
|
|
- if (checkAngle < minAngle || checkAngle > Math.PI - minAngle) return;
|
|
|
- const join = lineIntersection(linePoints, joinPoints);
|
|
|
- if (!join) return;
|
|
|
-
|
|
|
- const center = lineCenter([...linePoints, ...joinPoints]);
|
|
|
- const joinRect = getLineRect(joinPoints, joinLine.strokeWidth);
|
|
|
- const cheJoinInnerNdxs = getNdx === 0 ? [0, 3] : [1, 2];
|
|
|
- const cheLineInnerNdxs = getNdx === 0 ? [1, 2] : [0, 3];
|
|
|
- if (
|
|
|
- cheJoinInnerNdxs.some((ndx) =>
|
|
|
- isPolygonPointInner(lineRect, joinRect[ndx])
|
|
|
- ) ||
|
|
|
- cheLineInnerNdxs.some((ndx) =>
|
|
|
- isPolygonPointInner(joinRect, lineRect[ndx])
|
|
|
- )
|
|
|
- ) {
|
|
|
- return;
|
|
|
- }
|
|
|
+ const minAngle = MathUtils.degToRad(0.1);
|
|
|
+ const palAngle = MathUtils.degToRad(20);
|
|
|
+ const linePolygons: Record<string, Pos[]> = reactive({});
|
|
|
|
|
|
- let outerLine1, innerLine1, outerLine2, innerLine2;
|
|
|
- const rectJust =
|
|
|
- lineLen(center, lineRect[0]) > lineLen(center, lineRect[3]);
|
|
|
- if (rectJust) {
|
|
|
- outerLine1 = [lineRect[0], lineRect[1]];
|
|
|
- innerLine1 = [lineRect[3], lineRect[2]];
|
|
|
- } else {
|
|
|
- outerLine1 = [lineRect[3], lineRect[2]];
|
|
|
- innerLine1 = [lineRect[0], lineRect[1]];
|
|
|
- }
|
|
|
+ const lineJoinInfos = reactive({}) as Record<
|
|
|
+ string,
|
|
|
+ Record<string, LEJInfo | undefined>
|
|
|
+ >;
|
|
|
|
|
|
- if (lineLen(center, joinRect[0]) > lineLen(center, joinRect[3])) {
|
|
|
- outerLine2 = [joinRect[0], joinRect[1]];
|
|
|
- innerLine2 = [joinRect[3], joinRect[2]];
|
|
|
- } else {
|
|
|
- outerLine2 = [joinRect[3], joinRect[2]];
|
|
|
- innerLine2 = [joinRect[0], joinRect[1]];
|
|
|
- }
|
|
|
+ const getInfoKey = (line: LEJLine) =>
|
|
|
+ line.points.reduce((t, p) => p.x + p.y + t, "") + line.width;
|
|
|
+
|
|
|
+ const updateLine2JoinInfo = (
|
|
|
+ data: LineData,
|
|
|
+ line1: LineDataLine,
|
|
|
+ line2: LineDataLine
|
|
|
+ ) => {
|
|
|
|
|
|
- const outer = lineIntersection(outerLine1, outerLine2);
|
|
|
- if (!outer) return;
|
|
|
+ };
|
|
|
|
|
|
- let inside: Pos = lineIntersection(innerLine1, innerLine2)!;
|
|
|
- if (!inside) return;
|
|
|
+ const getLineInfo = (data: LineData, line: LineDataLine) => {
|
|
|
+ const origin = {
|
|
|
+ points: getLinePoints(data, line),
|
|
|
+ width: line.strokeWidth,
|
|
|
+ };
|
|
|
+ const key = getInfoKey(origin);
|
|
|
+ if (!(key in lineJoinInfos)) {
|
|
|
+ lineJoinInfos[key] = {};
|
|
|
+ }
|
|
|
|
|
|
- const insideLineInner1 = lineInner(innerLine1, inside);
|
|
|
- const insideLineInner2 = lineInner(innerLine2, inside);
|
|
|
+ const cache = lineJoinInfos[key];
|
|
|
+ const exist0 = "0" in cache;
|
|
|
+ const exist1 = "1" in cache;
|
|
|
+ if (exist0 && exist1) {
|
|
|
+ return [cache[0], cache[1]];
|
|
|
+ }
|
|
|
|
|
|
- if (!insideLineInner1 && !insideLineInner2) return;
|
|
|
+ const calcNdxs: number[] = [];
|
|
|
+ exist0 || calcNdxs.push(0);
|
|
|
+ exist1 || calcNdxs.push(1);
|
|
|
+
|
|
|
+ const update2Line = (join: LineDataLine, originNdx: number) => {
|
|
|
+ const target = {
|
|
|
+ points: getLinePoints(data, join),
|
|
|
+ width: join.strokeWidth,
|
|
|
+ };
|
|
|
+ const joinInfo = getLineEdgeJoinInfo(origin, target, minAngle, palAngle);
|
|
|
+ cache[originNdx] = joinInfo?.origin;
|
|
|
+
|
|
|
+ const targetKey = getInfoKey(target);
|
|
|
+ if (!(targetKey in lineJoinInfos)) {
|
|
|
+ lineJoinInfos[targetKey] = {};
|
|
|
+ }
|
|
|
+ const p = origin.points[originNdx];
|
|
|
+ lineJoinInfos[targetKey][target.points.indexOf(p)] = joinInfo?.target;
|
|
|
+ };
|
|
|
|
|
|
- let insides = [inside];
|
|
|
- // 如果角度过于尖锐则使用平行线
|
|
|
- let outers = [outer];
|
|
|
- if (checkAngle < palAngle) {
|
|
|
- const jov = getVectorLine(lineVerticalVector([join, outer]), join);
|
|
|
- const outer1 = lineIntersection(jov, outerLine1)!;
|
|
|
- outers = [outer1, join];
|
|
|
+ const updateManyLine = (joins: LineDataLine[], originNdx: number) => {
|
|
|
+ let maxAngle = minAngle;
|
|
|
+ let select: ReturnType<typeof getLEJLineAngle> & {
|
|
|
+ origin: LineDataLine;
|
|
|
+ target: LineDataLine;
|
|
|
+ };
|
|
|
+ for (let i = 0; i < joins.length; i++) {
|
|
|
+ const line1 = getLinePoints(data, joins[i]);
|
|
|
+ for (let j = i + 1; j < joins.length; j++) {
|
|
|
+ const line2 = getLinePoints(data, joins[j]);
|
|
|
+ if (line2IncludedAngle(line1, line2)) {
|
|
|
+ const ejlAngle = getLEJLineAngle(line1, line2);
|
|
|
+ if (ejlAngle.angle > maxAngle) {
|
|
|
+ maxAngle = ejlAngle.angle;
|
|
|
+ select = {
|
|
|
+ ...ejlAngle,
|
|
|
+ origin: joins[i],
|
|
|
+ target: joins[j],
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+ };
|
|
|
|
|
|
- const repsResult: { rep: number; points: Pos[] }[] = [];
|
|
|
- if (getNdx === 0) {
|
|
|
- repsResult.push({
|
|
|
- rep: 0,
|
|
|
- points: rectJust ? outers.reverse() : insides,
|
|
|
- });
|
|
|
- repsResult.push({ rep: 3, points: rectJust ? insides : outers });
|
|
|
+ for (const ndx of calcNdxs) {
|
|
|
+ const p = origin.points[ndx];
|
|
|
+ const joins = getJoinLine(data, line, p.id);
|
|
|
+
|
|
|
+ if (joins.length === 0) {
|
|
|
+ cache[ndx] = undefined;
|
|
|
+ } else if (joins.length !== 1) {
|
|
|
+ updateManyLine(joins, ndx);
|
|
|
} else {
|
|
|
- repsResult.push({ rep: 1, points: rectJust ? outers : insides });
|
|
|
- repsResult.push({
|
|
|
- rep: 2,
|
|
|
- points: rectJust ? insides : outers.reverse(),
|
|
|
- });
|
|
|
+ update2Line(joins[0], ndx);
|
|
|
}
|
|
|
- // testPoints.value.push(...insides, ...outers);
|
|
|
- return repsResult;
|
|
|
- };
|
|
|
+ }
|
|
|
+ return [cache[0], cache[1]];
|
|
|
+ };
|
|
|
|
|
|
- const linePoints = [line.a, line.b].map(
|
|
|
- (id) => data.points.find((item) => item.id === id)!
|
|
|
+ return (data: LineData, line: LineDataLine, useJoin = true) => {
|
|
|
+ const originEdges: Pos[] = getLineEdges(
|
|
|
+ getLinePoints(data, line),
|
|
|
+ line.strokeWidth
|
|
|
);
|
|
|
- const lineRect: Pos[] = getLineRect(linePoints, line.strokeWidth);
|
|
|
- const polygon = [...lineRect];
|
|
|
- const linev = lineVector(linePoints);
|
|
|
+ const initOriginEdges = [...originEdges];
|
|
|
if (!useJoin) {
|
|
|
- return polygon;
|
|
|
+ return originEdges;
|
|
|
}
|
|
|
-
|
|
|
- linePoints.forEach((point, ndx) => {
|
|
|
- const joinLines = getJoinLine(data, line, point.id);
|
|
|
- if (joinLines.length !== 1) return;
|
|
|
- const repsResult = getJoinInfo(joinLines[0], joinLines[0].points, ndx);
|
|
|
- if (!repsResult) return;
|
|
|
- for (const rep of repsResult) {
|
|
|
- const ndx = polygon.indexOf(lineRect[rep.rep]);
|
|
|
- polygon.splice(ndx, 1, ...rep.points);
|
|
|
+ getLineInfo(data, line).forEach((info) => {
|
|
|
+ if (!info) return;
|
|
|
+ for (const rep of info) {
|
|
|
+ const ndx = originEdges.indexOf(initOriginEdges[rep.rep]);
|
|
|
+ originEdges.splice(ndx, 1, ...rep.points);
|
|
|
}
|
|
|
});
|
|
|
-
|
|
|
- return polygon;
|
|
|
+ return originEdges;
|
|
|
};
|
|
|
});
|
|
|
|
|
@@ -213,7 +204,10 @@ export const useGetDiffIconPolygons = installGlobalVar(() => {
|
|
|
});
|
|
|
|
|
|
// 计算与icon相差的多边形
|
|
|
-export const useGetDiffLineIconPolygons = (line: LineData["lines"][0], linePoints: Ref<Pos[]>) => {
|
|
|
+export const useGetDiffLineIconPolygons = (
|
|
|
+ line: LineDataLine,
|
|
|
+ linePoints: Ref<Pos[]>
|
|
|
+) => {
|
|
|
const store = useStore();
|
|
|
const drawStore = useDrawIngData();
|
|
|
const linevv = computed(() => verticalVector(lineVector(linePoints.value!)));
|