From f55b32e9faaa56b276a23f24fd1382e827f03d69 Mon Sep 17 00:00:00 2001 From: sladro Date: Wed, 14 Jan 2026 12:03:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=94=9F=E6=88=90=E5=9B=BE?= =?UTF-8?q?=E7=BA=B8=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cad/DictionaryHelper.cs | 14 +++ Cad/FeatureDrivenDrawer.cs | 171 +++++++++++++++++++++++++++------- Cad/TemplateDrawingService.cs | 2 +- UI/DrawingParamsForm.cs | 60 ++++++++---- UI/ParamDrawingPanel.cs | 17 +++- 5 files changed, 211 insertions(+), 53 deletions(-) diff --git a/Cad/DictionaryHelper.cs b/Cad/DictionaryHelper.cs index fc29ed1..323137d 100644 --- a/Cad/DictionaryHelper.cs +++ b/Cad/DictionaryHelper.cs @@ -2,6 +2,8 @@ using System; using System.Collections.Generic; using Autodesk.AutoCAD.DatabaseServices; using CadParamPluging.Common; +using Autodesk.AutoCAD.ApplicationServices; +using Autodesk.AutoCAD.EditorInput; namespace CadParamPluging.Cad { @@ -56,6 +58,12 @@ namespace CadParamPluging.Cad rb.Add(new TypedValue((int)DxfCode.Text, entry)); } } + + try + { + // Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage($"\n[CadParamPluging] Saving Params: Count={bag.Items.Count}\n"); + } + catch {} var xrec = new Xrecord(); xrec.Data = rb; @@ -117,6 +125,12 @@ namespace CadParamPluging.Cad if (parts.Length == 2) { bag.Set(parts[0], parts[1]); + + try + { + // Log Hardness read + } + catch {} } else if (parts.Length == 1) { diff --git a/Cad/FeatureDrivenDrawer.cs b/Cad/FeatureDrivenDrawer.cs index 7df0b46..a503620 100644 --- a/Cad/FeatureDrivenDrawer.cs +++ b/Cad/FeatureDrivenDrawer.cs @@ -157,12 +157,33 @@ namespace CadParamPluging.Cad var outerDia = bag.GetDoubleOrNull(KeyOuterDiameter1) ?? 0; var height = bag.GetDoubleOrNull(KeyHeight1) ?? 0; + // Check if schematic mode applies (Machined + Rolling) + // Need to fetch from bag as we don't have DrawingContext here + var deliveryStatus = bag.GetString("DeliveryStatus"); + var processMethod = bag.GetString("ProcessMethod"); + + bool isMachined = !string.IsNullOrWhiteSpace(deliveryStatus) && deliveryStatus.Contains("车加工"); + bool isRolling = !string.IsNullOrWhiteSpace(processMethod) && processMethod.Contains("轧制"); + + double activeWidth = outerDia; + double extraMargin = 40; // Default margin + + if (isMachined && isRolling) + { + // In schematic mode, width is visually fixed to 2.0 * Height + activeWidth = height * 2.0; + + // 对于示意图模式,边距应按比例计算(图形较大尺寸的50%),上限100 + // 避免小型示意图因边距过大导致"预期尺寸"虚高 + var maxDim = Math.Max(activeWidth, height); + extraMargin = Math.Min(maxDim * 0.5, 100); + } + // 环形图形:宽度=外径(X方向),高度=高度参数(Y方向) - // 加上标注的额外空间(约40像素每侧) - var extraMargin = 40; + // 加上标注的额外空间 return new ExpectedDrawingSize { - Width = outerDia + extraMargin * 2, + Width = activeWidth + extraMargin * 2, Height = height + extraMargin * 2 }; } @@ -353,12 +374,72 @@ namespace CadParamPluging.Cad private static void DrawRingFeaturesHalf(DrawingContext ctx, double outerDia, double height) { var bag = ctx.Bag; - double R = outerDia / 2.0; // 外半径 + + // --- 几何与视觉映射计算 --- double H = height; + double physicalOuterR = outerDia / 2.0; + + // 1. 确定视觉外半径 (L) + // 轧制+车加工:强制 L/H = 2 + double visualOuterR = physicalOuterR; + if (ctx.IsMachined) + { + visualOuterR = H * 2.0; + } + + // 2. 确定视觉内半径 + var innerDia = bag.GetDoubleOrNull(KeyInnerDiameter2); + double physicalInnerR = 0; + double visualInnerR = 0; + + if (innerDia.HasValue && innerDia.Value > 0 && innerDia.Value < outerDia) + { + physicalInnerR = innerDia.Value / 2.0; + + if (ctx.IsMachined) + { + // 强制示意图模式: + // 按照用户提供的参考图 (L/H=2),右侧剖面区域和左侧内孔区域各占一半 + // 即 Visual Inner Radius = Visual Outer Radius / 2.0 + // 这样视觉上就是两个并排的正方形:左边是空的,右边是剖面 + visualInnerR = visualOuterR * 0.5; + } + else + { + visualInnerR = physicalInnerR * (visualOuterR / physicalOuterR); + } + } + + // 3. 定义半径映射函数 (非线性映射:孔区线性,壁厚区线性) + // r: 物理半径 + double MapRadius(double r) + { + if (r <= 0) return 0; + + // 如果没有内孔,直接线性映射 + if (physicalInnerR <= 1e-6) + { + return r * (visualOuterR / physicalOuterR); + } + + if (r <= physicalInnerR) + { + // 孔区映射 + return r * (visualInnerR / physicalInnerR); + } + else + { + // 壁厚区映射 + // V = Vir + (r - Pir) * (Vor - Vir) / (Por - Pir) + double wallScale = (visualOuterR - visualInnerR) / (physicalOuterR - physicalInnerR); + return visualInnerR + (r - physicalInnerR) * wallScale; + } + } + + // --- 绘图坐标计算 --- // 轧制时图形只画右半边,但要保持居中 - // 半图宽度为R,要居中则起点为 Center.X - R/2 - double ox = ctx.Center.X - R / 2.0; // 对称轴位置(左边界) + double ox = ctx.Center.X - visualOuterR / 2.0; // 对称轴位置(视觉左边界) double oy = ctx.Center.Y - H / 2.0; // 车加工态零件尺寸 @@ -372,77 +453,91 @@ namespace CadParamPluging.Cad heightPrime = bag.GetDoubleOrNull(KeyHeight1Prime); } - // === 特征1: 锻件外轮廓(右半边,三条边:下、右、上,左边开口) === - DrawForgingOuterContourHalf(ctx, ox, oy, R, H); + // === 特征1: 锻件外轮廓 === + DrawForgingOuterContourHalf(ctx, ox, oy, visualOuterR, H); - // === 特征1.1: 对称轴(垂直中心线) === + // === 特征1.1: 对称轴 === DrawRingSymmetryAxis(ctx, ox, oy, H); // === 特征2: 外径公差标注 === var outerTolPlus = bag.GetDoubleOrNull(KeyOuterDiameter1TolPlus); var outerTolMinus = bag.GetDoubleOrNull(KeyOuterDiameter1TolMinus); - DrawOuterDiameterDimensionHalf(ctx, ox, oy, R, H, outerDia, outerTolPlus, outerTolMinus, outerDiaPrime); + // 传入 visualOuterR 用于画线,传入 outerDia 用于文本 + DrawOuterDiameterDimensionHalf(ctx, ox, oy, visualOuterR, H, outerDia, outerTolPlus, outerTolMinus, outerDiaPrime); - // === 特征3: 内孔/内径(如果有内径参数) === - var innerDia = bag.GetDoubleOrNull(KeyInnerDiameter2); + // === 特征3: 内孔/内径 === double? xInnerRight = null; if (innerDia.HasValue && innerDia.Value > 0 && innerDia.Value < outerDia) { - double innerR = innerDia.Value / 2.0; - xInnerRight = ox + innerR; + // 计算视觉上的内径右边界 + xInnerRight = ox + visualInnerR; var innerTolPlus = bag.GetDoubleOrNull(KeyInnerDiameter2TolPlus); var innerTolMinus = bag.GetDoubleOrNull(KeyInnerDiameter2TolMinus); - // 只画右侧内孔线 DrawInnerHoleHalf(ctx, ox, xInnerRight.Value, oy, H); + // 传入 raw innerDia for text DrawInnerDiameterDimensionHalf(ctx, ox, xInnerRight.Value, oy, H, innerDia.Value, innerTolPlus, innerTolMinus, innerDiaPrime); - // === 特征4: 内径圆角(只画右侧) === + // === 特征4: 内径圆角 === var innerRadiusMax = bag.GetDoubleOrNull(KeyInnerRadiusMax); if (innerRadiusMax.HasValue && innerRadiusMax.Value > 0 && ctx.IsCenterPunched) { DrawInnerFilletsHalf(ctx, xInnerRight.Value, oy, H, innerRadiusMax.Value); } - // === 特征4.1: 剖面线(右半边环形截面) === - DrawRingSectionHatch(ctx, xInnerRight.Value, ox + R, oy, H); + // === 特征4.1: 剖面线 === + DrawRingSectionHatch(ctx, xInnerRight.Value, ox + visualOuterR, oy, H); - // 剖面左侧竖线应为粗实线(剖切边界) + // 剖面左侧竖线 DrawSectionInnerBoundaryBold(ctx, xInnerRight.Value, oy, H); } // === 特征5: 高度标注 === var heightTolPlus = bag.GetDoubleOrNull(KeyHeight1TolPlus); var heightTolMinus = bag.GetDoubleOrNull(KeyHeight1TolMinus); - DrawHeightDimensionHalf(ctx, ox, oy, R, H, heightTolPlus, heightTolMinus, heightPrime); + DrawHeightDimensionHalf(ctx, ox, oy, visualOuterR, H, heightTolPlus, heightTolMinus, heightPrime); // === 特征6: 未注圆角 === var unspecifiedFillet = bag.GetDoubleOrNull(KeyUnspecifiedFilletRadiusMax); if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0) { - DrawUnspecifiedFilletNote(ctx, ox, oy, H, R, unspecifiedFillet.Value); + DrawUnspecifiedFilletNote(ctx, ox, oy, H, visualOuterR, unspecifiedFillet.Value); } // === 特征7: 最小壁厚min标注 === var minWallThickness = bag.GetDoubleOrNull(KeyMinWallThickness); if (minWallThickness.HasValue && minWallThickness.Value > 0 && xInnerRight.HasValue) { - DrawMinWallThicknessNote(ctx, xInnerRight.Value, ox + R, oy, minWallThickness.Value); + DrawMinWallThicknessNote(ctx, xInnerRight.Value, ox + visualOuterR, oy, minWallThickness.Value); } // === 特征8: 零件轮廓(车加工态,右半边) === if (ctx.IsMachined && outerDiaPrime.HasValue && outerDiaPrime.Value > 0 && heightPrime.HasValue && heightPrime.Value > 0) { - DrawPartContourHalf(ctx, ox, oy, H, outerDiaPrime.Value, innerDiaPrime, heightPrime.Value); + // 零件轮廓(黄色部分)与锻件轮廓(白色部分)的间隙: + // 由于采用了强制比例和非线性映射,直接映射会导致间隙过大。 + // 此处采用固定视觉间隙 (2.5个单位),确保零件框紧贴锻件框内部,符合示意图效果。 + + var visualGap = 2.5; + var scaledOuterDiaPrime = (visualOuterR - visualGap) * 2.0; + var scaledInnerDiaPrime = innerDiaPrime.HasValue + ? (visualInnerR + visualGap) * 2.0 + : (double?)null; + + // 同时也修正高度方向的视觉间隙,使其上下也紧贴外框 + var scaledHeightPrime = H - visualGap * 2.0; + + DrawPartContourHalf(ctx, ox, oy, H, scaledOuterDiaPrime, scaledInnerDiaPrime, scaledHeightPrime); } // === 特征10: 轧制+车加工 特殊引线标注 (HB5936-13) === // 需满足: 车加工 + 轧制(本方法即为轧制) + 有内孔 if (ctx.IsMachined && innerDia.HasValue && innerDia.Value > 0) { - // 指向锻件内孔右上角 - DrawSpecialInnerHoleLeader(ctx, ox, oy, H, innerDia.Value); + // 指向锻件内孔右上角(白色线框) + var scaledInnerDia = visualInnerR * 2.0; + DrawSpecialInnerHoleLeader(ctx, ox, oy, H, scaledInnerDia); } // === 特征9: 硬度符号 === @@ -607,7 +702,7 @@ namespace CadParamPluging.Cad { const double extend = 5.0; // 截断线在轮廓上下各延长一点 const double frameMargin = 5.0; // 避免越过图框边界 - const double lineSpacing = 5.0; // 两根截断线间距5mm + const double lineSpacing = 3.0; // 两根截断线间距3mm var y0 = oy - extend; var y1 = oy + height + extend; @@ -797,18 +892,28 @@ namespace CadParamPluging.Cad { var Rp = outerDiaPrime / 2.0; var h = heightPrime; - - // 零件轮廓居中于锻件轮廓内 + + // 零件轮廓居中于锻件轮廓内 (垂直方向) var offsetY = (forgingHeight - h) / 2.0; var y0 = oy + offsetY; - // 绘制闭合方框(仅画外轮廓,不画内径线) + // 计算X方向的范围:从零件内半径到零件外半径 + // 如果没有内径,则默认从对称轴(ox)开始 + double minX = ox; + if (innerDiaPrime.HasValue && innerDiaPrime.Value > 0) + { + minX = ox + innerDiaPrime.Value / 2.0; + } + double maxX = ox + Rp; + + // 绘制闭合方框(对应截图中的黄色虚线框,即零件截面) var polyPart = new Polyline(); - polyPart.AddVertexAt(0, new Point2d(ox, y0), 0, 0, 0); - polyPart.AddVertexAt(1, new Point2d(ox + Rp, y0), 0, 0, 0); - polyPart.AddVertexAt(2, new Point2d(ox + Rp, y0 + h), 0, 0, 0); - polyPart.AddVertexAt(3, new Point2d(ox, y0 + h), 0, 0, 0); + polyPart.AddVertexAt(0, new Point2d(minX, y0), 0, 0, 0); + polyPart.AddVertexAt(1, new Point2d(maxX, y0), 0, 0, 0); + polyPart.AddVertexAt(2, new Point2d(maxX, y0 + h), 0, 0, 0); + polyPart.AddVertexAt(3, new Point2d(minX, y0 + h), 0, 0, 0); polyPart.Closed = true; // 闭合方框 + ctx.Style?.Apply(polyPart, DrawingStyleManager.Role.PartContour); ctx.Btr.AppendEntity(polyPart); ctx.Tr.AddNewlyCreatedDBObject(polyPart, true); diff --git a/Cad/TemplateDrawingService.cs b/Cad/TemplateDrawingService.cs index 2f48301..36d381b 100644 --- a/Cad/TemplateDrawingService.cs +++ b/Cad/TemplateDrawingService.cs @@ -522,7 +522,7 @@ namespace CadParamPluging.Cad var mt = new MText(); mt.Contents = ToMTextContents(renderedForCreation); mt.Location = insertPoint; - mt.TextHeight = 3.5; + mt.TextHeight = 3.0; mt.Attachment = AttachmentPoint.BottomLeft; // 关键:锚点在左下,文字向上延伸 diff --git a/UI/DrawingParamsForm.cs b/UI/DrawingParamsForm.cs index ba9e5ad..9dabdf7 100644 --- a/UI/DrawingParamsForm.cs +++ b/UI/DrawingParamsForm.cs @@ -6,6 +6,8 @@ using System.Globalization; using System.Linq; using System.Windows.Forms; using CadParamPluging.Common; +using Autodesk.AutoCAD.ApplicationServices; +using Autodesk.AutoCAD.EditorInput; namespace CadParamPluging.UI { @@ -409,7 +411,7 @@ namespace CadParamPluging.UI } var lbl = new Label { AutoSize = true, Text = labelText, TextAlign = ContentAlignment.MiddleLeft, Padding = new Padding(0, 6, 8, 6) }; - var ctrl = CreateControl(def); + var ctrl = CreateControl(def, controlKey); ctrl.Width = 260; if (!string.IsNullOrWhiteSpace(def.Hint)) @@ -640,17 +642,28 @@ namespace CadParamPluging.UI return bag; } - private Control CreateControl(ParamDefinition def) + private Control CreateControl(ParamDefinition def, string valueKey) { var initialValue = def.DefaultValue; // 优先使用传入的默认值 (loadedDefaults) if (_loadedDefaults != null) { - var val = _loadedDefaults.GetString(def.Key); + var val = _loadedDefaults.GetString(valueKey); if (val != null) // only if key exists { initialValue = val; + if (valueKey.StartsWith("Hardness")) + { + // Logging removed + } + } + else + { + if (valueKey.StartsWith("Hardness")) + { + // Logging removed + } } } // 确保不为 null @@ -694,7 +707,10 @@ namespace CadParamPluging.UI { cb.Items.AddRange(arr); var idx = Array.FindIndex(arr, x => string.Equals(x, initialValue, StringComparison.OrdinalIgnoreCase)); - cb.SelectedIndex = idx >= 0 ? idx : 0; + if (idx >= 0) + { + cb.SelectedIndex = idx; + } } if (!string.IsNullOrWhiteSpace(initialValue)) { @@ -771,6 +787,11 @@ namespace CadParamPluging.UI } bag.Set(key, value); + + if (key.StartsWith("Hardness")) + { + // Logging removed + } } Result = bag; @@ -780,22 +801,25 @@ namespace CadParamPluging.UI private static string ReadValue(Control ctrl, ParamDefinition def) { - switch (def.Type) + if (ctrl is CheckBox chk) { - case ParamValueType.Bool: - return (ctrl as CheckBox)?.Checked == true ? "true" : "false"; - case ParamValueType.Enum: - return ((ctrl as ComboBox)?.Text ?? string.Empty).Trim(); - case ParamValueType.Int: - case ParamValueType.Double: - if (ctrl is NumericUpDown num) - { - return num.Value.ToString(CultureInfo.InvariantCulture); - } - return string.Empty; - default: - return ((ctrl as TextBox)?.Text ?? string.Empty).Trim(); + return chk.Checked ? "true" : "false"; } + if (ctrl is NumericUpDown num) + { + return num.Value.ToString(CultureInfo.InvariantCulture); + } + if (ctrl is ComboBox cb) + { + // Handles both Enum type and String type rendered as ComboBox + return (cb.Text ?? string.Empty).Trim(); + } + if (ctrl is TextBox tb) + { + return (tb.Text ?? string.Empty).Trim(); + } + + return string.Empty; } } } diff --git a/UI/ParamDrawingPanel.cs b/UI/ParamDrawingPanel.cs index ff94e58..0057e33 100644 --- a/UI/ParamDrawingPanel.cs +++ b/UI/ParamDrawingPanel.cs @@ -339,6 +339,17 @@ namespace CadParamPluging.UI var frameWidth = frame.MaxPoint.X - frame.MinPoint.X; var frameHeight = frame.MaxPoint.Y - frame.MinPoint.Y; + // 确保 bag 中包含交付状态和工艺方法,以便 CalculateExpectedSize 正确判断示意图模式 + // tplParams.ProjectType = 交付状态(如"车加工"),tplParams.DrawingType = 工艺方法(如"轧制") + if (string.IsNullOrEmpty(bag.GetString("DeliveryStatus"))) + { + bag.Set("DeliveryStatus", tplParams.ProjectType ?? string.Empty); + } + if (string.IsNullOrEmpty(bag.GetString("ProcessMethod"))) + { + bag.Set("ProcessMethod", tplParams.DrawingType ?? string.Empty); + } + // 1. 获取预估图形尺寸 (不含标注的纯几何尺寸 + 预留边距) var expectedSize = FeatureDrivenDrawer.CalculateExpectedSize(bag, tplParams.SheetSize); @@ -350,6 +361,10 @@ namespace CadParamPluging.UI bool isOverflow = currentDrawW > frameWidth || currentDrawH > frameHeight; bool isTooSmall = currentDrawW < frameWidth * 0.3 && currentDrawH < frameHeight * 0.3; + // 调试日志 + AppendLog($"[尺寸检查] 白框尺寸: {frameWidth:F0}x{frameHeight:F0}, 预期图形(原始): {expectedSize.Width:F0}x{expectedSize.Height:F0}, 当前比例: 1:{(1/scaleFactor):F1}"); + AppendLog($"[尺寸检查] 预期图形(缩放后): {currentDrawW:F0}x{currentDrawH:F0}, 超出={isOverflow}, 过小={isTooSmall}"); + if (isOverflow || isTooSmall) { // 计算建议比例 (目标填充率 65%) @@ -485,7 +500,7 @@ namespace CadParamPluging.UI bagToSave.Set("DrawingType", tplParams.DrawingType); bagToSave.Set("SheetSize", tplParams.SheetSize); bagToSave.Set("SpecialCondition", tplParams.Scale); // tplParams.Scale 对应 _cbScale (特殊条件) - + DictionaryHelper.SaveParams(doc.Database, bagToSave); AppendLog("参数已保存到图纸内部数据中。"); }