From 3498650f5f063b2923c97e1d9153e70b9fc26184 Mon Sep 17 00:00:00 2001 From: dmy Date: Wed, 4 Mar 2026 11:08:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=BF=9D=E6=8A=A4?= =?UTF-8?q?=E8=A7=92=E5=8F=AF=E8=A7=86=E5=8C=96=E7=BB=98=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 2 +- webui/src/components/Geometry.vue | 82 +++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index 7883b25..4b8785c 100644 --- a/main.py +++ b/main.py @@ -157,7 +157,7 @@ def run_egm(para: Parameter, animation=None) -> dict: * 180 / math.pi ) # 挂点处保护角 - logger.info(f"挂点处保护角{shield_angle_at_avg_height:.3f}°") + logger.info(f"地线保护角{shield_angle_at_avg_height:.2f}°") logger.debug(f"最低相防护标识{rg_type}。(g表示地面,c表示下导线)") rated_voltage = para.rated_voltage logger.info(f"交、直流标识{para.ac_or_dc}") diff --git a/webui/src/components/Geometry.vue b/webui/src/components/Geometry.vue index 67869aa..63c9386 100644 --- a/webui/src/components/Geometry.vue +++ b/webui/src/components/Geometry.vue @@ -210,6 +210,9 @@ const draw = () => { // 绘制导线和地线挂点 drawWirePoints(range) + + // 绘制保护角 + drawShieldingAngle(range) } // 绘制导线和地线挂点 @@ -295,6 +298,85 @@ const drawGround = (range: ReturnType) => { ctx.stroke() } +// 绘制保护角 +const drawShieldingAngle = (range: ReturnType) => { + if (!ctx || props.hArm.length < 2) return + + const actualHeights = calculateActualHeights() + const gwX = Number(props.gcX[0]) || 0 + const gwY = actualHeights[0] + const cwX = Number(props.gcX[1]) || 0 + const cwY = actualHeights[1] + + const gwCanvasX = toCanvasX(gwX, range) + const gwCanvasY = toCanvasY(gwY, range) + const cwCanvasX = toCanvasX(cwX, range) + const cwCanvasY = toCanvasY(cwY, range) + + // 计算保护角(地线与导线连线与垂直线的夹角) + const dx = cwX - gwX + const dy = gwY - cwY + const shieldingAngle = Math.atan2(dx, dy) * (180 / Math.PI) + + // 绘制从地线到导线1的虚线 + ctx.strokeStyle = '#9C27B0' + ctx.lineWidth = 2 + ctx.setLineDash([6, 4]) + ctx.beginPath() + ctx.moveTo(gwCanvasX, gwCanvasY) + ctx.lineTo(cwCanvasX, cwCanvasY) + ctx.stroke() + ctx.setLineDash([]) + + // // 绘制垂直参考线(从地线向下) + // ctx.strokeStyle = 'rgba(156, 39, 176, 0.3)' + // ctx.lineWidth = 1 + // ctx.setLineDash([4, 4]) + // ctx.beginPath() + // ctx.moveTo(gwCanvasX, gwCanvasY) + // ctx.lineTo(gwCanvasX, gwCanvasY + 80) + // ctx.stroke() + // ctx.setLineDash([]) + + // // 绘制角度弧 + // const arcRadius = 30 + // const verticalAngle = Math.PI / 2 // 向下 + // const lineAngle = Math.atan2(cwCanvasY - gwCanvasY, cwCanvasX - gwCanvasX) + + ctx.strokeStyle = '#9C27B0' + ctx.lineWidth = 1.5 + ctx.beginPath() + // if (dx >= 0) { + // ctx.arc(gwCanvasX, gwCanvasY, arcRadius, Math.PI / 2, lineAngle, true) + // } else { + // ctx.arc(gwCanvasX, gwCanvasY, arcRadius, lineAngle, Math.PI / 2, false) + // } + // ctx.stroke() + + // 计算标注位置(在线的右侧) + const midX = (gwCanvasX + cwCanvasX) / 2 + const midY = (gwCanvasY + cwCanvasY) / 2 + const labelOffsetX = dx >= 0 ? -45 : 45 + const labelOffsetY = 0 + + // 绘制引线 + ctx.strokeStyle = '#9C27B0' + ctx.lineWidth = 1 + ctx.beginPath() + ctx.moveTo(midX, midY) + ctx.lineTo(midX + labelOffsetX, midY + labelOffsetY) + ctx.stroke() + + // 绘制标注文字 + const labelText = `保护角: ${Math.abs(shieldingAngle).toFixed(2)}°` + ctx.font = 'bold 12px Arial' + + // 绘制标注文字 + ctx.fillStyle = '#9C27B0' + ctx.textAlign = 'left' + ctx.fillText(labelText, midX + labelOffsetX, midY + labelOffsetY) +} + // 监听参数变化 watch( () => [props.hArm, props.gcX, props.hCSag, props.hGSag, props.stringCLen, props.stringGLen, props.groundAngels],