diff --git a/Cad/BlockRawFreeForgeRoundHeadDrawer.cs b/Cad/BlockRawFreeForgeRoundHeadDrawer.cs new file mode 100644 index 0000000..ab81329 --- /dev/null +++ b/Cad/BlockRawFreeForgeRoundHeadDrawer.cs @@ -0,0 +1,771 @@ +using System; +using System.Collections.Generic; +using Autodesk.AutoCAD.DatabaseServices; +using Autodesk.AutoCAD.Geometry; +using CadParamPluging.Common; + +namespace CadParamPluging.Cad +{ + public static class BlockRawFreeForgeRoundHeadDrawer + { + 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) + }; + + DrawBlockRawFreeForgeRoundHeadCore(context); + } + + private static void DrawBlockRawFreeForgeRoundHeadCore(FeatureDrivenDrawer.DrawingContext ctx) + { + var bag = ctx.Bag; + + // BoxSize1 (Width - 总长度) + // BoxSize2 (Height - 高度/直径) + var width = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize1); + var height = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize2); + + if (!width.HasValue || width.Value <= 0 || !height.HasValue || height.Value <= 0) + { + return; + } + + double H = height.Value; + double W = width.Value; + + // 外轮廓圆弧:高度固定为 H/5 + // 依据用户新需求 (2026-01-29): 黄色部分(圆弧高)是粉色部分(总高H)的1/5 + double arcHeight = H / 5.0; + + // 视觉比例:总宽度映射 + double visualTotalW = H * 3.0; // 保持视觉宽高比约 3:1 + + // 绘图坐标计算 (保持居中) + double ox = ctx.Center.X - visualTotalW / 2.0; // 左边界 (圆弧最左端) + double oy = ctx.Center.Y - H / 2.0; // 底边 + + // 内框边界(从左圆弧弦线到右圆弧弦线) + // 注意:ox 是圆弧顶点,xInnerLeft 应该是弦线位置 + double xInnerLeft = ox + arcHeight; + double xInnerRight = ox + visualTotalW - arcHeight; + double innerWidth = xInnerRight - xInnerLeft; + + // 获取圆头处圆角半径 (BoxRoundHeadFilletRadiusMax) - 用于外侧圆角 + // 依据用户需求:外侧圆角由“圆头处圆角半径”控制 + var headFilletParam = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxRoundHeadFilletRadiusMax); + double headFilletR = headFilletParam.HasValue && headFilletParam.Value > 0 + ? headFilletParam.Value + : 0; + + // 获取内框圆角参数:优先取 UnspecifiedFilletRadiusMax,如果没有则取 BoxFilletRadiusMax - 用于内部剖面 + var innerFilletParam = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyUnspecifiedFilletRadiusMax); + if (!innerFilletParam.HasValue || innerFilletParam.Value <= 0) + { + innerFilletParam = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxFilletRadiusMax); + } + + double sectionFilletR = innerFilletParam.HasValue && innerFilletParam.Value > 0 + ? innerFilletParam.Value + : 0; + + // 1. 绘制完整锻件外轮廓(方体有圆头 - 白色,大圆弧) + // 修正:圆弧弦线需向内缩进 headFilletR (原 logic 使用 innerFilletR),以与锻件外侧圆角起点对齐 + DrawBlockRoundHeadOutline(ctx, ox, oy, visualTotalW, H, arcHeight, headFilletR); + + // 2. 绘制分段式内框(左、中、右三段)以支持中间剖面区域的独立圆角 + // 中间区域(剖面)作为主体,如果设置了圆角,四个角都应为圆角 + + // 计算视觉上的剖面宽度 + // 依据用户需求:尺寸3 (BoxSize3) 对应剖面的宽 + var size3 = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize3); + double visualSectionWidth; + + if (size3.HasValue && size3.Value > 0) + { + // 按比例映射:VisualW / PhysicalW + double scale = visualTotalW / W; + visualSectionWidth = size3.Value * scale; + + // 限制最大宽度,防止出错 + if (visualSectionWidth > innerWidth * 0.95) + { + visualSectionWidth = innerWidth * 0.95; + } + } + else + { + // 降级策略 + visualSectionWidth = innerWidth / 3.0; + } + + // 居中布置剖面 + double sectionOffset = (innerWidth - visualSectionWidth) / 2.0; + double xSectionLeft = xInnerLeft + sectionOffset; + double xSectionRight = xSectionLeft + visualSectionWidth; + + // 绘制中间剖面框(带圆角) + // 使用 sectionFilletR + DrawBoxSectionContourWithFillet(ctx, xSectionLeft, xSectionRight, oy, H, sectionFilletR); + + // 绘制左侧框线(连接左端圆弧和中间剖面框) + // 左端: xInnerLeft (需处理左上下角的圆角 - 使用 headFilletR) + // 右端: xSectionLeft (连接到中间框的直边) + DrawBoxSideFrame(ctx, xInnerLeft, xSectionLeft, oy, H, headFilletR, isLeft: true); + + // 绘制右侧框线 + // 左端: xSectionRight (连接到中间框的直边) + // 右端: xInnerRight (需处理右上下角的圆角 - 使用 headFilletR) + DrawBoxSideFrame(ctx, xSectionRight, xInnerRight, oy, H, headFilletR, isLeft: false); + + // 3. 剖面填充 - 只在中间区域 + // 使用 sectionFilletR + if (sectionFilletR > 0.01) + { + DrawRingSectionHatchWithFillet(ctx, xSectionLeft, xSectionRight, oy, H, sectionFilletR); + } + else + { + DrawBlockSectionHatch(ctx, xSectionLeft, xSectionRight, oy, H); + } + + // 5. 零件轮廓框(黄色双点划线矩形 - 在内框内,与锻件有一定间距) + var widthPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize1Prime); + var heightPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize2Prime); + if (widthPrime.HasValue && widthPrime.Value > 0 && heightPrime.HasValue && heightPrime.Value > 0) + { + double partH = heightPrime.Value; + double partW = widthPrime.Value; + + // 计算零件在视觉上的宽度比例 + double partWidthRatio = partW / W; + double visualPartW = innerWidth * partWidthRatio; + if (visualPartW > innerWidth) visualPartW = innerWidth * 0.9; + + // 零件在锻件内居中 + double partOffsetX = (innerWidth - visualPartW) / 2.0; + double partOffsetY = (H - partH) / 2.0; + + double xPartLeft = xInnerLeft + partOffsetX; + double yPartBottom = oy + partOffsetY; + + DrawBlockPartContour(ctx, xPartLeft, yPartBottom, visualPartW, partH); + } + + // 6. 宽度标注 (BoxSize1) - 位于底部 + // 标注从锻件最左端到最右端 (BoxSize1 对应 锻件总宽) + { + var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize1) ?? W; + var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize1); + var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize1TolPlus); + var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize1TolMinus); + var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize1TolPlus); + var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize1TolMinus); + + var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr); + + // 添加零件尺寸 (Prime) 到下方,用括号包裹 + var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize1Prime); + if (valPrime.HasValue && valPrime.Value > 0) + { + dimText += $"\\X({FeatureDrivenDrawer.FormatDimNumber(valPrime.Value, null)})"; + } + + // 修正:标注需涵盖内框宽度 (矩形部分) + + // 修正:引线起点改为内框边界 (xInnerLeft/Right) 和高度底部上移圆角半径,确保闭合到白色线框 + // 使用 headFilletR 作为 Offset,因为这是侧边框的倒角 + double dimOriginY = oy + headFilletR; + AddLinearDim( + ctx, + new Point3d(xInnerLeft, dimOriginY, 0), + new Point3d(xInnerRight, dimOriginY, 0), + new Point3d((xInnerLeft + xInnerRight) / 2, oy - 25, 0), + 0, + dimText); + } + + // 7. 高度标注 (BoxSize2) - 位于右侧 + // 标注从锻件顶部到底部 + { + var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize2) ?? H; + var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize2); + var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize2TolPlus); + var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize2TolMinus); + var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize2TolPlus); + var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize2TolMinus); + + var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr); + + // 添加零件尺寸 (Prime) 到下方 + var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize2Prime); + if (valPrime.HasValue && valPrime.Value > 0) + { + dimText += $"\\X({FeatureDrivenDrawer.FormatDimNumber(valPrime.Value, null)})"; + } + + // 标注从圆弧最外侧开始(避免与圆弧轮廓线重叠) + double xOuterRight = ox + visualTotalW; + // 修正:标注界线起点应从圆弧顶端开始,往内缩进一个圆弧高度 arcHeight + headFilletR,定位在弦线上 + double xDimOrigin = xOuterRight - (arcHeight + headFilletR); + + AddLinearDim( + ctx, + new Point3d(xDimOrigin, oy, 0), + new Point3d(xDimOrigin, oy + H, 0), + new Point3d(xOuterRight + 20, oy + H / 2, 0), + 90, + dimText); + } + + // 8. 中间矩形宽度标注 (BoxSize3) - 位于上方 + // 对应剖面区域宽度 + { + var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize3) ?? 0; + var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize3); + + // 只有当有值时才标注 + if (val > 0) + { + var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize3TolPlus); + var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize3TolMinus); + var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize3TolPlus); + var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize3TolMinus); + + var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr); + + // 添加零件尺寸 (Prime) 到下方 + var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize3Prime); + if (valPrime.HasValue && valPrime.Value > 0) + { + dimText += $"\\X({FeatureDrivenDrawer.FormatDimNumber(valPrime.Value, null)})"; + } + + AddLinearDim( + ctx, + new Point3d(xSectionLeft, oy + H, 0), + new Point3d(xSectionRight, oy + H, 0), + new Point3d((xSectionLeft + xSectionRight) / 2, oy + H + 15, 0), + 0, + dimText); + } + } + + // 9. 硬度符号 - 从剖面底部引出 + var hardnessVal = bag.GetString(FeatureDrivenDrawer.KeyHardness); + if (!string.IsNullOrWhiteSpace(hardnessVal)) + { + double xStart = (xSectionLeft + xSectionRight) / 2.0; + double yStart = oy; + DrawHardnessSymbol(ctx, xStart, yStart); + } + + // 10. 标刻内容引线 - 从剖面顶部引出 + var markingText = bag.GetString(FeatureDrivenDrawer.KeyMarkingContent); + if (!string.IsNullOrWhiteSpace(markingText)) + { + double xTarget = (xSectionLeft + xSectionRight) / 2.0; + double yTarget = oy + H; + DrawSpecialHBLeaderToTop(ctx, xTarget, yTarget, markingText); + } + } + + private static void DrawBlockRoundHeadOutline(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double totalWidth, double height, double arcHeight, double innerFilletR) + { + try + { + double H = height; + double r = innerFilletR; + + double xCurrentLeft = ox + arcHeight + r; + double xCurrentRight = ox + totalWidth - arcHeight - r; + + double sagitta = arcHeight + r; + double halfChord = H / 2.0; + + double bulge = 0; + if (halfChord > 1e-3) + { + bulge = -(sagitta / halfChord); + } + + var poly = new Polyline(); + + poly.AddVertexAt(0, new Point2d(xCurrentRight, oy), 0, 0, 0); + poly.AddVertexAt(1, new Point2d(xCurrentLeft, oy), bulge, 0, 0); + poly.AddVertexAt(2, new Point2d(xCurrentLeft, oy + H), 0, 0, 0); + poly.AddVertexAt(3, new Point2d(xCurrentRight, oy + H), bulge, 0, 0); + poly.Closed = true; + + ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold); + ctx.Btr.AppendEntity(poly); + ctx.Tr.AddNewlyCreatedDBObject(poly, true); + } + catch { } + } + + private static void DrawBoxSectionContourWithFillet(FeatureDrivenDrawer.DrawingContext ctx, double xLeft, double xRight, double yBottom, double height, double filletR) + { + var yTop = yBottom + height; + var width = xRight - xLeft; + + var maxR = Math.Min(width * 0.5, height * 0.5); + var r = Math.Min(filletR, maxR); + + if (r <= 0.01) + { + var poly = new Polyline(); + poly.AddVertexAt(0, new Point2d(xLeft, yBottom), 0, 0, 0); + poly.AddVertexAt(1, new Point2d(xRight, yBottom), 0, 0, 0); + poly.AddVertexAt(2, new Point2d(xRight, yTop), 0, 0, 0); + poly.AddVertexAt(3, new Point2d(xLeft, yTop), 0, 0, 0); + poly.Closed = true; + + ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold); + ctx.Btr.AppendEntity(poly); + ctx.Tr.AddNewlyCreatedDBObject(poly, true); + return; + } + + var bulge = Math.Tan(Math.PI / 8.0); + + var polyFillet = new Polyline(); + + polyFillet.AddVertexAt(0, new Point2d(xLeft + r, yBottom), 0, 0, 0); + polyFillet.AddVertexAt(1, new Point2d(xRight - r, yBottom), bulge, 0, 0); + polyFillet.AddVertexAt(2, new Point2d(xRight, yBottom + r), 0, 0, 0); + polyFillet.AddVertexAt(3, new Point2d(xRight, yTop - r), bulge, 0, 0); + polyFillet.AddVertexAt(4, new Point2d(xRight - r, yTop), 0, 0, 0); + polyFillet.AddVertexAt(5, new Point2d(xLeft + r, yTop), bulge, 0, 0); + polyFillet.AddVertexAt(6, new Point2d(xLeft, yTop - r), 0, 0, 0); + polyFillet.AddVertexAt(7, new Point2d(xLeft, yBottom + r), bulge, 0, 0); + + polyFillet.Closed = true; + + ctx.Style?.Apply(polyFillet, DrawingStyleManager.Role.OutlineBold); + ctx.Btr.AppendEntity(polyFillet); + ctx.Tr.AddNewlyCreatedDBObject(polyFillet, true); + } + + private static void DrawBoxSideFrame(FeatureDrivenDrawer.DrawingContext ctx, double xStart, double xEnd, double yBottom, double height, double filletR, bool isLeft) + { + var yTop = yBottom + height; + var width = Math.Abs(xEnd - xStart); + if (width < 0.1) return; + + var maxR = Math.Min(width * 0.5, height * 0.5); + var r = Math.Min(filletR, maxR); + var bulge = -Math.Tan(Math.PI / 8.0); + + var poly = new Polyline(); + + if (isLeft) + { + poly.AddVertexAt(0, new Point2d(xEnd, yBottom), 0, 0, 0); + + if (r > 0.01) + { + poly.AddVertexAt(1, new Point2d(xStart + r, yBottom), bulge, 0, 0); + poly.AddVertexAt(2, new Point2d(xStart, yBottom + r), 0, 0, 0); + poly.AddVertexAt(3, new Point2d(xStart, yTop - r), bulge, 0, 0); + poly.AddVertexAt(4, new Point2d(xStart + r, yTop), 0, 0, 0); + poly.AddVertexAt(5, new Point2d(xEnd, yTop), 0, 0, 0); + } + else + { + poly.AddVertexAt(1, new Point2d(xStart, yBottom), 0, 0, 0); + poly.AddVertexAt(2, new Point2d(xStart, yTop), 0, 0, 0); + poly.AddVertexAt(3, new Point2d(xEnd, yTop), 0, 0, 0); + } + poly.Closed = false; + } + else + { + poly.AddVertexAt(0, new Point2d(xStart, yTop), 0, 0, 0); + + if (r > 0.01) + { + poly.AddVertexAt(1, new Point2d(xEnd - r, yTop), bulge, 0, 0); + poly.AddVertexAt(2, new Point2d(xEnd, yTop - r), 0, 0, 0); + poly.AddVertexAt(3, new Point2d(xEnd, yBottom + r), bulge, 0, 0); + poly.AddVertexAt(4, new Point2d(xEnd - r, yBottom), 0, 0, 0); + poly.AddVertexAt(5, new Point2d(xStart, yBottom), 0, 0, 0); + } + else + { + poly.AddVertexAt(1, new Point2d(xEnd, yTop), 0, 0, 0); + poly.AddVertexAt(2, new Point2d(xEnd, yBottom), 0, 0, 0); + poly.AddVertexAt(3, new Point2d(xStart, yBottom), 0, 0, 0); + } + poly.Closed = false; + } + + ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold); + ctx.Btr.AppendEntity(poly); + ctx.Tr.AddNewlyCreatedDBObject(poly, true); + } + + private static void DrawRingSectionHatchWithFillet(FeatureDrivenDrawer.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) + { + DrawBlockSectionHatch(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 { } + } + catch { } + } + + private static void DrawBlockSectionHatch(FeatureDrivenDrawer.DrawingContext ctx, double xLeft, double xRight, double yBottom, double height) + { + if (xRight <= xLeft) + { + return; + } + + try + { + var boundary = new Polyline(); + boundary.AddVertexAt(0, new Point2d(xLeft, yBottom), 0, 0, 0); + boundary.AddVertexAt(1, new Point2d(xRight, yBottom), 0, 0, 0); + boundary.AddVertexAt(2, new Point2d(xRight, yBottom + height), 0, 0, 0); + boundary.AddVertexAt(3, new Point2d(xLeft, yBottom + height), 0, 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 { } + } + catch { } + } + + private static void DrawBlockPartContour(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double width, double height) + { + try + { + var poly = new Polyline(); + poly.AddVertexAt(0, new Point2d(x, y), 0, 0, 0); + poly.AddVertexAt(1, new Point2d(x + width, y), 0, 0, 0); + poly.AddVertexAt(2, new Point2d(x + width, y + height), 0, 0, 0); + poly.AddVertexAt(3, new Point2d(x, y + height), 0, 0, 0); + poly.Closed = true; + + ctx.Style?.Apply(poly, DrawingStyleManager.Role.PartContour); + ctx.Btr.AppendEntity(poly); + ctx.Tr.AddNewlyCreatedDBObject(poly, true); + } + catch { } + } + + private static void DrawHardnessSymbol(FeatureDrivenDrawer.DrawingContext ctx, double xStart, double yStart) + { + try + { + var p1 = new Point3d(xStart, yStart, 0); + var p2 = new Point3d(xStart + 15, yStart - 15, 0); + var p3 = new Point3d(p2.X + 10, p2.Y, 0); + + var poly = new Polyline(); + poly.AddVertexAt(0, new Point2d(p1.X, p1.Y), 0, 0, 0); + poly.AddVertexAt(1, new Point2d(p2.X, p2.Y), 0, 0, 0); + poly.AddVertexAt(2, new Point2d(p3.X, p3.Y), 0, 0, 0); + + ctx.Style?.Apply(poly, DrawingStyleManager.Role.Dimension); + poly.ColorIndex = 3; + + ctx.Btr.AppendEntity(poly); + ctx.Tr.AddNewlyCreatedDBObject(poly, true); + + double radius = 4.0; + var center = new Point3d(p3.X + radius, p3.Y, 0); + var circle = new Circle(center, Vector3d.ZAxis, radius); + circle.ColorIndex = 3; + + ctx.Btr.AppendEntity(circle); + ctx.Tr.AddNewlyCreatedDBObject(circle, true); + + var text = new DBText(); + text.TextString = "HB"; + text.Height = 3.5; + text.ColorIndex = 3; + text.HorizontalMode = TextHorizontalMode.TextCenter; + text.VerticalMode = TextVerticalMode.TextVerticalMid; + text.AlignmentPoint = center; + text.Position = center; + + ctx.Btr.AppendEntity(text); + ctx.Tr.AddNewlyCreatedDBObject(text, true); + } + catch { } + } + + private static void DrawSpecialHBLeaderToTop(FeatureDrivenDrawer.DrawingContext ctx, double xTarget, double yTarget, string textContent) + { + try + { + var p1 = new Point3d(xTarget, yTarget, 0); + var p2 = new Point3d(xTarget - 10, yTarget + 10, 0); + + double textLen = (string.IsNullOrEmpty(textContent) ? 10 : textContent.Length) * 2.5; + if (textLen < 20) textLen = 20; + + var p3 = new Point3d(p2.X - textLen, p2.Y, 0); + + var leader = new Leader(); + leader.SetDatabaseDefaults(); + leader.AppendVertex(p1); + leader.AppendVertex(p2); + leader.AppendVertex(p3); + leader.HasArrowHead = true; + leader.ColorIndex = 7; // 白色 + leader.Layer = "0"; + + ctx.Btr.AppendEntity(leader); + ctx.Tr.AddNewlyCreatedDBObject(leader, true); + + var text = new DBText(); + text.TextString = textContent; + text.Height = 3.5; + text.ColorIndex = 7; + text.Layer = "0"; + + text.HorizontalMode = TextHorizontalMode.TextLeft; + text.VerticalMode = TextVerticalMode.TextBottom; + text.AlignmentPoint = new Point3d(p3.X, p3.Y + 1.0, 0); + text.Position = text.AlignmentPoint; + + ctx.Btr.AppendEntity(text); + ctx.Tr.AddNewlyCreatedDBObject(text, true); + } + catch { } + } + + 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 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; + } + + } +} diff --git a/Cad/DiskRawFreeForgeDrawer.cs b/Cad/DiskRawFreeForgeDrawer.cs new file mode 100644 index 0000000..198c143 --- /dev/null +++ b/Cad/DiskRawFreeForgeDrawer.cs @@ -0,0 +1,400 @@ +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 poly = new Polyline(); + 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); + + // 直径标注 + 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); + AddLinearDim(ctx, new Point3d(ox, oy, 0), new Point3d(ox + diameter.Value, oy, 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); + AddLinearDim(ctx, new Point3d(ox + diameter.Value, oy, 0), new Point3d(ox + diameter.Value, oy + H, 0), + new Point3d(ox + diameter.Value + 20, ctx.Center.Y, 0), 90, htDimText); + + // 未注圆角(使用通用 Key) + var unspecifiedFillet = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyUnspecifiedFilletRadiusMax); + if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0) + { + DrawUnspecifiedFilletNote(ctx, ox, oy + H, R, diameter.Value, unspecifiedFillet.Value); + } + + // 零件尺寸(如果有) + var diaPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterPrime); + var heightPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1Prime); + if (diaPrime.HasValue && diaPrime.Value > 0 && heightPrime.HasValue && heightPrime.Value > 0) + { + DrawDiskPartContour(ctx, ox, oy, diameter.Value, H, diaPrime.Value, heightPrime.Value); + } + } + + 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); + + // 零件直径标注 + AddLinearDim(ctx, new Point3d(ox + offsetX, oy + offsetY, 0), + new Point3d(ox + offsetX + partDia, oy + offsetY, 0), + new Point3d(ox + offsetX + partDia / 2, oy + offsetY - 10, 0), 0, $"%%c{partDia}"); + + // 零件高度标注 + AddLinearDim(ctx, new Point3d(ox + offsetX + partDia, oy + offsetY, 0), + new Point3d(ox + offsetX + partDia, oy + offsetY + partH, 0), + new Point3d(ox + offsetX + partDia + 10, oy + offsetY + partH / 2, 0), 90, $"{partH}"); + } + + 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}}}"; + } + } +} diff --git a/Cad/Drawers/BlockRawFreeForgeRoundHeadGenerator.cs b/Cad/Drawers/BlockRawFreeForgeRoundHeadGenerator.cs index 0375666..2fe9be8 100644 --- a/Cad/Drawers/BlockRawFreeForgeRoundHeadGenerator.cs +++ b/Cad/Drawers/BlockRawFreeForgeRoundHeadGenerator.cs @@ -33,7 +33,7 @@ namespace CadParamPluging.Cad public override void Draw(CadContext ctx, ParamBag bag, TemplateParams templateParams, Autodesk.AutoCAD.Geometry.Point3d center, double scaleFactor) { // 调用独立的新绘制方法 - FeatureDrivenDrawer.DrawBlockRawFreeForgeRoundHead(ctx, bag, center, scaleFactor); + BlockRawFreeForgeRoundHeadDrawer.Draw(ctx, bag, center, scaleFactor); } } } diff --git a/Cad/Drawers/DiskRawFreeForgeGenerator.cs b/Cad/Drawers/DiskRawFreeForgeGenerator.cs new file mode 100644 index 0000000..9463d1f --- /dev/null +++ b/Cad/Drawers/DiskRawFreeForgeGenerator.cs @@ -0,0 +1,39 @@ +using CadParamPluging.Common; +using CadParamPluging.Domain.Models; + +namespace CadParamPluging.Cad +{ + public sealed class DiskRawFreeForgeGenerator : TemplateDrawingGeneratorBase + { + public static readonly string Key = TemplateKeyBuilder.Build("毛料态", "自由锻", "饼盘", ""); + + public override string TemplateKey => Key; + + public override FeatureDrivenDrawer.ExpectedDrawingSize CalculateExpectedSize(ParamBag bag, TemplateParams templateParams) + { + var diameter = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameter) ?? 0; + var height = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1) ?? 0; + + // Visual size estimation + // Disk drawing is roughly: + // Top view (Circle) + Side view (Rectangle)? + // Wait, FeatureDrivenDrawer.DrawDiskFeatures only draws the Side View (Rectangle). + // "这里绘制侧视图" (Lines 1762-1763 of FeatureDrivenDrawer.cs) + // So width = Diameter, Height = Height. + + // Margins + var extraMargin = 60.0; + + return new FeatureDrivenDrawer.ExpectedDrawingSize + { + Width = diameter + extraMargin * 2, + Height = height + extraMargin * 2 + }; + } + + public override void Draw(CadContext ctx, ParamBag bag, TemplateParams templateParams, Autodesk.AutoCAD.Geometry.Point3d center, double scaleFactor) + { + DiskRawFreeForgeDrawer.Draw(ctx, bag, center, scaleFactor); + } + } +} diff --git a/Cad/Drawers/TemplateDrawingRegistry.cs b/Cad/Drawers/TemplateDrawingRegistry.cs index bf2b078..04d2720 100644 --- a/Cad/Drawers/TemplateDrawingRegistry.cs +++ b/Cad/Drawers/TemplateDrawingRegistry.cs @@ -20,6 +20,7 @@ namespace CadParamPluging.Cad Register(new RingRawFreeForgeCenterPunchGenerator()); Register(new ShaftRawFreeForgeRoundShaftGenerator()); Register(new ShaftRawFreeForgeSquareShaftGenerator()); + Register(new DiskRawFreeForgeGenerator()); } public static bool TryResolve(string templateKey, out ITemplateDrawingGenerator generator) diff --git a/Cad/FeatureDrivenDrawer.cs b/Cad/FeatureDrivenDrawer.cs index 0dc5094..d840a9e 100644 --- a/Cad/FeatureDrivenDrawer.cs +++ b/Cad/FeatureDrivenDrawer.cs @@ -2941,9 +2941,9 @@ namespace CadParamPluging.Cad } /// - /// 毛料态-自由锻-方体-有圆头:独立图纸生成逻辑 - /// 逻辑完全复制自“车加工-轧制-环形”,但映射了方体参数 + /// [MOVED] Logic moved to BlockRawFreeForgeRoundHeadDrawer.cs /// + [Obsolete("Use BlockRawFreeForgeRoundHeadDrawer.Draw instead")] public static void DrawBlockRawFreeForgeRoundHead(CadContext ctx, ParamBag bag, Point3d center, double scaleFactor = 1.0) { if (ctx == null) throw new ArgumentNullException(nameof(ctx)); diff --git a/CadParamPluging.csproj b/CadParamPluging.csproj index d099111..fdd3dfa 100644 --- a/CadParamPluging.csproj +++ b/CadParamPluging.csproj @@ -88,6 +88,7 @@ + @@ -96,6 +97,8 @@ + + diff --git a/Common/DropdownOptions.cs b/Common/DropdownOptions.cs index eff1d06..4114df1 100644 --- a/Common/DropdownOptions.cs +++ b/Common/DropdownOptions.cs @@ -25,8 +25,8 @@ namespace CadParamPluging.Common { DeliveryStatuses = new List { "毛料态", "车加工" }, ProcessMethods = new List { "轧制", "自由锻" }, - StructuralFeatures = new List { "环形", "方体" }, - SpecialConditions = new List { "无", "中心冲孔", "非中心冲孔", "有圆头", "圆轴" } + StructuralFeatures = new List { "环形", "方体", "轴杆", "饼盘" }, + SpecialConditions = new List { "无", "中心冲孔", "非中心冲孔", "有圆头", "圆轴", "方轴", "无圆头" } }; } diff --git a/Common/TemplateSchemaDefaults.cs b/Common/TemplateSchemaDefaults.cs index 7b8f134..d2db33a 100644 --- a/Common/TemplateSchemaDefaults.cs +++ b/Common/TemplateSchemaDefaults.cs @@ -278,6 +278,35 @@ namespace CadParamPluging.Common }, PartOwnershipConfigured = true }); + + // 模板:交付状态=毛料态, 工艺方法=自由锻, 结构特征=饼盘, 特殊条件=无 + // TemplateKey: "毛料态|自由锻|饼盘|" + schemas.Items.Add(new TemplateSchemaDefinition + { + ProjectType = "毛料态", + DrawingType = "自由锻", + SheetSize = "饼盘", + Scale = "", + DisplayName = "饼盘(毛料态/自由锻)", + SelectedParamKeys = new List + { + "Diameter", + "DiameterTolPlus", + "DiameterTolMinus", + "Height1", + "Height1TolPlus", + "Height1TolMinus", + "UnspecifiedFilletRadiusMax", // 未注圆角半径R≤ + "DiameterPrime", + "Height1Prime" + }, + SelectedPartParamKeys = new List + { + "DiameterPrime", + "Height1Prime" + }, + PartOwnershipConfigured = true + }); schemas.Normalize(); return schemas;