using System; using System.Collections.Generic; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using CadParamPluging.Common; namespace CadParamPluging.Cad { public static class ShaftRawFreeForgeSquareShaftDrawer { 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 = "轴杆", SpecialCondition = "方轴", ProcessMethod = "自由锻", Btr = btr, Style = new DrawingStyleManager(db, tr) }; DrawCore(context); } private static void DrawCore(FeatureDrivenDrawer.DrawingContext ctx) { var bag = ctx.Bag; var size1 = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1); var size2 = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2); var size3 = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3); var originalSize1 = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1); if (!size1.HasValue || size1.Value <= 0 || !size2.HasValue || size2.Value <= 0) { return; } double S1 = size1.Value; double S2 = size2.Value; double S3 = size3.HasValue && size3.Value > 0 ? size3.Value : 0; double originalS1 = originalSize1.HasValue ? originalSize1.Value : S1; double ox = ctx.Center.X - S1 / 2.0; double oy = ctx.Center.Y - S2 / 2.0; var filletRParam = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftFilletRadiusMax); double filletR = filletRParam.HasValue && filletRParam.Value > 0 ? filletRParam.Value : 0; double maxR = Math.Min(S1 / 2.0, S2 / 2.0); if (filletR > maxR) filletR = maxR; // 判断是否需要断线 bool needBreakLines = originalS1 > 150; const double lineSpacing = 3.5; // 1. Draw Main View - 如果需要断线,则绘制带缺口的轮廓 double xBreak = ox + S1 / 4.0; // 1. Draw Main View - 如果需要断线,则绘制带缺口的轮廓 if (needBreakLines) { DrawRectWithBreak(ctx, ox, oy, S1, S2, filletR, xBreak, lineSpacing); } else { DrawRectWithFillets(ctx, ox, oy, S1, S2, filletR, DrawingStyleManager.Role.OutlineBold); } // 2. 绘制左右两端的弧线(向外凸出) // 弧高设为 S2/5(尺寸2的1/5) double arcHeight = S2 / 5.0; DrawEndArcs(ctx, ox, oy, S1, S2, arcHeight); // 3. 绘制中心线 (横向,在中间位置) - 已移除 // DrawHorizontalCenterLine(ctx, ctx.Center.Y, ox, ox + S1, needBreakLines, xBreak, lineSpacing); // 4. Draw Break Lines if needed if (needBreakLines) { DrawBreakLines(ctx, ox, oy, S1, S2); } // 3. Draw Section if S3 > 0 if (S3 > 0) { double sectionW = S3; double sectionH = S2; double sectionOx = ox + S1 * 2.0 / 3.0 - sectionW / 2.0; // 剖面位于右边1/3处 double sectionOy = oy; double maxRSec = Math.Min(sectionW / 2.0, sectionH / 2.0); double filletRSec = (filletR > maxRSec) ? maxRSec : filletR; var sectionPoly = CreateRectPoly(sectionOx, sectionOy, sectionW, sectionH, filletRSec); ctx.Style?.Apply(sectionPoly, DrawingStyleManager.Role.OutlineBold); ctx.Btr.AppendEntity(sectionPoly); ctx.Tr.AddNewlyCreatedDBObject(sectionPoly, true); CreateHatchForPolyline(ctx, sectionPoly); } // 4. Dimensions { var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1) ?? S1; var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize1); var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1TolPlus); var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1TolMinus); var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize1TolPlus); var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize1TolMinus); var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr); var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1Prime); if (valPrime.HasValue && valPrime.Value > 0) { dimText += @"\X(" + FeatureDrivenDrawer.FormatDimNumber(valPrime.Value) + ")"; } double dimY = oy - 25; double dimOriginY = oy + filletR; FeatureDrivenDrawer.AddLinearDim(ctx, new Point3d(ox, dimOriginY, 0), new Point3d(ox + S1, dimOriginY, 0), new Point3d(ctx.Center.X, dimY, 0), 0, dimText); } { var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2) ?? S2; var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize2); var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2TolPlus); var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2TolMinus); var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize2TolPlus); var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize2TolMinus); var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr); var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2Prime); if (valPrime.HasValue && valPrime.Value > 0) { dimText += @"\X(" + FeatureDrivenDrawer.FormatDimNumber(valPrime.Value) + ")"; } double dimX = ox + S1 + 20; double dimOriginX = ox + S1 - filletR; FeatureDrivenDrawer.AddLinearDim(ctx, new Point3d(dimOriginX, oy, 0), new Point3d(dimOriginX, oy + S2, 0), new Point3d(dimX, ctx.Center.Y, 0), 90, dimText); } if (S3 > 0) { var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3) ?? S3; var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize3); var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3TolPlus); var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3TolMinus); var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize3TolPlus); var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize3TolMinus); var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr); var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3Prime); if (valPrime.HasValue && valPrime.Value > 0) { dimText += @"\X(" + FeatureDrivenDrawer.FormatDimNumber(valPrime.Value) + ")"; } double dimY = oy + S2 + 20; double sectionOx = ox + S1 * 2.0 / 3.0 - S3 / 2.0; // 标注位置对应剖面 double dimOriginY = oy + S2 - filletR; FeatureDrivenDrawer.AddLinearDim(ctx, new Point3d(sectionOx, dimOriginY, 0), new Point3d(sectionOx + S3, dimOriginY, 0), new Point3d(ctx.Center.X, dimY, 0), 0, dimText); } var hardnessVal = bag.GetString(FeatureDrivenDrawer.KeyHardness); if (!string.IsNullOrWhiteSpace(hardnessVal)) { double xStart = (S3 > 0) ? ctx.Center.X : (ox + S1 / 2.0); double yStart = oy; FeatureDrivenDrawer.DrawHardnessSymbol(ctx, xStart, yStart); } var markingText = bag.GetString(FeatureDrivenDrawer.KeyMarkingContent); if (!string.IsNullOrWhiteSpace(markingText)) { double xTarget = (S3 > 0) ? ctx.Center.X : (ox + S1 / 2.0); double yTarget = oy + S2; FeatureDrivenDrawer.DrawSpecialHBLeaderToTop(ctx, xTarget, yTarget, markingText); } var s1Prime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1Prime); var s2Prime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2Prime); if (s1Prime.HasValue && s1Prime.Value > 0 && s2Prime.HasValue && s2Prime.Value > 0) { double pL = s1Prime.Value; double pH = s2Prime.Value; double pOx = ctx.Center.X - pL / 2.0; double pOy = ctx.Center.Y - pH / 2.0; if (needBreakLines) { // double xBreak = ox + S1 / 4.0; // variable is already declared in outer scope DrawRectOutlineWithBreak(ctx, pOx, pOy, pL, pH, xBreak, lineSpacing, DrawingStyleManager.Role.PartContour); } else { DrawRectOutline(ctx, pOx, pOy, pL, pH, DrawingStyleManager.Role.PartContour); } } } /// /// 绘制断线(使用 BreakLine 样式:白色 PHANTOM 双点划线) /// private static void DrawBreakLines(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double width, double height) { const double lineSpacing = 3.5; const double extend = 5.0; double xBreak = ox + width / 4.0; double y0 = oy - extend; double y1 = oy + height + extend; var line1 = new Line(new Point3d(xBreak, y0, 0), new Point3d(xBreak, y1, 0)); ctx.Style?.Apply(line1, DrawingStyleManager.Role.BreakLine); ctx.Btr.AppendEntity(line1); ctx.Tr.AddNewlyCreatedDBObject(line1, true); var line2 = new Line(new Point3d(xBreak + lineSpacing, y0, 0), new Point3d(xBreak + lineSpacing, y1, 0)); ctx.Style?.Apply(line2, DrawingStyleManager.Role.BreakLine); ctx.Btr.AppendEntity(line2); ctx.Tr.AddNewlyCreatedDBObject(line2, true); } /// /// 绘制带断口的矩形轮廓(在断线位置打断上下横线) /// private static void DrawRectWithBreak(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double w, double h, double r, double xBreak, double breakWidth) { // 左边竖线 var leftLine = new Line(new Point3d(x, y, 0), new Point3d(x, y + h, 0)); ctx.Style?.Apply(leftLine, DrawingStyleManager.Role.OutlineBold); ctx.Btr.AppendEntity(leftLine); ctx.Tr.AddNewlyCreatedDBObject(leftLine, true); // 右边竖线 var rightLine = new Line(new Point3d(x + w, y, 0), new Point3d(x + w, y + h, 0)); ctx.Style?.Apply(rightLine, DrawingStyleManager.Role.OutlineBold); ctx.Btr.AppendEntity(rightLine); ctx.Tr.AddNewlyCreatedDBObject(rightLine, true); // 底边:断开 [xBreak, xBreak + breakWidth] // 左段 var bottomLeft = new Line(new Point3d(x, y, 0), new Point3d(xBreak, y, 0)); ctx.Style?.Apply(bottomLeft, DrawingStyleManager.Role.OutlineBold); ctx.Btr.AppendEntity(bottomLeft); ctx.Tr.AddNewlyCreatedDBObject(bottomLeft, true); // 右段 var bottomRight = new Line(new Point3d(xBreak + breakWidth, y, 0), new Point3d(x + w, y, 0)); ctx.Style?.Apply(bottomRight, DrawingStyleManager.Role.OutlineBold); ctx.Btr.AppendEntity(bottomRight); ctx.Tr.AddNewlyCreatedDBObject(bottomRight, true); // 顶边:断开 [xBreak, xBreak + breakWidth] // 左段 var topLeft = new Line(new Point3d(x, y + h, 0), new Point3d(xBreak, y + h, 0)); ctx.Style?.Apply(topLeft, DrawingStyleManager.Role.OutlineBold); ctx.Btr.AppendEntity(topLeft); ctx.Tr.AddNewlyCreatedDBObject(topLeft, true); // 右段 var topRight = new Line(new Point3d(xBreak + breakWidth, y + h, 0), new Point3d(x + w, y + h, 0)); ctx.Style?.Apply(topRight, DrawingStyleManager.Role.OutlineBold); ctx.Btr.AppendEntity(topRight); ctx.Tr.AddNewlyCreatedDBObject(topRight, true); } private static void DrawRectWithFillets(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double w, double h, double r, DrawingStyleManager.Role role = DrawingStyleManager.Role.OutlineBold) { var poly = CreateRectPoly(x, y, w, h, r); ctx.Style?.Apply(poly, role); ctx.Btr.AppendEntity(poly); ctx.Tr.AddNewlyCreatedDBObject(poly, true); } private static Polyline CreateRectPoly(double x, double y, double w, double h, double r) { var poly = new Polyline(); if (r < 0.01) { poly.AddVertexAt(0, new Point2d(x, y), 0, 0, 0); poly.AddVertexAt(1, new Point2d(x + w, y), 0, 0, 0); poly.AddVertexAt(2, new Point2d(x + w, y + h), 0, 0, 0); poly.AddVertexAt(3, new Point2d(x, y + h), 0, 0, 0); } else { var bulge = Math.Tan(Math.PI / 8.0); poly.AddVertexAt(0, new Point2d(x + r, y), 0, 0, 0); poly.AddVertexAt(1, new Point2d(x + w - r, y), bulge, 0, 0); poly.AddVertexAt(2, new Point2d(x + w, y + r), 0, 0, 0); poly.AddVertexAt(3, new Point2d(x + w, y + h - r), bulge, 0, 0); poly.AddVertexAt(4, new Point2d(x + w - r, y + h), 0, 0, 0); poly.AddVertexAt(5, new Point2d(x + r, y + h), bulge, 0, 0); poly.AddVertexAt(6, new Point2d(x, y + h - r), 0, 0, 0); poly.AddVertexAt(7, new Point2d(x, y + r), bulge, 0, 0); } poly.Closed = true; return poly; } private static void DrawRectOutline(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double w, double h, DrawingStyleManager.Role role) { var poly = new Polyline(); poly.AddVertexAt(0, new Point2d(x, y), 0, 0, 0); poly.AddVertexAt(1, new Point2d(x + w, y), 0, 0, 0); poly.AddVertexAt(2, new Point2d(x + w, y + h), 0, 0, 0); poly.AddVertexAt(3, new Point2d(x, y + h), 0, 0, 0); poly.Closed = true; ctx.Style?.Apply(poly, role); ctx.Btr.AppendEntity(poly); ctx.Tr.AddNewlyCreatedDBObject(poly, true); } 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 { } } private static ParamBag ScaleParamBag(ParamBag original, double scaleFactor) { if (original == null) return null; if (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("SquareShaftSize") || k.Contains("Radius") || k.Contains("Prime")) { 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; } /// /// 绘制左右两端的弧线(向外凸出) /// 使用Polyline的bulge(凸度)值绘制,确保端点精确对齐 /// private static void DrawEndArcs(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double W, double H, double arcHeight) { try { // 弧线端点: // 左侧弧线:从(ox, oy+H)到(ox, oy),向左凸出arcHeight // 右侧弧线:从(ox+W, oy)到(ox+W, oy+H),向右凸出arcHeight double chordLength = H; double sagitta = arcHeight; // 计算凸度:bulge = 2 * 拱高 / 弦长 double bulge = (2.0 * sagitta) / chordLength; // 左侧弧线:从(ox, oy+H)到(ox, oy),向左凸出(正凸度) var leftArc = new Polyline(); leftArc.AddVertexAt(0, new Point2d(ox, oy + H), bulge, 0, 0); leftArc.AddVertexAt(1, new Point2d(ox, oy), 0, 0, 0); ctx.Style?.Apply(leftArc, DrawingStyleManager.Role.OutlineBold); ctx.Btr.AppendEntity(leftArc); ctx.Tr.AddNewlyCreatedDBObject(leftArc, true); // 右侧弧线:从(ox+W, oy)到(ox+W, oy+H),向右凸出(正凸度) var rightArc = new Polyline(); rightArc.AddVertexAt(0, new Point2d(ox + W, oy), bulge, 0, 0); rightArc.AddVertexAt(1, new Point2d(ox + W, oy + H), 0, 0, 0); ctx.Style?.Apply(rightArc, DrawingStyleManager.Role.OutlineBold); ctx.Btr.AppendEntity(rightArc); ctx.Tr.AddNewlyCreatedDBObject(rightArc, true); } catch { // ignore } } /// /// 绘制带断口的零件轮廓(在断线位置打断上下横线) /// 支持自定义 Role (通常为 PartContour) /// private static void DrawRectOutlineWithBreak(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double w, double h, double xBreak, double breakWidth, DrawingStyleManager.Role role) { // 左边竖线 var leftLine = new Line(new Point3d(x, y, 0), new Point3d(x, y + h, 0)); ctx.Style?.Apply(leftLine, role); ctx.Btr.AppendEntity(leftLine); ctx.Tr.AddNewlyCreatedDBObject(leftLine, true); // 右边竖线 var rightLine = new Line(new Point3d(x + w, y, 0), new Point3d(x + w, y + h, 0)); ctx.Style?.Apply(rightLine, role); ctx.Btr.AppendEntity(rightLine); ctx.Tr.AddNewlyCreatedDBObject(rightLine, true); // 底边:断开 [xBreak, xBreak + breakWidth] // 左段 if (xBreak > x) { var bottomLeft = new Line(new Point3d(x, y, 0), new Point3d(Math.Min(xBreak, x + w), y, 0)); ctx.Style?.Apply(bottomLeft, role); ctx.Btr.AppendEntity(bottomLeft); ctx.Tr.AddNewlyCreatedDBObject(bottomLeft, true); } // 右段 if (xBreak + breakWidth < x + w) { var bottomRight = new Line(new Point3d(Math.Max(xBreak + breakWidth, x), y, 0), new Point3d(x + w, y, 0)); ctx.Style?.Apply(bottomRight, role); ctx.Btr.AppendEntity(bottomRight); ctx.Tr.AddNewlyCreatedDBObject(bottomRight, true); } // 顶边:断开 [xBreak, xBreak + breakWidth] // 左段 if (xBreak > x) { var topLeft = new Line(new Point3d(x, y + h, 0), new Point3d(Math.Min(xBreak, x + w), y + h, 0)); ctx.Style?.Apply(topLeft, role); ctx.Btr.AppendEntity(topLeft); ctx.Tr.AddNewlyCreatedDBObject(topLeft, true); } // 右段 if (xBreak + breakWidth < x + w) { var topRight = new Line(new Point3d(Math.Max(xBreak + breakWidth, x), y + h, 0), new Point3d(x + w, y + h, 0)); ctx.Style?.Apply(topRight, role); ctx.Btr.AppendEntity(topRight); ctx.Tr.AddNewlyCreatedDBObject(topRight, true); } } } }