From 25c65424d5e725611b7f9bde3059c70f97f77784 Mon Sep 17 00:00:00 2001 From: fan Date: Wed, 14 Jun 2023 15:38:45 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BD=A8=E8=BF=B9=E7=BA=BF=E7=94=9F=E6=88=90?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../draw-app/properties/RunLineProperty.vue | 10 +- src/graphics/runLine/RunLine.ts | 160 +++++++++++++++++- 2 files changed, 162 insertions(+), 8 deletions(-) diff --git a/src/components/draw-app/properties/RunLineProperty.vue b/src/components/draw-app/properties/RunLineProperty.vue index e33f4f9..a97d6ab 100644 --- a/src/components/draw-app/properties/RunLineProperty.vue +++ b/src/components/draw-app/properties/RunLineProperty.vue @@ -121,13 +121,9 @@ function generatePathLine() { const runLine = drawStore.selectedGraphic as RunLine; if (runLine) { const points = runLineModel.points; - const pointsUp: Point[] = []; - const pointsDown: Point[] = []; - points.forEach((item) => { - pointsUp.push(new Point(item.x, item.y - 10)); - pointsDown.push(new Point(item.x, item.y + 10)); - }); - runLine.generatePathLine(pointsUp, pointsDown); + const points1: Point[] = []; + points.forEach((p) => points1.push(new Point(p.x, p.y))); + runLine.generatePathLine(points1); } } diff --git a/src/graphics/runLine/RunLine.ts b/src/graphics/runLine/RunLine.ts index f46d458..05808c1 100644 --- a/src/graphics/runLine/RunLine.ts +++ b/src/graphics/runLine/RunLine.ts @@ -37,6 +37,7 @@ export const runLineConsts = { runLineWidth: 6, nameFontSize: 16, nameOffsetX: 40, + pathLineDistance: 10, }; export class RunLine extends JlGraphic { @@ -94,8 +95,164 @@ export class RunLine extends JlGraphic { old.points = points; this.updateData(old); } + /** + * 计算两点法向量 + * @param point1 + * @param point2 + * @returns + */ + getNormalVector(point1: Point, point2: Point): number[] { + const x1 = point1.x, + y1 = point1.y; + const x2 = point2.x, + y2 = point2.y; + const length = Math.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2); + return [(y2 - y1) / length, (x1 - x2) / length]; + } + /** + * 点延向量方向平移 + * @param point + * @param normal 单位向量 + * @param length 平移长度 + * @returns + */ + movePointAlongNormal(point: Point, normal: number[], length: number): Point { + const newPoint = new Point( + point.x + length * normal[0], + point.y + length * normal[1] + ); + return newPoint; + } + /** + * 计算两组点各自组成直线的相交点(若两线平行 返回第一组坐标第一个点) + * @param line1 两点坐标列表 + * @param line2 两点坐标列表 + * @returns + */ + getIntersectionPoint(line1: number[], line2: number[]) { + const a1 = line1[0], + b1 = line1[1]; + const a2 = line1[2], + b2 = line1[3]; + const a3 = line2[0], + b3 = line2[1]; + const a4 = line2[2], + b4 = line2[3]; + const denominator = (a3 - a4) * (b1 - b2) - (a1 - a2) * (b3 - b4); + if (denominator === 0) { + return new Point(a1, b1); + } + const x = + ((a3 - a4) * (a2 * b1 - a1 * b2) - (a1 - a2) * (a4 * b3 - a3 * b4)) / + denominator; + const y = + ((b3 - b4) * (b2 * a1 - b1 * a2) - (b1 - b2) * (b4 * a3 - b3 * a4)) / + -denominator; + return new Point(x, y); + } - generatePathLine(pointsUp: Point[], pointsDown: Point[]) { + generatePathLine(points: Point[]) { + const pointsUp: Point[] = []; + const pointsDown: Point[] = []; + points.forEach((p, index) => { + // 起始点终止点计算两点法向量 做平移计算,中间点做线段法向量平移就交点 + if (index === 0) { + const normalVector = this.getNormalVector(p, points[index + 1]); + const resverNormalVector = [-normalVector[0], -normalVector[1]]; + pointsUp.push( + this.movePointAlongNormal( + p, + normalVector, + runLineConsts.pathLineDistance + ) + ); + pointsDown.push( + this.movePointAlongNormal( + p, + resverNormalVector, + runLineConsts.pathLineDistance + ) + ); + } else if (index === points.length - 1) { + const normalVector = this.getNormalVector(points[index - 1], p); + const resverNormalVector = [-normalVector[0], -normalVector[1]]; + pointsUp.push( + this.movePointAlongNormal( + p, + normalVector, + runLineConsts.pathLineDistance + ) + ); + pointsDown.push( + this.movePointAlongNormal( + p, + resverNormalVector, + runLineConsts.pathLineDistance + ) + ); + } else { + const normalVector1 = this.getNormalVector(p, points[index + 1]); + const resverNormalVector1 = [-normalVector1[0], -normalVector1[1]]; + const curP1 = this.movePointAlongNormal( + p, + normalVector1, + runLineConsts.pathLineDistance + ); + const nextP1 = this.movePointAlongNormal( + points[index + 1], + normalVector1, + runLineConsts.pathLineDistance + ); + const resverCurP1 = this.movePointAlongNormal( + p, + resverNormalVector1, + runLineConsts.pathLineDistance + ); + const resverNextP1 = this.movePointAlongNormal( + points[index + 1], + resverNormalVector1, + runLineConsts.pathLineDistance + ); + + const normalVector2 = this.getNormalVector(points[index - 1], p); + const resverNormalVector2 = [-normalVector2[0], -normalVector2[1]]; + console.log(normalVector2); + + const curP2 = this.movePointAlongNormal( + p, + normalVector2, + runLineConsts.pathLineDistance + ); + const nextP2 = this.movePointAlongNormal( + points[index - 1], + normalVector2, + runLineConsts.pathLineDistance + ); + const resverCurP2 = this.movePointAlongNormal( + p, + resverNormalVector2, + runLineConsts.pathLineDistance + ); + const resverNextP2 = this.movePointAlongNormal( + points[index - 1], + resverNormalVector2, + runLineConsts.pathLineDistance + ); + console.log(curP1, nextP1, curP2, nextP2, 'line'); + pointsUp.push( + this.getIntersectionPoint( + [curP1.x, curP1.y, nextP1.x, nextP1.y], + [curP2.x, curP2.y, nextP2.x, nextP2.y] + ) + ); + pointsDown.push( + this.getIntersectionPoint( + [resverCurP1.x, resverCurP1.y, resverNextP1.x, resverNextP1.y], + [resverCurP2.x, resverCurP2.y, resverNextP2.x, resverNextP2.y] + ) + ); + } + }); const app = getDrawApp(); if (!app) return; const pathLineDrawAssistant = app.getDrawAssistant( @@ -117,6 +274,7 @@ export class RunLine extends JlGraphic { const pathLineDown = pathLineDrawAssistant.quickCreate(pointsDown); this.datas.upPathLineId = pathLineUp?.id || ''; this.datas.downPathLineId = pathLineDown?.id || ''; + console.log(pointsUp, pointsDown, 'points'); } getStartPoint(): IPointData {