diff --git a/src/services/editor.service.ts b/src/services/editor.service.ts index 03e20fa..68b1414 100644 --- a/src/services/editor.service.ts +++ b/src/services/editor.service.ts @@ -796,6 +796,9 @@ function drawLine(ctx: CanvasRenderingContext2D, pen: MapPen): void { const { type, direction = 1, pass = 0, c1, c2 } = pen.route ?? {}; const { x: dx1 = 0, y: dy1 = 0 } = c1 ?? {}; const { x: dx2 = 0, y: dy2 = 0 } = c2 ?? {}; + const [c1x, c1y] = [x1 + dx1 * s, y1 + dy1 * s]; + const [c2x, c2y] = [x2 + dx2 * s, y2 + dy2 * s]; + const t = direction < 0 ? 0.5 : 0.5; ctx.save(); ctx.beginPath(); @@ -807,14 +810,14 @@ function drawLine(ctx: CanvasRenderingContext2D, pen: MapPen): void { ctx.lineTo(x2, y2); break; case MapRouteType.二阶贝塞尔曲线: - ctx.quadraticCurveTo(x1 + dx1 * s, y1 + dy1 * s, x2, y2); + ctx.quadraticCurveTo(c1x, c1y, x2, y2); p1.next = { x: x1 + (2 / 3) * dx1 * s, y: y1 + (2 / 3) * dy1 * s }; - p2.prev = { x: x2 / 3 + (2 / 3) * (x1 + dx1 * s), y: y2 / 3 + (2 / 3) * (y1 + dy1 * s) }; + p2.prev = { x: x2 / 3 + (2 / 3) * c1x, y: y2 / 3 + (2 / 3) * c1y }; break; case MapRouteType.三阶贝塞尔曲线: - ctx.bezierCurveTo(x1 + dx1 * s, y1 + dy1 * s, x2 + dx2 * s, y2 + dy2 * s, x2, y2); - p1.next = { x: x1 + dx1 * s, y: y1 + dy1 * s }; - p2.prev = { x: x2 + dx2 * s, y: y2 + dy2 * s }; + ctx.bezierCurveTo(c1x, c1y, c2x, c2y, x2, y2); + p1.next = { x: c1x, y: c1y }; + p2.prev = { x: c2x, y: c2y }; break; default: break; @@ -825,22 +828,50 @@ function drawLine(ctx: CanvasRenderingContext2D, pen: MapPen): void { ctx.stroke(); ctx.beginPath(); ctx.setLineDash([0]); - let r = (() => { - switch (type) { - case MapRouteType.直线: - return Math.atan2(y2 - y1, x2 - x1); - case MapRouteType.二阶贝塞尔曲线: - return direction < 0 ? Math.atan2(dy1 * s, dx1 * s) : Math.atan2(y2 - y1 - dy1 * s, x2 - x1 - dx1 * s); - case MapRouteType.三阶贝塞尔曲线: - return direction < 0 ? Math.atan2(dy1 * s, dx1 * s) : Math.atan2(-dy2 * s, -dx2 * s); - default: - return 0; - } - })(); - if (direction < 0) { - ctx.translate(x1, y1); - } else { - ctx.translate(x2, y2); + + let [ax, ay] = [0, 0]; + let r = 0; + switch (type) { + case MapRouteType.直线: + { + ax = x1 + (x2 - x1) * t; + ay = y1 + (y2 - y1) * t; + r = Math.atan2(y2 - y1, x2 - x1); + } + break; + case MapRouteType.二阶贝塞尔曲线: + { + const t1x = x1 + (c1x - x1) * t; + const t1y = y1 + (c1y - y1) * t; + const t2x = c1x + (x2 - c1x) * t; + const t2y = c1y + (y2 - c1y) * t; + ax = t1x + (t2x - t1x) * t; + ay = t1y + (t2y - t1y) * t; + r = Math.atan2(t2y - t1y, t2x - t1x); + } + break; + case MapRouteType.三阶贝塞尔曲线: + { + const t1x = x1 + (c1x - x1) * t; + const t1y = y1 + (c1y - y1) * t; + const t2x = c1x + (c2x - c1x) * t; + const t2y = c1y + (c2y - c1y) * t; + const t3x = c2x + (x2 - c2x) * t; + const t3y = c2y + (y2 - c2y) * t; + const t12x = t1x + (t2x - t1x) * t; + const t12y = t1y + (t2y - t1y) * t; + const t23x = t2x + (t3x - t2x) * t; + const t23y = t2y + (t3y - t2y) * t; + ax = t12x + (t23x - t12x) * t; + ay = t12y + (t23y - t12y) * t; + r = Math.atan2(t23y - t12y, t23x - t12x); + } + break; + default: + break; + } + ctx.translate(ax, ay); + if (direction > 0) { r += Math.PI; } ctx.moveTo(Math.cos(r + Math.PI / 5) * s * 10, Math.sin(r + Math.PI / 5) * s * 10); @@ -936,3 +967,23 @@ function drawRobot(ctx: CanvasRenderingContext2D, pen: MapPen): void { ctx.restore(); } //#endregion + +//#region 辅助函数 +function calcLinePoint(p1: Point, p2: Point, t: number): Point { + const x = p1.x + (p2.x - p1.x) * t; + const y = p1.y + (p2.y - p1.y) * t; + return { x, y }; +} + +// function calcBezierPoint(points: Point[], t: number): Point { + +// while (pts.length > 1) { +// const nextPts = []; +// for (let i = 0, size = pts.length - 1; i < size; i++) { +// nextPts.push(lerp(pts[i], pts[i + 1], t)); +// } +// pts = nextPts; +// } +// return pts[0]; +// } +//#endregion