using System; using System.Collections.Generic; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using CadParamPluging.Common; namespace CadParamPluging.Cad { public static class DiskRawFreeForgeDrawer { public static void Draw(CadContext ctx, ParamBag bag, Point3d center, double scaleFactor = 1.0) { if (ctx == null) throw new ArgumentNullException(nameof(ctx)); if (bag == null) throw new ArgumentNullException(nameof(bag)); var effectiveBag = scaleFactor < 1.0 ? ScaleParamBag(bag, scaleFactor) : bag; var db = ctx.Database; var tr = ctx.Transaction; var prevDb = HostApplicationServices.WorkingDatabase; HostApplicationServices.WorkingDatabase = db; BlockTableRecord btr; try { var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); } finally { HostApplicationServices.WorkingDatabase = prevDb; } var context = new FeatureDrivenDrawer.DrawingContext { Ctx = ctx, Bag = effectiveBag, OriginalBag = bag, Center = center, DeliveryStatus = "毛料态", StructuralFeature = "饼盘", ProcessMethod = "自由锻", Btr = btr, Style = new DrawingStyleManager(db, tr) }; DrawDiskFeatures(context); } private static void DrawDiskFeatures(FeatureDrivenDrawer.DrawingContext ctx) { var bag = ctx.Bag; var diameter = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameter); var height = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1); if (!diameter.HasValue || diameter.Value <= 0) return; if (!height.HasValue || height.Value <= 0) return; double ox = ctx.Center.X - diameter.Value / 2.0; double oy = ctx.Center.Y - height.Value / 2.0; double R = diameter.Value / 2.0; double H = height.Value; // 获取未注圆角半径 var unspecifiedFillet = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyUnspecifiedFilletRadiusMax); double r = unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0 ? unspecifiedFillet.Value : 0; // 安全检查:圆角不能超过宽或高的一半 double maxR = Math.Min(diameter.Value * 0.5, H * 0.5); r = Math.Min(r, maxR); // 绘制饼盘轮廓(俯视图为圆,侧视图为矩形,根据 R 控制圆角弧度) var poly = new Polyline(); if (r > 0.01) { var bulge = Math.Tan(Math.PI / 8.0); double xLeft = ox; double xRight = ox + diameter.Value; double yBottom = oy; double yTop = oy + H; poly.AddVertexAt(0, new Point2d(xLeft + r, yBottom), 0, 0, 0); poly.AddVertexAt(1, new Point2d(xRight - r, yBottom), bulge, 0, 0); poly.AddVertexAt(2, new Point2d(xRight, yBottom + r), 0, 0, 0); poly.AddVertexAt(3, new Point2d(xRight, yTop - r), bulge, 0, 0); poly.AddVertexAt(4, new Point2d(xRight - r, yTop), 0, 0, 0); poly.AddVertexAt(5, new Point2d(xLeft + r, yTop), bulge, 0, 0); poly.AddVertexAt(6, new Point2d(xLeft, yTop - r), 0, 0, 0); poly.AddVertexAt(7, new Point2d(xLeft, yBottom + r), bulge, 0, 0); } else { poly.AddVertexAt(0, new Point2d(ox, oy), 0, 0, 0); poly.AddVertexAt(1, new Point2d(ox + diameter.Value, oy), 0, 0, 0); poly.AddVertexAt(2, new Point2d(ox + diameter.Value, oy + H), 0, 0, 0); poly.AddVertexAt(3, new Point2d(ox, oy + H), 0, 0, 0); } poly.Closed = true; ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold); ctx.Btr.AppendEntity(poly); ctx.Tr.AddNewlyCreatedDBObject(poly, true); // 绘制中心线 (点划线) const double extendLine = 5.0; const double frameMargin = 5.0; var y0 = oy - extendLine; var y1 = oy + H + extendLine; try { var frameExtents = TemplateDrawingService.ComputeWhiteFrameExtents(ctx?.Ctx); if (frameExtents.HasValue) { var frame = frameExtents.Value; y0 = Math.Max(y0, frame.MinPoint.Y + frameMargin); y1 = Math.Min(y1, frame.MaxPoint.Y - frameMargin); } } catch { } if (y1 <= y0) { y0 = oy; y1 = oy + H; } var centerLine = new Line(new Point3d(ctx.Center.X, y0, 0), new Point3d(ctx.Center.X, y1, 0)); ctx.Style?.Apply(centerLine, DrawingStyleManager.Role.Centerline); ctx.Btr.AppendEntity(centerLine); ctx.Tr.AddNewlyCreatedDBObject(centerLine, true); var diaPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterPrime); var heightPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1Prime); // 直径标注 var diaTolPlus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterTolPlus); var diaTolMinus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterTolMinus); var diameterStr = bag.GetString(FeatureDrivenDrawer.KeyDiameter); var diaTolPlusStr = bag.GetString(FeatureDrivenDrawer.KeyDiameterTolPlus); var diaTolMinusStr = bag.GetString(FeatureDrivenDrawer.KeyDiameterTolMinus); var diaDimText = BuildDimensionText($"%%c{FormatDimNumber(diameter.Value, diameterStr)}", diaTolPlus, diaTolMinus, diaTolPlusStr, diaTolMinusStr); if (diaPrime.HasValue && diaPrime.Value > 0) { diaDimText += $"\\X(%%c{FormatDimNumber(diaPrime.Value)})"; } // 为避免标注界线悬空,根据 r 的存在小幅调整起点 AddLinearDim(ctx, new Point3d(ox, oy + r, 0), new Point3d(ox + diameter.Value, oy + r, 0), new Point3d(ctx.Center.X, oy - 20, 0), 0, diaDimText); // 高度标注 var htTolPlus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1TolPlus); var htTolMinus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1TolMinus); var heightStr = bag.GetString(FeatureDrivenDrawer.KeyHeight1); var htTolPlusStr = bag.GetString(FeatureDrivenDrawer.KeyHeight1TolPlus); var htTolMinusStr = bag.GetString(FeatureDrivenDrawer.KeyHeight1TolMinus); var htDimText = BuildDimensionText(FormatDimNumber(H, heightStr), htTolPlus, htTolMinus, htTolPlusStr, htTolMinusStr); if (heightPrime.HasValue && heightPrime.Value > 0) { htDimText += $"\\X({FormatDimNumber(heightPrime.Value)})"; } AddLinearDim(ctx, new Point3d(ox + diameter.Value - r, oy, 0), new Point3d(ox + diameter.Value - r, oy + H, 0), new Point3d(ox + diameter.Value + 20, ctx.Center.Y, 0), 90, htDimText); // 添加未注圆角文字标注 if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0) { DrawUnspecifiedFilletNote(ctx, ox, oy + H, R, diameter.Value, unspecifiedFillet.Value); } // 零件轮廓(如果有) if (diaPrime.HasValue && diaPrime.Value > 0 && heightPrime.HasValue && heightPrime.Value > 0) { DrawDiskPartContour(ctx, ox, oy, diameter.Value, H, diaPrime.Value, heightPrime.Value); } // 标刻内容 var markingText = bag.GetString(FeatureDrivenDrawer.KeyMarkingContent); if (!string.IsNullOrWhiteSpace(markingText)) { double flatHalfWidth = (diameter.Value / 2.0) - r; double offset = Math.Min(15.0, flatHalfWidth * 0.8); double xTarget = ctx.Center.X - offset; double yTarget = oy + H; FeatureDrivenDrawer.DrawSpecialHBLeaderToTop(ctx, xTarget, yTarget, markingText); } // 硬度符号 var hardnessVal = bag.GetString(FeatureDrivenDrawer.KeyHardness); if (!string.IsNullOrWhiteSpace(hardnessVal) && hardnessVal != "空") { double flatHalfWidth = (diameter.Value / 2.0) - r; double offset = Math.Min(15.0, flatHalfWidth * 0.8); double xHardness = ctx.Center.X + offset; double yHardness = oy; FeatureDrivenDrawer.DrawHardnessSymbol(ctx, xHardness, yHardness, hardnessVal); } } private static void DrawDiskPartContour(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double forgingDia, double forgingH, double partDia, double partH) { double offsetX = (forgingDia - partDia) / 2.0; double offsetY = (forgingH - partH) / 2.0; var polyPart = new Polyline(); polyPart.AddVertexAt(0, new Point2d(ox + offsetX, oy + offsetY), 0, 0, 0); polyPart.AddVertexAt(1, new Point2d(ox + offsetX + partDia, oy + offsetY), 0, 0, 0); polyPart.AddVertexAt(2, new Point2d(ox + offsetX + partDia, oy + offsetY + partH), 0, 0, 0); polyPart.AddVertexAt(3, new Point2d(ox + offsetX, oy + offsetY + partH), 0, 0, 0); polyPart.Closed = true; ctx.Style?.Apply(polyPart, DrawingStyleManager.Role.PartContour); ctx.Btr.AppendEntity(polyPart); ctx.Tr.AddNewlyCreatedDBObject(polyPart, true); } private static void DrawUnspecifiedFilletNote(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double R, double height, double filletR) { try { // Try to get original value to avoid scaling var val = filletR; if (ctx.OriginalBag != null) { double? original = ctx.OriginalBag.GetDoubleOrNull(FeatureDrivenDrawer.KeyUnspecifiedFilletRadiusMax); if (original.HasValue) val = original.Value; } var text = new DBText(); text.TextString = $"未注圆角半径R≤{val}"; // Position logic copied from FeatureDrivenDrawer (may need adjustment if generic logic was weird) // In FeatureDrivenDrawer: text.Position = new Point3d(ox + height + 10, oy + R + 15, 0); // ox, oy passed in were Top Left or similar? // In DrawDiskFeatures: DrawUnspecifiedFilletNote(ctx, ox, oy + H, R, diameter.Value, unspecifiedFillet.Value); // ox is Left X. oy+H is Top Y. // R passed is Radius (Diameter/2). height passed is Diameter (Circle diameter?). // Let's verify arguments in DrawDiskFeatures call: // DrawUnspecifiedFilletNote(ctx, ox, oy + H, R, diameter.Value, unspecifiedFillet.Value); // Arg3 (R) = R (Radius). Arg4 (height) = diameter. // Inside DrawUnspecifiedFilletNote: // Position = new Point3d(ox + height + 10, oy + R + 15, 0); // ox + diameter + 10 -> Right of the drawing. // oy + R + 15 -> Top Y + Radius + 15 -> Above the drawing? text.Position = new Point3d(ox + height + 10, oy + R + 15, 0); text.Height = 5; ctx.Style?.Apply(text, DrawingStyleManager.Role.Text); ctx.Btr.AppendEntity(text); ctx.Tr.AddNewlyCreatedDBObject(text, true); } catch { // ignore } } private static ParamBag ScaleParamBag(ParamBag original, double scaleFactor) { if (original == null || Math.Abs(scaleFactor - 1.0) < 0.000001) return original; var newBag = new ParamBag(); foreach(var k in original.GetKeys()) { var v = original.GetString(k); if (k.Contains("Diameter") || k.Contains("Length") || k.Contains("Radius") || k.Contains("Prime") || k.Contains("Height") || k.Contains("Thickness") || k.Contains("Size")) { if (double.TryParse(v, out var d)) { newBag.Set(k, (d * scaleFactor).ToString("0.###")); } else { newBag.Set(k, v); } } else { newBag.Set(k, v); } } return newBag; } // --- Helper Methods Copied for Isolation --- private static void AddLinearDim(FeatureDrivenDrawer.DrawingContext ctx, Point3d pt1, Point3d pt2, Point3d dimLinePt, double rotationDeg, string textOverride, Action customizer = null) { try { var prevDb = HostApplicationServices.WorkingDatabase; HostApplicationServices.WorkingDatabase = ctx.Db; try { double rotRad = rotationDeg * Math.PI / 180.0; var dim = new RotatedDimension(rotRad, pt1, pt2, dimLinePt, textOverride, ctx.Db.Dimstyle); try { dim.SetDatabaseDefaults(); } catch { } dim.ColorIndex = 3; if (!string.IsNullOrEmpty(textOverride)) { dim.DimensionText = textOverride; } try { dim.Normal = Vector3d.ZAxis; } catch { } TryApplyDimSizeOverrides(dim); TryApplyDimLayoutOverrides(dim); customizer?.Invoke(dim, ctx); ctx.Style?.Apply(dim, DrawingStyleManager.Role.Dimension); dim.ColorIndex = 3; ctx.Btr.AppendEntity(dim); ctx.Tr.AddNewlyCreatedDBObject(dim, true); try { dim.RecomputeDimensionBlock(true); } catch { } } finally { HostApplicationServices.WorkingDatabase = prevDb; } } catch { } } private static void TryApplyDimSizeOverrides(Dimension dim) { if (dim == null) return; TrySetDimProp(dim, "Dimtxt", 3.5); TrySetDimProp(dim, "Dimasz", 2.5); TrySetDimProp(dim, "Dimgap", 1.0); TrySetDimProp(dim, "Dimexe", 1.0); TrySetDimProp(dim, "Dimexo", 0.0); TrySetDimProp(dim, "Dimtofl", true); TrySetDimProp(dim, "Dimatfit", 3); TrySetDimProp(dim, "Dimtad", 1); TrySetDimProp(dim, "Dimclrd", 3); TrySetDimProp(dim, "Dimclre", 3); TrySetDimProp(dim, "Dimclrt", 3); } private static void TryApplyDimLayoutOverrides(Dimension dim) { if (dim == null) return; TrySetDimProp(dim, "Dimtih", false); TrySetDimProp(dim, "Dimtoh", false); TrySetDimProp(dim, "Dimse1", false); TrySetDimProp(dim, "Dimse2", false); } private static void TrySetDimProp(object obj, string propName, double value) { if (obj == null) return; try { var prop = obj.GetType().GetProperty(propName); if (prop != null && prop.CanWrite && prop.PropertyType == typeof(double)) prop.SetValue(obj, value, null); } catch { } } private static void TrySetDimProp(object obj, string propName, bool value) { if (obj == null) return; try { var prop = obj.GetType().GetProperty(propName); if (prop != null && prop.CanWrite && prop.PropertyType == typeof(bool)) prop.SetValue(obj, value, null); } catch { } } private static void TrySetDimProp(object obj, string propName, int value) { if (obj == null) return; try { var prop = obj.GetType().GetProperty(propName); if (prop != null && prop.CanWrite && prop.PropertyType == typeof(int)) prop.SetValue(obj, value, null); } catch { } } private static string FormatDimNumber(double value, string rawInput = null) { try { if (!string.IsNullOrWhiteSpace(rawInput) && double.TryParse(rawInput, out var d) && Math.Abs(d - value) < 0.000001) { int decIndex = rawInput.IndexOf('.'); int decimals = 0; if (decIndex >= 0) { decimals = rawInput.Length - decIndex - 1; } if (decimals == 0) return value.ToString("0"); return value.ToString("0." + new string('0', decimals)); } string str = value.ToString("0.##########"); int decimalIndex = str.IndexOf('.'); if (decimalIndex < 0) { return str; } int autoDecimals = str.Length - decimalIndex - 1; if (autoDecimals == 0) return str; string format = "0." + new string('0', autoDecimals); return value.ToString(format); } catch { return value.ToString(); } } private static string BuildDimensionText(string baseText, double? tolPlus, double? tolMinus, string tolPlusStr = null, string tolMinusStr = null) { if (!tolPlus.HasValue && !tolMinus.HasValue) { return baseText; } bool isSymmetrical = false; if (tolPlus.HasValue && tolMinus.HasValue) { if (Math.Abs(Math.Abs(tolPlus.Value) - Math.Abs(tolMinus.Value)) < 0.000001) { isSymmetrical = true; } } if (isSymmetrical) { var val = Math.Abs(tolPlus.Value); return $"{baseText}%%p{FormatDimNumber(val, tolPlusStr)}"; } const double tolScale = 0.7; var plusStr = string.Empty; var minusStr = string.Empty; if (tolPlus.HasValue) { plusStr = tolPlus.Value >= 0 ? $"+{FormatDimNumber(tolPlus.Value, tolPlusStr)}" : $"{FormatDimNumber(tolPlus.Value, tolPlusStr)}"; } if (tolMinus.HasValue) { double vm = tolMinus.Value; string formattedVal = FormatDimNumber(Math.Abs(vm), tolMinusStr); if (Math.Abs(vm) < 0.000001) { minusStr = formattedVal; } else { minusStr = $"-{formattedVal}"; } } if (tolPlus.HasValue && tolMinus.HasValue) { return $"{baseText} {{\\H{tolScale}x;\\S{plusStr}^{minusStr};}}"; } var single = tolPlus.HasValue ? plusStr : minusStr; return $"{baseText} {{\\H{tolScale}x;{single}}}"; } } }