|
@@ -17,9 +17,12 @@ import { copy, mergeFuns, onlyId, rangMod } from "@/utils/shared";
|
|
import {
|
|
import {
|
|
eqPoint,
|
|
eqPoint,
|
|
getVectorLine,
|
|
getVectorLine,
|
|
|
|
+ lineIntersection,
|
|
|
|
+ lineLen,
|
|
linePointProjection,
|
|
linePointProjection,
|
|
lineVector,
|
|
lineVector,
|
|
Pos,
|
|
Pos,
|
|
|
|
+ vector,
|
|
vector2IncludedAngle,
|
|
vector2IncludedAngle,
|
|
verticalVector,
|
|
verticalVector,
|
|
zeroEq,
|
|
zeroEq,
|
|
@@ -328,21 +331,26 @@ export const getInitCtx = (): NLineDataCtx => ({
|
|
},
|
|
},
|
|
});
|
|
});
|
|
|
|
|
|
-export const repPointRef = (data: LineData, delId: string, repId: string, queUpdate = true) => {
|
|
|
|
|
|
+export const repPointRef = (
|
|
|
|
+ data: LineData,
|
|
|
|
+ delId: string,
|
|
|
|
+ repId: string,
|
|
|
|
+ queUpdate = true
|
|
|
|
+) => {
|
|
for (let i = 0; i < data.lines.length; i++) {
|
|
for (let i = 0; i < data.lines.length; i++) {
|
|
const line = data.lines[i];
|
|
const line = data.lines[i];
|
|
if (line.a === delId) {
|
|
if (line.a === delId) {
|
|
if (queUpdate) {
|
|
if (queUpdate) {
|
|
data.lines[i] = { ...line, a: repId };
|
|
data.lines[i] = { ...line, a: repId };
|
|
} else {
|
|
} else {
|
|
- data.lines[i].a = repId
|
|
|
|
|
|
+ data.lines[i].a = repId;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (line.b === delId) {
|
|
if (line.b === delId) {
|
|
if (queUpdate) {
|
|
if (queUpdate) {
|
|
data.lines[i] = { ...line, b: repId };
|
|
data.lines[i] = { ...line, b: repId };
|
|
} else {
|
|
} else {
|
|
- data.lines[i].b = repId
|
|
|
|
|
|
+ data.lines[i].b = repId;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -423,11 +431,16 @@ export const normalLineData = (data: LineData, ctx: NLineDataCtx) => {
|
|
return deduplicateLines(data);
|
|
return deduplicateLines(data);
|
|
};
|
|
};
|
|
|
|
|
|
-export const genMoveLineHandler = (data: LineData, lineId: string, ctx = getInitCtx()) => {
|
|
|
|
|
|
+export const genMoveLineHandler = (
|
|
|
|
+ data: LineData,
|
|
|
|
+ lineId: string,
|
|
|
|
+ ctx = getInitCtx()
|
|
|
|
+) => {
|
|
const line = data.lines.find((line) => line.id === lineId)!;
|
|
const line = data.lines.find((line) => line.id === lineId)!;
|
|
const pointIds = [line.a, line.b];
|
|
const pointIds = [line.a, line.b];
|
|
const points = pointIds.map((id) => data.points.find((p) => p.id === id)!);
|
|
const points = pointIds.map((id) => data.points.find((p) => p.id === id)!);
|
|
- const initPoints = copy(points)
|
|
|
|
|
|
+ const lineDire = lineVector(points)
|
|
|
|
+ const initPoints = copy(points);
|
|
const angleRange = [MathUtils.degToRad(10), MathUtils.degToRad(170)];
|
|
const angleRange = [MathUtils.degToRad(10), MathUtils.degToRad(170)];
|
|
const getJoinLine = (pId: string) =>
|
|
const getJoinLine = (pId: string) =>
|
|
data.lines
|
|
data.lines
|
|
@@ -505,67 +518,104 @@ export const genMoveLineHandler = (data: LineData, lineId: string, ctx = getInit
|
|
angle: invAngle!,
|
|
angle: invAngle!,
|
|
};
|
|
};
|
|
|
|
|
|
-
|
|
|
|
- info.angle = rangMod(info.angle, Math.PI)
|
|
|
|
- const needVertical = info.angle > angleRange[1] || info.angle < angleRange[0];
|
|
|
|
- const needSplit = needVertical || joinLineDires.some(
|
|
|
|
|
|
+ info.angle = rangMod(info.angle, Math.PI);
|
|
|
|
+ const needVertical =
|
|
|
|
+ info.angle > angleRange[1] || info.angle < angleRange[0];
|
|
|
|
+ const needSplit =
|
|
|
|
+ needVertical ||
|
|
|
|
+ joinLineDires.some(
|
|
(dire) =>
|
|
(dire) =>
|
|
dire !== info.selectLineDire &&
|
|
dire !== info.selectLineDire &&
|
|
!zeroEq(
|
|
!zeroEq(
|
|
rangMod(vector2IncludedAngle(dire, info.selectLineDire), Math.PI)
|
|
rangMod(vector2IncludedAngle(dire, info.selectLineDire), Math.PI)
|
|
)
|
|
)
|
|
- )
|
|
|
|
- return { ...info, needSplit, needVertical }
|
|
|
|
|
|
+ );
|
|
|
|
+ return { ...info, needSplit, needVertical };
|
|
};
|
|
};
|
|
|
|
|
|
let refInfos: ReturnType<typeof getRefInfo>[];
|
|
let refInfos: ReturnType<typeof getRefInfo>[];
|
|
- let snapLines: (null | Pos[])[]
|
|
|
|
- let inited = false
|
|
|
|
|
|
+ let snapLines: (null | Pos[])[];
|
|
|
|
+ let inited = false;
|
|
|
|
|
|
const init = (moveDires: Vector2[]) => {
|
|
const init = (moveDires: Vector2[]) => {
|
|
- refInfos = [getRefInfo(moveDires[0], 0), getRefInfo(moveDires[0], 1)]
|
|
|
|
- snapLines = []
|
|
|
|
|
|
+ refInfos = [getRefInfo(moveDires[0], 0), getRefInfo(moveDires[0], 1)];
|
|
|
|
+ snapLines = [];
|
|
for (let i = 0; i < refInfos.length; i++) {
|
|
for (let i = 0; i < refInfos.length; i++) {
|
|
- const refInfo = refInfos[i]
|
|
|
|
|
|
+ const refInfo = refInfos[i];
|
|
if (!refInfo) {
|
|
if (!refInfo) {
|
|
- continue
|
|
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
if (refInfo.needSplit) {
|
|
if (refInfo.needSplit) {
|
|
// 拆分点
|
|
// 拆分点
|
|
- const point = points[i]
|
|
|
|
- const newPoint = { ...point, id: onlyId() }
|
|
|
|
- data.points.push(newPoint)
|
|
|
|
- repPointRef(data, point.id, newPoint.id, false)
|
|
|
|
- const newLine = { ...getBaseItem(), ...defaultStyle, a: point.id, b: newPoint.id }
|
|
|
|
- data.lines.push(newLine)
|
|
|
|
- ctx.add.lines[newLine.id] = newLine
|
|
|
|
- ctx.add.points[newPoint.id] = newPoint
|
|
|
|
|
|
+ const point = points[i];
|
|
|
|
+ const newPoint = { ...point, id: onlyId() };
|
|
|
|
+ data.points.push(newPoint);
|
|
|
|
+ repPointRef(data, point.id, newPoint.id, false);
|
|
|
|
+ const newLine = {
|
|
|
|
+ ...getBaseItem(),
|
|
|
|
+ ...defaultStyle,
|
|
|
|
+ a: point.id,
|
|
|
|
+ b: newPoint.id,
|
|
|
|
+ };
|
|
|
|
+ data.lines.push(newLine);
|
|
|
|
+ ctx.add.lines[newLine.id] = newLine;
|
|
|
|
+ ctx.add.points[newPoint.id] = newPoint;
|
|
|
|
|
|
if (i) {
|
|
if (i) {
|
|
- line.b = point.id
|
|
|
|
|
|
+ line.b = point.id;
|
|
} else {
|
|
} else {
|
|
- line.a = point.id
|
|
|
|
|
|
+ line.a = point.id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- const dire = refInfo.needVertical ? verticalVector(refInfo.selectLineDire) : refInfo.selectLineDire
|
|
|
|
- snapLines[i] = getVectorLine(dire, copy(points[i]), 10)
|
|
|
|
|
|
+ const dire = refInfo.needVertical
|
|
|
|
+ ? verticalVector(refInfo.selectLineDire)
|
|
|
|
+ : refInfo.selectLineDire;
|
|
|
|
+ snapLines[i] = getVectorLine(dire, copy(points[i]), 10);
|
|
}
|
|
}
|
|
|
|
+ };
|
|
|
|
+ const assignPos = (origin: LineData['points'][0], target: Pos) => {
|
|
|
|
+ origin.x = target.x
|
|
|
|
+ origin.y = target.y
|
|
|
|
+ ctx.update.points[origin.id] = origin
|
|
}
|
|
}
|
|
|
|
|
|
const handler = (finalPoss: Pos[]) => {
|
|
const handler = (finalPoss: Pos[]) => {
|
|
- const moveDires = finalPoss.map((pos, ndx) => lineVector([initPoints[ndx], pos]))
|
|
|
|
if (!inited) {
|
|
if (!inited) {
|
|
- inited = true
|
|
|
|
- init(moveDires)
|
|
|
|
|
|
+ const moveDires = finalPoss.map((pos, ndx) =>
|
|
|
|
+ lineVector([initPoints[ndx], pos])
|
|
|
|
+ );
|
|
|
|
+ inited = true;
|
|
|
|
+ init(moveDires);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!snapLines[0] && !snapLines[1]) {
|
|
|
|
+ assignPos(points[0], finalPoss[0])
|
|
|
|
+ assignPos(points[1], finalPoss[1])
|
|
|
|
+ return;
|
|
|
|
+ } else if (!snapLines[0]) {
|
|
|
|
+ const pos = linePointProjection(snapLines[1]!, finalPoss[1])
|
|
|
|
+ assignPos(points[1], pos)
|
|
|
|
+ assignPos(points[0], pos.sub(initPoints[1]).add(initPoints[0]))
|
|
|
|
+ return;
|
|
|
|
+ } else if (!snapLines[1]) {
|
|
|
|
+ const pos = linePointProjection(snapLines[0]!, finalPoss[0])
|
|
|
|
+ assignPos(points[0], pos)
|
|
|
|
+ assignPos(points[1], pos.sub(initPoints[0]).add(initPoints[1]))
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
-
|
|
|
|
- for (let i = 0; i < snapLines.length; i++) {
|
|
|
|
- const snapLine = snapLines[i]
|
|
|
|
- const fpos = !snapLine ? finalPoss[i] : linePointProjection(snapLine, finalPoss[i])
|
|
|
|
- Object.assign(points[i], fpos)
|
|
|
|
- ctx.update.points[points[i].id] = points[i]
|
|
|
|
|
|
+
|
|
|
|
+ const moves = snapLines.map((snapLine, i) => {
|
|
|
|
+ const pos = !snapLine ? finalPoss[i] : linePointProjection(snapLine, finalPoss[i])
|
|
|
|
+ return vector(pos).sub(initPoints[i])
|
|
|
|
+ });
|
|
|
|
+ if (moves[0].lengthSq() > moves[1].lengthSq()) {
|
|
|
|
+ assignPos(points[0], moves[0].add(initPoints[0]));
|
|
|
|
+ assignPos(points[1], lineIntersection(getVectorLine(lineDire, points[0]), snapLines[1])!)
|
|
|
|
+ } else {
|
|
|
|
+ assignPos(points[1], moves[1].add(initPoints[1]));
|
|
|
|
+ assignPos(points[0], lineIntersection(getVectorLine(lineDire, points[1]), snapLines[0])!)
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
- return handler
|
|
|
|
|
|
+ return handler;
|
|
};
|
|
};
|