diff --git a/Cad/Drawers/RingRawRollingGenerator.cs b/Cad/Drawers/RingRawRollingGenerator.cs index a4d785d..5574070 100644 --- a/Cad/Drawers/RingRawRollingGenerator.cs +++ b/Cad/Drawers/RingRawRollingGenerator.cs @@ -1,11 +1,84 @@ +using System; +using Autodesk.AutoCAD.Geometry; using CadParamPluging.Common; +using CadParamPluging.Domain.Models; namespace CadParamPluging.Cad { - public sealed class RingRawRollingGenerator : TemplateDrawingGeneratorBase + public sealed class RingRawRollingGenerator : ITemplateDrawingGenerator { public static readonly string Key = TemplateKeyBuilder.Build("毛料态", "轧制", "环形", "无"); + private const string MachinedStatus = "车加工"; - public override string TemplateKey => Key; + public string TemplateKey => Key; + + public FeatureDrivenDrawer.ExpectedDrawingSize CalculateExpectedSize(ParamBag bag, TemplateParams templateParams) + { + var workingBag = CloneBagWithMachinedStatus(bag, templateParams); + return FeatureDrivenDrawer.CalculateExpectedSize(workingBag, templateParams?.SheetSize); + } + + public void Draw(CadContext ctx, ParamBag bag, TemplateParams templateParams, Point3d center, double scaleFactor) + { + if (ctx == null) + { + throw new ArgumentNullException(nameof(ctx)); + } + + if (templateParams == null) + { + throw new ArgumentNullException(nameof(templateParams)); + } + + var workingBag = CloneBagWithMachinedStatus(bag, templateParams); + var drawParams = CreateMachinedTemplateParams(templateParams); + + FeatureDrivenDrawer.DrawRingRollingWithUnspecifiedFillet( + ctx, + workingBag, + drawParams.ProjectType, + drawParams.SheetSize, + drawParams.Scale, + drawParams.DrawingType, + center, + scaleFactor); + } + + private static ParamBag CloneBagWithMachinedStatus(ParamBag source, TemplateParams templateParams) + { + var clone = new ParamBag(); + if (source?.Items != null) + { + foreach (var item in source.Items) + { + if (item == null) + { + continue; + } + + clone.Items.Add(new ParamValue { Key = item.Key, Value = item.Value }); + } + } + + clone.Set("DeliveryStatus", MachinedStatus); + if (!string.IsNullOrWhiteSpace(templateParams?.DrawingType) + && string.IsNullOrWhiteSpace(clone.GetString("ProcessMethod"))) + { + clone.Set("ProcessMethod", templateParams.DrawingType); + } + + return clone; + } + + private static TemplateParams CreateMachinedTemplateParams(TemplateParams templateParams) + { + return new TemplateParams + { + ProjectType = MachinedStatus, + DrawingType = templateParams?.DrawingType, + SheetSize = templateParams?.SheetSize, + Scale = templateParams?.Scale + }; + } } } diff --git a/Cad/FeatureDrivenDrawer.cs b/Cad/FeatureDrivenDrawer.cs index 41fa3a2..009c426 100644 --- a/Cad/FeatureDrivenDrawer.cs +++ b/Cad/FeatureDrivenDrawer.cs @@ -312,6 +312,62 @@ namespace CadParamPluging.Cad } } + public static void DrawRingRollingWithUnspecifiedFillet(CadContext ctx, ParamBag bag, string deliveryStatus, string structuralFeature, + string specialCondition = null, string processMethod = null, Point3d? center = null, double scaleFactor = 1.0) + { + if (ctx == null) throw new ArgumentNullException(nameof(ctx)); + if (bag == null) throw new ArgumentNullException(nameof(bag)); + + if (!IsRing(structuralFeature) + || string.IsNullOrWhiteSpace(processMethod) + || processMethod.IndexOf("轧制", StringComparison.OrdinalIgnoreCase) < 0) + { + Draw(ctx, bag, deliveryStatus, structuralFeature, specialCondition, processMethod, center, scaleFactor); + return; + } + + 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 DrawingContext + { + Ctx = ctx, + Bag = effectiveBag, + OriginalBag = bag, + Center = center ?? Point3d.Origin, + DeliveryStatus = deliveryStatus, + StructuralFeature = structuralFeature, + SpecialCondition = specialCondition, + ProcessMethod = processMethod, + Btr = btr, + Style = new DrawingStyleManager(db, tr) + }; + + var outerDia = effectiveBag.GetDoubleOrNull(KeyOuterDiameter1); + var height = effectiveBag.GetDoubleOrNull(KeyHeight1); + if (!outerDia.HasValue || outerDia.Value <= 0 || !height.HasValue || height.Value <= 0) + { + return; + } + + DrawRingFeaturesHalfWithUnspecifiedFillet(context, outerDia.Value, height.Value); + } + #endregion #region 结构特征判断 @@ -383,6 +439,16 @@ namespace CadParamPluging.Cad /// 轧制工艺 - 只画右半边图 /// private static void DrawRingFeaturesHalf(DrawingContext ctx, double outerDia, double height) + { + DrawRingFeaturesHalfCore(ctx, outerDia, height, false); + } + + private static void DrawRingFeaturesHalfWithUnspecifiedFillet(DrawingContext ctx, double outerDia, double height) + { + DrawRingFeaturesHalfCore(ctx, outerDia, height, true); + } + + private static void DrawRingFeaturesHalfCore(DrawingContext ctx, double outerDia, double height, bool applyUnspecifiedFillet) { var bag = ctx.Bag; @@ -477,7 +543,15 @@ namespace CadParamPluging.Cad } // === 特征1: 锻件外轮廓 === - DrawForgingOuterContourHalf(ctx, ox, oy, visualOuterR, H); + var unspecifiedFillet = bag.GetDoubleOrNull(KeyUnspecifiedFilletRadiusMax); + if (applyUnspecifiedFillet && unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0) + { + DrawForgingOuterContourHalf(ctx, ox, oy, visualOuterR, H, unspecifiedFillet); + } + else + { + DrawForgingOuterContourHalf(ctx, ox, oy, visualOuterR, H, null); + } // === 特征1.1: 对称轴 === DrawRingSymmetryAxis(ctx, ox, oy, H); @@ -508,9 +582,20 @@ namespace CadParamPluging.Cad { DrawInnerFilletsHalf(ctx, xInnerRight.Value, oy, H, innerRadiusMax.Value); } + else if (applyUnspecifiedFillet && unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0) + { + DrawInnerFilletsHalfInward(ctx, xInnerRight.Value, oy, H, unspecifiedFillet.Value); + } // === 特征4.1: 剖面线 === - DrawRingSectionHatch(ctx, xInnerRight.Value, ox + visualOuterR, oy, H); + if (applyUnspecifiedFillet && unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0) + { + DrawRingSectionHatchWithFillet(ctx, xInnerRight.Value, ox + visualOuterR, oy, H, unspecifiedFillet.Value); + } + else + { + DrawRingSectionHatch(ctx, xInnerRight.Value, ox + visualOuterR, oy, H); + } // 剖面左侧竖线 DrawSectionInnerBoundaryBold(ctx, xInnerRight.Value, oy, H); @@ -522,7 +607,6 @@ namespace CadParamPluging.Cad 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, visualOuterR, unspecifiedFillet.Value); @@ -710,8 +794,32 @@ namespace CadParamPluging.Cad /// /// 轧制:绘制右半边外轮廓(开口多段线) /// - private static void DrawForgingOuterContourHalf(DrawingContext ctx, double ox, double oy, double radius, double height) + private static void DrawForgingOuterContourHalf(DrawingContext ctx, double ox, double oy, double radius, double height, double? filletRadius) { + var rawR = filletRadius.GetValueOrDefault(); + if (rawR > 0) + { + var maxR = Math.Min(radius * 0.5, height * 0.5); + var r = Math.Min(rawR, maxR); + if (r > 0.01) + { + var bulge = Math.Tan(Math.PI / 8.0); + var polyFillet = new Polyline(); + polyFillet.AddVertexAt(0, new Point2d(ox, oy), 0, 0, 0); + polyFillet.AddVertexAt(1, new Point2d(ox + radius - r, oy), bulge, 0, 0); + polyFillet.AddVertexAt(2, new Point2d(ox + radius, oy + r), 0, 0, 0); + polyFillet.AddVertexAt(3, new Point2d(ox + radius, oy + height - r), bulge, 0, 0); + polyFillet.AddVertexAt(4, new Point2d(ox + radius - r, oy + height), 0, 0, 0); + polyFillet.AddVertexAt(5, new Point2d(ox, oy + height), 0, 0, 0); + polyFillet.Closed = false; + + ctx.Style?.Apply(polyFillet, DrawingStyleManager.Role.OutlineBold); + ctx.Btr.AppendEntity(polyFillet); + ctx.Tr.AddNewlyCreatedDBObject(polyFillet, true); + return; + } + } + // 右半边轮廓:下边、右边、上边(左边开口) var poly = new Polyline(); poly.AddVertexAt(0, new Point2d(ox, oy), 0, 0, 0); // 左下(对称轴下端) @@ -879,6 +987,15 @@ namespace CadParamPluging.Cad DrawFilletArc(ctx, xInnerRight - filletR, yBottom + filletR, filletR, Math.PI * 1.5, Math.PI * 2); } + private static void DrawInnerFilletsHalfInward(DrawingContext ctx, double xInnerRight, double yBottom, double height, double filletR) + { + var yTop = yBottom + height; + + // 仅绘制内孔右侧边界的圆角,圆角朝向剖面内部(右侧) + DrawFilletArc(ctx, xInnerRight + filletR, yTop - filletR, filletR, Math.PI / 2, Math.PI); + DrawFilletArc(ctx, xInnerRight + filletR, yBottom + filletR, filletR, Math.PI, Math.PI * 1.5); + } + /// /// 轧制:高度标注(在右侧) /// @@ -1237,6 +1354,75 @@ namespace CadParamPluging.Cad } } + private static void DrawRingSectionHatchWithFillet(DrawingContext ctx, double xInnerRight, double xOuterRight, double yBottom, double height, double filletR) + { + if (xOuterRight <= xInnerRight) + { + return; + } + + var availableWidth = xOuterRight - xInnerRight; + var maxR = Math.Min(availableWidth * 0.5, height * 0.5); + var r = Math.Min(filletR, maxR); + if (r <= 0.01) + { + DrawRingSectionHatch(ctx, xInnerRight, xOuterRight, yBottom, height); + return; + } + + try + { + var yTop = yBottom + height; + var bulge = Math.Tan(Math.PI / 8.0); + + var boundary = new Polyline(); + boundary.AddVertexAt(0, new Point2d(xInnerRight + r, yBottom), 0, 0, 0); + boundary.AddVertexAt(1, new Point2d(xOuterRight - r, yBottom), bulge, 0, 0); + boundary.AddVertexAt(2, new Point2d(xOuterRight, yBottom + r), 0, 0, 0); + boundary.AddVertexAt(3, new Point2d(xOuterRight, yTop - r), bulge, 0, 0); + boundary.AddVertexAt(4, new Point2d(xOuterRight - r, yTop), 0, 0, 0); + boundary.AddVertexAt(5, new Point2d(xInnerRight + r, yTop), bulge, 0, 0); + boundary.AddVertexAt(6, new Point2d(xInnerRight, yTop - r), 0, 0, 0); + boundary.AddVertexAt(7, new Point2d(xInnerRight, yBottom + r), bulge, 0, 0); + boundary.Closed = true; + + ctx.Btr.AppendEntity(boundary); + ctx.Tr.AddNewlyCreatedDBObject(boundary, true); + + 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); + + try + { + boundary.Erase(true); + } + catch + { + // ignore + } + } + catch + { + // ignore + } + } + private static string FormatDimNumber(double value, string rawInput = null) { try