From 03de14489f9e4310fd43de607007d5376671c1dd Mon Sep 17 00:00:00 2001 From: sladro Date: Tue, 3 Feb 2026 17:06:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=AD=E5=BF=83=E5=86=B2=E5=AD=94=E5=AE=8C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RingRawFreeForgeCenterPunchDrawer.cs | 382 ++++++++++++++++++ .../RingRawFreeForgeCenterPunchGenerator.cs | 22 + Cad/Drawers/TemplateDrawingRegistry.cs | 3 + CadParamPluging.csproj | 2 + Common/TemplateSchemaDefaults.cs | 35 ++ 5 files changed, 444 insertions(+) create mode 100644 Cad/Drawers/RingRawFreeForgeCenterPunchDrawer.cs create mode 100644 Cad/Drawers/RingRawFreeForgeCenterPunchGenerator.cs diff --git a/Cad/Drawers/RingRawFreeForgeCenterPunchDrawer.cs b/Cad/Drawers/RingRawFreeForgeCenterPunchDrawer.cs new file mode 100644 index 0000000..c1754b0 --- /dev/null +++ b/Cad/Drawers/RingRawFreeForgeCenterPunchDrawer.cs @@ -0,0 +1,382 @@ +using System; +using Autodesk.AutoCAD.DatabaseServices; +using Autodesk.AutoCAD.Geometry; +using CadParamPluging.Common; + +namespace CadParamPluging.Cad.Drawers +{ + public static class RingRawFreeForgeCenterPunchDrawer + { + 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)); + + // Apply scaling + 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; + } + + // Construct DrawingContext + // Note: SpecialCondition needs to be "中心冲孔" + var context = new FeatureDrivenDrawer.DrawingContext + { + Ctx = ctx, + Bag = effectiveBag, + OriginalBag = bag, + Center = center, + DeliveryStatus = "毛料态", + StructuralFeature = "环形", + SpecialCondition = "中心冲孔", + ProcessMethod = "自由锻", + Btr = btr, + // We need to instantiate DrawingStyleManager. Accessing internal constructor via reflection or if it's internal to assembly we are fine. + // Assuming same assembly. + Style = new DrawingStyleManager(db, tr) + }; + + DrawCore(context); + } + + private static ParamBag ScaleParamBag(ParamBag original, double scaleFactor) + { + if (original == null || scaleFactor <= 0 || (Math.Abs(scaleFactor - 1.0) < 1e-6)) + { + return original; + } + + var scaled = new ParamBag(); + + // 需要缩放的尺寸参数Key列表 + var sizeKeys = new System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) + { + // 环形参数 + FeatureDrivenDrawer.KeyOuterDiameter1, FeatureDrivenDrawer.KeyInnerDiameter2, FeatureDrivenDrawer.KeyHeight1, + FeatureDrivenDrawer.KeyOuterDiameter1Prime, FeatureDrivenDrawer.KeyInnerDiameter2Prime, FeatureDrivenDrawer.KeyHeight1Prime, + FeatureDrivenDrawer.KeyMinWallThickness, + // 圆角参数 + FeatureDrivenDrawer.KeyUnspecifiedFilletRadiusMax, FeatureDrivenDrawer.KeyInnerRadiusMax, + + // 包含公差参数以保持一致性 + FeatureDrivenDrawer.KeyOuterDiameter1TolPlus, FeatureDrivenDrawer.KeyOuterDiameter1TolMinus, + FeatureDrivenDrawer.KeyInnerDiameter2TolPlus, FeatureDrivenDrawer.KeyInnerDiameter2TolMinus, + FeatureDrivenDrawer.KeyHeight1TolPlus, FeatureDrivenDrawer.KeyHeight1TolMinus + }; + + foreach (var key in original.GetKeys()) + { + var value = original.GetString(key); + + if (sizeKeys.Contains(key)) + { + // 尝试解析为数值并缩放 + if (double.TryParse(value, out var numValue)) + { + var scaledValue = numValue * scaleFactor; + // 保留适当的小数位数,避免精度问题 + scaled.Set(key, scaledValue.ToString("F4")); + } + else + { + scaled.Set(key, value); + } + } + else + { + // 非尺寸参数直接复制 + scaled.Set(key, value); + } + } + + return scaled; + } + + private static void DrawCore(FeatureDrivenDrawer.DrawingContext ctx) + { + var bag = ctx.Bag; + var outerDia = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyOuterDiameter1); + var height = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1); + + if (!outerDia.HasValue || !height.HasValue) return; + + double W = outerDia.Value; + double H = height.Value; + double ox = ctx.Center.X - W / 2.0; + double oy = ctx.Center.Y - H / 2.0; + + // Unconditionally retrieve variables for Part Contour (Prime parameters) + var outerDiaPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyOuterDiameter1Prime); + var innerDiaPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyInnerDiameter2Prime); + var heightPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1Prime); + + // Radii + var outerFilletR = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyUnspecifiedFilletRadiusMax) ?? 0; + var innerFilletR = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyInnerRadiusMax) ?? 0; + + // Pre-calculate inner hole parameters + var innerDia = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyInnerDiameter2); + var innerTolPlus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyInnerDiameter2TolPlus); + var innerTolMinus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyInnerDiameter2TolMinus); + double? xInnerLeft = null; + double? xInnerRight = null; + + // Full Section: Draw Contour with Fillet for both sides + if (innerDia.HasValue && innerDia.Value > 0 && innerDia.Value < W) + { + double xInnerLeftVal = ctx.Center.X - innerDia.Value / 2.0; + double xInnerRightVal = ctx.Center.X + innerDia.Value / 2.0; + + // Draw Left Section Contour (Outer Edge: ox, Inner Edge: xInnerLeftVal) + // Left Side of Left Section is Outer -> outerFilletR + // Right Side of Left Section is Inner -> innerFilletR + DrawSectionWithAsymmetricFillets(ctx, ox, xInnerLeftVal, oy, H, outerFilletR, innerFilletR); + + // Draw Right Section Contour (Inner Edge: xInnerRightVal, Outer Edge: ox + W) + // Left Side of Right Section is Inner -> innerFilletR + // Right Side of Right Section is Outer -> outerFilletR + DrawSectionWithAsymmetricFillets(ctx, xInnerRightVal, ox + W, oy, H, innerFilletR, outerFilletR); + + // Draw Connecting Lines (Hole Back View) - Top and Bottom + // Extend into the inner fillet radius + + double lineStart = xInnerLeftVal - innerFilletR; + double lineEnd = xInnerRightVal + innerFilletR; + + var connectingLineTop = new Line(new Point3d(lineStart, oy + H, 0), new Point3d(lineEnd, oy + H, 0)); + connectingLineTop.ColorIndex = 7; // White + ctx.Btr.AppendEntity(connectingLineTop); + ctx.Tr.AddNewlyCreatedDBObject(connectingLineTop, true); + + var connectingLineBottom = new Line(new Point3d(lineStart, oy, 0), new Point3d(lineEnd, oy, 0)); + connectingLineBottom.ColorIndex = 7; // White + ctx.Btr.AppendEntity(connectingLineBottom); + ctx.Tr.AddNewlyCreatedDBObject(connectingLineBottom, true); + + // Adjust Inner Dim to attach to vertical wall (offset by innerFilletR) + FeatureDrivenDrawer.DrawInnerDiameterDimension(ctx, xInnerLeftVal, xInnerRightVal, oy + innerFilletR, innerDia.Value, innerTolPlus, innerTolMinus, innerDiaPrime); + + // Store values for later use in dimensions/notes + xInnerRight = xInnerRightVal; + xInnerLeft = xInnerLeftVal; + } + else + { + // Fallback if no inner hole (should not happen for a ring but safe to keep) + // FeatureDrivenDrawer.DrawForgingOuterContour(ctx, ox, oy, W, H); + } + + // 1.1 Centerline + // 改为竖直中心线,两头超出3mm + var cx = ctx.Center.X; + var vLine = new Line(new Point3d(cx, oy - 3, 0), new Point3d(cx, oy + H + 3, 0)); + ctx.Style?.Apply(vLine, DrawingStyleManager.Role.Centerline); + ctx.Btr.AppendEntity(vLine); + ctx.Tr.AddNewlyCreatedDBObject(vLine, true); + + // 2. Outer Diameter Dimension + var outerTolPlus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyOuterDiameter1TolPlus); + var outerTolMinus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyOuterDiameter1TolMinus); + // Adjust Y by outerFilletR + FeatureDrivenDrawer.DrawOuterDiameterDimension(ctx, ox, oy + outerFilletR, W, W, outerTolPlus, outerTolMinus, outerDiaPrime); + + // 5. Height Dimension + var displayBag = ctx.OriginalBag ?? ctx.Bag; + + var displayHeightVal = displayBag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1) ?? H; + var displayHeightStr = displayBag.GetString(FeatureDrivenDrawer.KeyHeight1); + + var displayTolPlus = displayBag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1TolPlus); + var displayTolMinus = displayBag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1TolMinus); + var displayTolPlusStr = displayBag.GetString(FeatureDrivenDrawer.KeyHeight1TolPlus); + var displayTolMinusStr = displayBag.GetString(FeatureDrivenDrawer.KeyHeight1TolMinus); + + var displayHeightPrime = displayBag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1Prime); + + var heightBaseText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(displayHeightVal, displayHeightStr), displayTolPlus, displayTolMinus, displayTolPlusStr, displayTolMinusStr); + var heightDimText = heightBaseText; + + if (displayHeightPrime.HasValue && displayHeightPrime.Value > 0) + { + heightDimText = heightBaseText + $"\\X({FeatureDrivenDrawer.FormatDimNumber(displayHeightPrime.Value)})"; + } + + // Custom Height Dimension Logic to ensure "Closed" look with fillets + // Move X definition points inward by outerFilletR + double dimX = ox + W - outerFilletR; + + FeatureDrivenDrawer.AddLinearDim( + ctx, + new Point3d(dimX, oy, 0), + new Point3d(dimX, oy + H, 0), + new Point3d(ox + W + 25, oy + H / 2, 0), + 90, + heightDimText); + + // 7. Min Wall Thickness + var minWallThickness = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyMinWallThickness); + if (minWallThickness.HasValue && minWallThickness.Value > 0 && xInnerRight.HasValue) + { + FeatureDrivenDrawer.DrawMinWallThicknessNote(ctx, xInnerRight.Value, ox + W, oy, minWallThickness.Value); + } + + // 8. Part Contour (Machined Parameters present) + if (outerDiaPrime.HasValue && outerDiaPrime.Value > 0 && heightPrime.HasValue && heightPrime.Value > 0) + { + FeatureDrivenDrawer.DrawPartContour(ctx, ctx.Center, outerDiaPrime.Value, innerDiaPrime, heightPrime.Value); + } + + // 9. Hardness Symbol + var hardnessVal = bag.GetString(FeatureDrivenDrawer.KeyHardness); + if (!string.IsNullOrWhiteSpace(hardnessVal)) + { + if (xInnerRight.HasValue) + { + double xStart = (xInnerRight.Value + ox + W) / 2.0; + double yStart = oy; + FeatureDrivenDrawer.DrawHardnessSymbol(ctx, xStart, yStart); + } + else + { + FeatureDrivenDrawer.DrawHardnessSymbol(ctx, ox + W / 2.0, oy); + } + } + + // 10. Marking Content + var markingText = bag.GetString(FeatureDrivenDrawer.KeyMarkingContent); + if (!string.IsNullOrWhiteSpace(markingText)) + { + if (xInnerRight.HasValue) + { + double xTarget = (xInnerRight.Value + ox + W) / 2.0; + double yTarget = oy + H; + FeatureDrivenDrawer.DrawSpecialHBLeaderToTop(ctx, xTarget, yTarget, markingText); + } + else + { + FeatureDrivenDrawer.DrawSpecialHBLeaderToTop(ctx, ox + W / 2.0, oy + H, markingText); + } + } + } + + /// + /// Draws a section rectangle with potentially different fillet radii for left and right sides. + /// Also handles hatching. + /// rLeft: Radius for Top-Left and Bottom-Left corners. + /// rRight: Radius for Top-Right and Bottom-Right corners. + /// + private static void DrawSectionWithAsymmetricFillets(FeatureDrivenDrawer.DrawingContext ctx, double xLeft, double xRight, double yBottom, double height, double rLeft, double rRight) + { + var yTop = yBottom + height; + var width = xRight - xLeft; + + // Constrain radii + var maxR = Math.Min(width * 0.5, height * 0.5); + var rl = Math.Min(rLeft, maxR); + var rr = Math.Min(rRight, maxR); + if (rl < 0) rl = 0; + if (rr < 0) rr = 0; + + // If radii are negligible, draw rectangle + if (rl <= 0.01 && rr <= 0.01) + { + // ... (Logic from FeatureDrivenDrawer but combined) + // Use reuse logic or just implement simply. + // Simple Polyline + var simplePoly = new Polyline(); + simplePoly.AddVertexAt(0, new Point2d(xLeft, yBottom), 0, 0, 0); + simplePoly.AddVertexAt(1, new Point2d(xRight, yBottom), 0, 0, 0); + simplePoly.AddVertexAt(2, new Point2d(xRight, yTop), 0, 0, 0); + simplePoly.AddVertexAt(3, new Point2d(xLeft, yTop), 0, 0, 0); + simplePoly.Closed = true; + + ctx.Style?.Apply(simplePoly, DrawingStyleManager.Role.OutlineBold); + ctx.Btr.AppendEntity(simplePoly); + ctx.Tr.AddNewlyCreatedDBObject(simplePoly, true); + + // Hatch + CreateHatchForPolyline(ctx, simplePoly); + return; + } + + var bulge = Math.Tan(Math.PI / 8.0); + + var poly = new Polyline(); + + // 1. Bottom Line Start (xLeft + rl) + poly.AddVertexAt(0, new Point2d(xLeft + rl, yBottom), 0, 0, 0); + + // 2. Bottom Line End / Bottom-Right Arc Start (xRight - rr) + poly.AddVertexAt(1, new Point2d(xRight - rr, yBottom), bulge, 0, 0); + + // 3. Right Line Start / Bottom-Right Arc End (xRight, yBottom + rr) + poly.AddVertexAt(2, new Point2d(xRight, yBottom + rr), 0, 0, 0); + + // 4. Right Line End / Top-Right Arc Start (xRight, yTop - rr) + poly.AddVertexAt(3, new Point2d(xRight, yTop - rr), bulge, 0, 0); + + // 5. Top Line Start / Top-Right Arc End (xRight - rr, yTop) + poly.AddVertexAt(4, new Point2d(xRight - rr, yTop), 0, 0, 0); + + // 6. Top Line End / Top-Left Arc Start (xLeft + rl, yTop) + poly.AddVertexAt(5, new Point2d(xLeft + rl, yTop), bulge, 0, 0); + + // 7. Left Line Start / Top-Left Arc End (xLeft, yTop - rl) + poly.AddVertexAt(6, new Point2d(xLeft, yTop - rl), 0, 0, 0); + + // 8. Left Line End / Bottom-Left Arc Start (xLeft, yBottom + rl) + poly.AddVertexAt(7, new Point2d(xLeft, yBottom + rl), bulge, 0, 0); + + poly.Closed = true; + + ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold); + ctx.Btr.AppendEntity(poly); + ctx.Tr.AddNewlyCreatedDBObject(poly, true); + + // Hatch + CreateHatchForPolyline(ctx, poly); + } + + private static void CreateHatchForPolyline(FeatureDrivenDrawer.DrawingContext ctx, Polyline boundary) + { + try + { + var hatch = new Hatch(); + hatch.SetDatabaseDefaults(); + hatch.Normal = new Vector3d(0, 0, 1); + hatch.Elevation = 0.0; + + ctx.Btr.AppendEntity(hatch); + ctx.Tr.AddNewlyCreatedDBObject(hatch, true); + + hatch.SetHatchPattern(HatchPatternType.PreDefined, "ANSI31"); + hatch.PatternScale = 10; + hatch.PatternAngle = 0; + hatch.Associative = false; + ctx.Style?.Apply(hatch, DrawingStyleManager.Role.Hatch); + + var ids = new ObjectIdCollection(); + ids.Add(boundary.ObjectId); + hatch.AppendLoop(HatchLoopTypes.External, ids); + hatch.EvaluateHatch(true); + } + catch + { + // ignore hatch errors + } + } + } +} diff --git a/Cad/Drawers/RingRawFreeForgeCenterPunchGenerator.cs b/Cad/Drawers/RingRawFreeForgeCenterPunchGenerator.cs new file mode 100644 index 0000000..6b1cb43 --- /dev/null +++ b/Cad/Drawers/RingRawFreeForgeCenterPunchGenerator.cs @@ -0,0 +1,22 @@ +using Autodesk.AutoCAD.Geometry; +using CadParamPluging.Common; +using CadParamPluging.Domain.Models; +using CadParamPluging.Cad.Drawers; + +namespace CadParamPluging.Cad +{ + public class RingRawFreeForgeCenterPunchGenerator : ITemplateDrawingGenerator + { + public string TemplateKey => TemplateKeyBuilder.Build("毛料态", "自由锻", "环形", "中心冲孔"); + + public FeatureDrivenDrawer.ExpectedDrawingSize CalculateExpectedSize(ParamBag bag, TemplateParams templateParams) + { + return FeatureDrivenDrawer.CalculateExpectedSize(bag, "环形"); + } + + public void Draw(CadContext ctx, ParamBag bag, TemplateParams templateParams, Point3d center, double scaleFactor) + { + RingRawFreeForgeCenterPunchDrawer.Draw(ctx, bag, center, scaleFactor); + } + } +} diff --git a/Cad/Drawers/TemplateDrawingRegistry.cs b/Cad/Drawers/TemplateDrawingRegistry.cs index b033693..b2f379b 100644 --- a/Cad/Drawers/TemplateDrawingRegistry.cs +++ b/Cad/Drawers/TemplateDrawingRegistry.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using CadParamPluging.Cad.Drawers; // Add this just in case, though they seem to be in .Cad + namespace CadParamPluging.Cad { @@ -15,6 +17,7 @@ namespace CadParamPluging.Cad Register(new BlockRawFreeForgeRoundHeadGenerator()); Register(new RingRawFreeForgeNonCenterPunchGenerator()); Register(new BlockRawFreeForgeNoRoundHeadGenerator()); + Register(new RingRawFreeForgeCenterPunchGenerator()); } public static bool TryResolve(string templateKey, out ITemplateDrawingGenerator generator) diff --git a/CadParamPluging.csproj b/CadParamPluging.csproj index 680b4ba..62f66f3 100644 --- a/CadParamPluging.csproj +++ b/CadParamPluging.csproj @@ -89,6 +89,8 @@ + + diff --git a/Common/TemplateSchemaDefaults.cs b/Common/TemplateSchemaDefaults.cs index 3f9f198..8286793 100644 --- a/Common/TemplateSchemaDefaults.cs +++ b/Common/TemplateSchemaDefaults.cs @@ -183,6 +183,41 @@ namespace CadParamPluging.Common PartOwnershipConfigured = true }); + // 模板九:交付状态=毛料态, 工艺方法=自由锻, 结构特征=环形, 特殊条件=中心冲孔 + schemas.Items.Add(new TemplateSchemaDefinition + { + ProjectType = "毛料态", + DrawingType = "自由锻", + SheetSize = "环形", + Scale = "中心冲孔", + DisplayName = "环形(毛料态/自由锻/中心冲孔)", + SelectedParamKeys = new List + { + "OuterDiameter1", + "OuterDiameter1TolPlus", + "OuterDiameter1TolMinus", + "InnerDiameter2", + "InnerDiameter2TolPlus", + "InnerDiameter2TolMinus", + "Height1", + "Height1TolPlus", + "Height1TolMinus", + "MinWallThickness", + "UnspecifiedFilletRadiusMax", // 未注圆角半径R≤ + "InnerRadiusMax", // 内径半径R≤ + "OuterDiameter1Prime", + "InnerDiameter2Prime", + "Height1Prime" + }, + SelectedPartParamKeys = new List + { + "OuterDiameter1Prime", + "InnerDiameter2Prime", + "Height1Prime" + }, + PartOwnershipConfigured = true + }); + schemas.Normalize(); return schemas; }