From 912163f9b2add1f3c09a0dba2e1529ad71a6a23a Mon Sep 17 00:00:00 2001 From: sladro Date: Thu, 29 Jan 2026 13:08:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=AF=9B=E6=96=99=E6=80=81=E3=80=81=E8=87=AA?= =?UTF-8?q?=E7=94=B1=E9=94=BB=E3=80=81=E6=96=B9=E4=BD=93=E3=80=81=E6=9C=89?= =?UTF-8?q?=E5=9C=86=E5=A4=B4=E7=9A=84=E6=A8=A1=E6=9D=BF=E5=BC=80=E5=8F=91?= =?UTF-8?q?=E5=AE=8C=E6=88=90=EF=BC=8C=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cad/FeatureDrivenDrawer.cs | 118 ++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 60 deletions(-) diff --git a/Cad/FeatureDrivenDrawer.cs b/Cad/FeatureDrivenDrawer.cs index e06b6a3..1d46ab7 100644 --- a/Cad/FeatureDrivenDrawer.cs +++ b/Cad/FeatureDrivenDrawer.cs @@ -2963,34 +2963,21 @@ namespace CadParamPluging.Cad double H = height.Value; double W = width.Value; - // 外轮廓圆弧:优先使用参数 BoxRoundHeadFilletRadiusMax 控制 - var roundHeadRParam = bag.GetDoubleOrNull(KeyBoxRoundHeadFilletRadiusMax); - double outerArcR; - if (roundHeadRParam.HasValue && roundHeadRParam.Value > 0) - { - outerArcR = roundHeadRParam.Value; - // 限制最大半径不超过高度的一半(防止自交) - outerArcR = Math.Min(outerArcR, H / 2.0); - } - else - { - // 默认兜底:固定为高度的15%作为圆弧半径 - outerArcR = H * 0.15; - } + // 外轮廓圆弧:高度固定为 H/5 + // 依据用户新需求 (2026-01-29): 黄色部分(圆弧高)是粉色部分(总高H)的1/5 + double arcHeight = H / 5.0; // 视觉比例:总宽度映射 double visualTotalW = H * 3.0; // 保持视觉宽高比约 3:1 - // 视觉上的外轮廓圆弧半径 - double visualOuterArcR = outerArcR; - // 绘图坐标计算 (保持居中) - double ox = ctx.Center.X - visualTotalW / 2.0; // 左边界 + double ox = ctx.Center.X - visualTotalW / 2.0; // 左边界 (圆弧最左端) double oy = ctx.Center.Y - H / 2.0; // 底边 - // 内框边界(从左圆弧结束到右圆弧开始) - double xInnerLeft = ox + visualOuterArcR; - double xInnerRight = ox + visualTotalW - visualOuterArcR; + // 内框边界(从左圆弧弦线到右圆弧弦线) + // 注意:ox 是圆弧顶点,xInnerLeft 应该是弦线位置 + double xInnerLeft = ox + arcHeight; + double xInnerRight = ox + visualTotalW - arcHeight; double innerWidth = xInnerRight - xInnerLeft; // 获取内框圆角参数:优先取 UnspecifiedFilletRadiusMax,如果没有则取 BoxFilletRadiusMax @@ -3004,9 +2991,9 @@ namespace CadParamPluging.Cad ? innerFilletParam.Value : 0; - // 1. 绘制完整锻件外轮廓(方体有圆头 - 白色,固定小弧度) - // 修正:外轮廓圆弧半径需增加内框圆角半径,以保证外圆弧的起点与内框圆角的起点在X轴上重合,消除直边延伸 - DrawBlockRoundHeadOutline(ctx, ox, oy, visualTotalW, H, visualOuterArcR + innerFilletR); + // 1. 绘制完整锻件外轮廓(方体有圆头 - 白色,大圆弧) + // 修正:取消外框处的圆角(改为直角),不再缩进弦线 + DrawBlockRoundHeadOutline(ctx, ox, oy, visualTotalW, H, arcHeight, 0); // 2. 绘制分段式内框(左、中、右三段)以支持中间剖面区域的独立圆角 // 中间区域(剖面)作为主体,如果设置了圆角,四个角都应为圆角 @@ -3023,14 +3010,14 @@ namespace CadParamPluging.Cad DrawBoxSectionContourWithFillet(ctx, xSectionLeft, xSectionRight, oy, H, innerFilletR); // 绘制左侧框线(连接左端圆弧和中间剖面框) - // 左端: xInnerLeft (需处理左上下角的圆角 - 修正为使用内框圆角 innerFilletR,与方体参数一致) + // 左端: xInnerLeft (需处理左上下角的圆角 - 修正为不使用圆角,改为直角 0) // 右端: xSectionLeft (连接到中间框的直边) - DrawBoxSideFrame(ctx, xInnerLeft, xSectionLeft, oy, H, innerFilletR, isLeft: true); + DrawBoxSideFrame(ctx, xInnerLeft, xSectionLeft, oy, H, 0, isLeft: true); // 绘制右侧框线 // 左端: xSectionRight (连接到中间框的直边) - // 右端: xInnerRight (需处理右上下角的圆角 - 修正为使用内框圆角 innerFilletR,与方体参数一致) - DrawBoxSideFrame(ctx, xSectionRight, xInnerRight, oy, H, innerFilletR, isLeft: false); + // 右端: xInnerRight (需处理右上下角的圆角 - 修正为不使用圆角,改为直角 0) + DrawBoxSideFrame(ctx, xSectionRight, xInnerRight, oy, H, 0, isLeft: false); // 3. 剖面填充 - 只在中间区域 // 如果有圆角,填充范围也应考虑圆角(不过Hatch边界通常可以自动处理) @@ -3043,9 +3030,6 @@ namespace CadParamPluging.Cad DrawBlockSectionHatch(ctx, xSectionLeft, xSectionRight, oy, H); } - // 4. 剖面左右边界线 -> 已包含在 DrawBoxSectionContourWithFillet 中 - // 故移除 DrawSectionInnerBoundaryBold 调用 - // 5. 零件轮廓框(黄色双点划线矩形 - 在内框内,与锻件有一定间距) var widthPrime = bag.GetDoubleOrNull(KeyBoxSize1Prime); var heightPrime = bag.GetDoubleOrNull(KeyBoxSize2Prime); @@ -3105,9 +3089,8 @@ namespace CadParamPluging.Cad // 标注从圆弧最外侧开始(避免与圆弧轮廓线重叠) double xOuterRight = ox + visualTotalW; - // 修正:标注界线起点应向内缩进(visualOuterArcR + innerFilletR),以连接到锻件顶底平直边的末端 - // 否则标注界线会从包围盒的角点开始,导致与圆角轮廓之间有空隙 - double xDimOrigin = xOuterRight - (visualOuterArcR + innerFilletR); + // 修正:标注界线起点应从圆弧顶端开始,往内缩进一个圆弧高度 arcHeight (不再包含 innerFilletR),定位在弦线上 + double xDimOrigin = xOuterRight - arcHeight; AddLinearDim( ctx, @@ -3120,7 +3103,7 @@ namespace CadParamPluging.Cad // 8. 中间矩形宽度标注(剖面区域宽度)- 第二个宽度标注,位于上方 { - var rectRealWidth = W - 2 * outerArcR; // 实际中间矩形宽度 = 总宽度 - 两端圆头 + var rectRealWidth = W - 2 * arcHeight; // 实际中间矩形宽度 = 总宽度 - 两端圆头 if (rectRealWidth > 0) { AddLinearDim( @@ -3238,38 +3221,53 @@ namespace CadParamPluging.Cad /// /// 绘制方体有圆头的完整外轮廓 - /// 结构:左圆弧 + 中间矩形顶底边 + 右圆弧(小弧度,不是半圆) + /// 结构:左侧大圆弧 (高=H/5) + 顶直线 + 右侧大圆弧 + 底直线 + /// 依据用户需求:圆弧高度(黄色)是总高度(粉色)的1/5 + /// offset: 弦线向内偏移量(通常用于与内框圆角对齐) /// - private static void DrawBlockRoundHeadOutline(DrawingContext ctx, double ox, double oy, double totalWidth, double height, double arcR) + private static void DrawBlockRoundHeadOutline(DrawingContext ctx, double ox, double oy, double totalWidth, double height, double arcHeight, double chordOffset = 0) { try { - // 使用 Polyline 绘制外轮廓 - // arcR 是圆弧部分的半径(固定小弧度) + // 计算 Bulge + // Bulge = Sagitta / HalfChord + // Sagitta = arcHeight (H/5) + // HalfChord = height / 2 + // Bulge = (H/5) / (H/2) = 2/5 = 0.4 + // 修正:0.4 (CCW) 导致圆弧向内凹(可能与Polyline默认法向或绘制方向有关),改为 -0.4 以向外凸 + double bulge = -0.4; + + // 弦线位置(修正:增加 offset 以与内框圆角起点对齐) + double xChordLeft = ox + arcHeight + chordOffset; + double xChordRight = ox + totalWidth - arcHeight - chordOffset; + var poly = new Polyline(); - // 圆弧的 bulge 值:对于90度圆角,bulge = tan(22.5°) ≈ 0.414 - double bulge = Math.Tan(Math.PI / 8.0); - - // 左侧圆弧中心 X 坐标 - double xLeftArc = ox + arcR; - // 右侧圆弧中心 X 坐标 - double xRightArc = ox + totalWidth - arcR; - - // 从左下开始,顺时针绘制带圆角的矩形外轮廓 - // 左下角 - poly.AddVertexAt(0, new Point2d(ox, oy + arcR), bulge, 0, 0); // 左下圆弧 - poly.AddVertexAt(1, new Point2d(xLeftArc, oy), 0, 0, 0); // 底边开始 - // 右下角 - poly.AddVertexAt(2, new Point2d(xRightArc, oy), bulge, 0, 0); // 右下圆弧 - poly.AddVertexAt(3, new Point2d(ox + totalWidth, oy + arcR), 0, 0, 0); // 右边开始 - // 右上角 - poly.AddVertexAt(4, new Point2d(ox + totalWidth, oy + height - arcR), bulge, 0, 0); // 右上圆弧 - poly.AddVertexAt(5, new Point2d(xRightArc, oy + height), 0, 0, 0); // 顶边开始 - // 左上角 - poly.AddVertexAt(6, new Point2d(xLeftArc, oy + height), bulge, 0, 0); // 左上圆弧 - poly.AddVertexAt(7, new Point2d(ox, oy + height - arcR), 0, 0, 0); // 左边开始 + // 顺时针绘制 (CW) + // 1. 左下角 (Start of Left Arc) + // 注意:为了让左侧圆弧向外(向左),在CW路径中(向上走),Bulge应为正(Left side of vector) + // wait, CW path on left side goes UP. + // Vector results: Up. + // Bulge > 0 means CCW from vector. CCW from Up is Left. + // So Bulge = 0.4 creates arc to Left. Correct. + poly.AddVertexAt(0, new Point2d(xChordLeft, oy), bulge, 0, 0); + // 2. 左上角 (End of Left Arc, Start of Top Line) + poly.AddVertexAt(1, new Point2d(xChordLeft, oy + height), 0, 0, 0); + + // 3. 右上角 (End of Top Line, Start of Right Arc) + // CW path goes Right? No, Top Line goes Right. + // Right side path goes Down. + // Vector: Down. + // We want Arc to Right. + // CCW from Down is Right. + // So Bulge = 0.4. + poly.AddVertexAt(2, new Point2d(xChordRight, oy + height), bulge, 0, 0); + + // 4. 右下角 (End of Right Arc, Start of Bottom Line) + poly.AddVertexAt(3, new Point2d(xChordRight, oy), 0, 0, 0); + + // Close back to 0 poly.Closed = true; ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold);