diff --git a/.agent/rules/code.md b/.agent/rules/code.md
new file mode 100644
index 0000000..91ce360
--- /dev/null
+++ b/.agent/rules/code.md
@@ -0,0 +1,8 @@
+---
+trigger: always_on
+---
+
+这个项目必须用中文输出
+这个项目所有cad图纸生成代码,每个模板是物理隔离的
+这个项目我来编译,你不要编译
+创建文件的时候,不要忘记引入工程
\ No newline at end of file
diff --git a/Cad/Drawers/RingMachinedRollingGenerator.cs b/Cad/Drawers/RingMachinedRollingGenerator.cs
index d756b5e..666b02f 100644
--- a/Cad/Drawers/RingMachinedRollingGenerator.cs
+++ b/Cad/Drawers/RingMachinedRollingGenerator.cs
@@ -1,4 +1,6 @@
using CadParamPluging.Common;
+using Autodesk.AutoCAD.Geometry;
+using CadParamPluging.Domain.Models;
namespace CadParamPluging.Cad
{
@@ -7,5 +9,10 @@ namespace CadParamPluging.Cad
public static readonly string Key = TemplateKeyBuilder.Build("车加工", "轧制", "环形", "无");
public override string TemplateKey => Key;
+
+ public override void Draw(CadContext ctx, ParamBag bag, TemplateParams templateParams, Point3d center, double scaleFactor)
+ {
+ RingMachinedRollingDrawer.Draw(ctx, bag, center, scaleFactor);
+ }
}
}
diff --git a/Cad/RingMachinedRollingDrawer.cs b/Cad/RingMachinedRollingDrawer.cs
new file mode 100644
index 0000000..4fb085e
--- /dev/null
+++ b/Cad/RingMachinedRollingDrawer.cs
@@ -0,0 +1,715 @@
+using System;
+using System.Collections.Generic;
+using Autodesk.AutoCAD.DatabaseServices;
+using Autodesk.AutoCAD.Geometry;
+using CadParamPluging.Common;
+
+namespace CadParamPluging.Cad
+{
+ ///
+ /// 车加工-轧制-环形 独立绘图器
+ /// 物理隔离的绘图逻辑,不依赖 FeatureDrivenDrawer 的具体实现(除了部分通用工具方法)
+ ///
+ public static class RingMachinedRollingDrawer
+ {
+ #region 参数Key常量 (复用 FeatureDrivenDrawer 的定义)
+ public const string KeyOuterDiameter1 = "OuterDiameter1";
+ public const string KeyOuterDiameter1TolPlus = "OuterDiameter1TolPlus";
+ public const string KeyOuterDiameter1TolMinus = "OuterDiameter1TolMinus";
+ public const string KeyInnerDiameter2 = "InnerDiameter2";
+ public const string KeyInnerDiameter2TolPlus = "InnerDiameter2TolPlus";
+ public const string KeyInnerDiameter2TolMinus = "InnerDiameter2TolMinus";
+ public const string KeyHeight1 = "Height1";
+ public const string KeyHeight1TolPlus = "Height1TolPlus";
+ public const string KeyHeight1TolMinus = "Height1TolMinus";
+ public const string KeyMinWallThickness = "MinWallThickness";
+ public const string KeyUnspecifiedFilletRadiusMax = "UnspecifiedFilletRadiusMax";
+
+ public const string KeyOuterDiameter1Prime = "OuterDiameter1Prime";
+ public const string KeyInnerDiameter2Prime = "InnerDiameter2Prime";
+ public const string KeyHeight1Prime = "Height1Prime";
+
+ public const string KeyMarkingContent = "MarkingContent";
+ #endregion
+
+ 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)
+ };
+
+ var outerDia = effectiveBag.GetDoubleOrNull(KeyOuterDiameter1);
+ var height = effectiveBag.GetDoubleOrNull(KeyHeight1);
+
+ if (!outerDia.HasValue || outerDia.Value <= 0 || !height.HasValue || height.Value <= 0)
+ {
+ return;
+ }
+
+ // 调用核心绘制逻辑
+ // 此处传递 true 以启用 UnspecifiedFillet 逻辑 (与 FeatureDrivenDrawer.DrawRingRollingWithUnspecifiedFillet 保持一致)
+ DrawCore(context, outerDia.Value, height.Value, true);
+ }
+
+ private static void DrawCore(FeatureDrivenDrawer.DrawingContext ctx, double outerDia, double height, bool applyUnspecifiedFillet)
+ {
+ var bag = ctx.Bag;
+
+ // --- 几何与视觉映射计算 ---
+ double H = height;
+ double physicalOuterR = outerDia / 2.0;
+ double physicalInnerR = 0;
+
+ var innerDia = bag.GetDoubleOrNull(KeyInnerDiameter2);
+ if (innerDia.HasValue && innerDia.Value > 0)
+ {
+ physicalInnerR = innerDia.Value / 2.0;
+ }
+
+ // 1. 确定视觉半径
+ double visualOuterR = physicalOuterR;
+ double visualInnerR = physicalInnerR;
+
+ // 轧制+车加工(示意图模式)特殊处理
+ if (ctx.IsMachined)
+ {
+ var minWallThkParam = bag.GetDoubleOrNull(KeyMinWallThickness);
+
+ if (minWallThkParam.HasValue && minWallThkParam.Value > 0)
+ {
+ visualInnerR = minWallThkParam.Value * 2.0;
+ visualOuterR = minWallThkParam.Value * 3.0;
+ }
+ else
+ {
+ visualOuterR = H * 3.0;
+ visualInnerR = visualOuterR * (2.0/3.0);
+ }
+ }
+
+ // 3. 定义半径映射函数
+ double MapRadius(double r)
+ {
+ if (r <= 0) return 0;
+ if (physicalInnerR <= 1e-6)
+ {
+ return r * (visualOuterR / physicalOuterR);
+ }
+ if (r <= physicalInnerR)
+ {
+ return r * (visualInnerR / physicalInnerR);
+ }
+ else
+ {
+ double wallScale = (visualOuterR - visualInnerR) / (physicalOuterR - physicalInnerR);
+ return visualInnerR + (r - physicalInnerR) * wallScale;
+ }
+ }
+
+ // --- 绘图坐标计算 ---
+ double ox = ctx.Center.X - visualOuterR / 2.0; // 对称轴位置
+ double oy = ctx.Center.Y - H / 2.0;
+
+ // 车加工态零件尺寸
+ double? outerDiaPrime = null;
+ double? innerDiaPrime = null;
+ double? heightPrime = null;
+ if (ctx.IsMachined)
+ {
+ outerDiaPrime = bag.GetDoubleOrNull(KeyOuterDiameter1Prime);
+ innerDiaPrime = bag.GetDoubleOrNull(KeyInnerDiameter2Prime);
+ heightPrime = bag.GetDoubleOrNull(KeyHeight1Prime);
+ }
+
+ // === 特征1: 锻件外轮廓 ===
+ var unspecifiedFillet = bag.GetDoubleOrNull(KeyUnspecifiedFilletRadiusMax);
+ bool hasUnspecifiedFillet = applyUnspecifiedFillet && unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0;
+
+ if (!hasUnspecifiedFillet)
+ {
+ DrawForgingOuterContourHalf(ctx, ox, oy, visualOuterR, H, null);
+ }
+
+ // === 特征1.1: 对称轴 ===
+ DrawRingSymmetryAxis(ctx, ox, oy, H);
+
+ // === 特征2: 外径公差标注 ===
+ var outerTolPlus = bag.GetDoubleOrNull(KeyOuterDiameter1TolPlus);
+ var outerTolMinus = bag.GetDoubleOrNull(KeyOuterDiameter1TolMinus);
+ DrawOuterDiameterDimensionHalf(ctx, ox, oy, visualOuterR, H, outerDia, outerTolPlus, outerTolMinus, outerDiaPrime);
+
+ // === 特征3: 内孔/内径 ===
+ double? xInnerRight = null;
+ if (innerDia.HasValue && innerDia.Value > 0 && innerDia.Value < outerDia)
+ {
+ xInnerRight = ox + visualInnerR;
+
+ var innerTolPlus = bag.GetDoubleOrNull(KeyInnerDiameter2TolPlus);
+ var innerTolMinus = bag.GetDoubleOrNull(KeyInnerDiameter2TolMinus);
+
+ if (hasUnspecifiedFillet)
+ {
+ FeatureDrivenDrawer.DrawRingSectionContourWithFillet(ctx, xInnerRight.Value, ox + visualOuterR, oy, H, unspecifiedFillet.Value);
+
+ FeatureDrivenDrawer.DrawHoleHorizontalLines(ctx, ox, xInnerRight.Value, oy, H, unspecifiedFillet.Value);
+
+ var sectionWidth = (ox + visualOuterR) - (xInnerRight.Value);
+ var maxR = Math.Min(sectionWidth * 0.5, H * 0.5);
+ var r = Math.Min(unspecifiedFillet.Value, maxR);
+
+ var dimExtensionOffset = 0.0;
+ if (r > 0.01) dimExtensionOffset = r;
+
+ DrawInnerDiameterDimensionHalf(ctx, ox, xInnerRight.Value, oy, H, innerDia.Value, innerTolPlus, innerTolMinus, innerDiaPrime, dimExtensionOffset);
+
+ FeatureDrivenDrawer.DrawRingSectionHatchWithFillet(ctx, xInnerRight.Value, ox + visualOuterR, oy, H, unspecifiedFillet.Value);
+ }
+ else
+ {
+ DrawInnerHoleHalf(ctx, ox, xInnerRight.Value, oy, H);
+ DrawInnerDiameterDimensionHalf(ctx, ox, xInnerRight.Value, oy, H, innerDia.Value, innerTolPlus, innerTolMinus, innerDiaPrime);
+
+ FeatureDrivenDrawer.DrawRingSectionHatch(ctx, xInnerRight.Value, ox + visualOuterR, oy, H);
+
+ FeatureDrivenDrawer.DrawSectionInnerBoundaryBold(ctx, xInnerRight.Value, oy, H);
+ }
+ }
+
+ // === 特征5: 高度标注 ===
+ var heightTolPlus = bag.GetDoubleOrNull(KeyHeight1TolPlus);
+ var heightTolMinus = bag.GetDoubleOrNull(KeyHeight1TolMinus);
+
+ double heightDimIndentX = 0.0;
+ if (hasUnspecifiedFillet)
+ {
+ var sWidth = (ox + visualOuterR) - (xInnerRight.Value);
+ var maxR = Math.Min(sWidth * 0.5, H * 0.5);
+ var r = Math.Min(unspecifiedFillet.Value, maxR);
+ if (r > 0.01) heightDimIndentX = r;
+ }
+
+ DrawHeightDimensionHalf(ctx, ox, oy, visualOuterR, H, heightTolPlus, heightTolMinus, heightPrime, heightDimIndentX);
+
+ // === 特征6: 未注圆角 ===
+ if (!applyUnspecifiedFillet && unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
+ {
+ FeatureDrivenDrawer.DrawUnspecifiedFilletNote(ctx, ox, oy, H, visualOuterR, unspecifiedFillet.Value);
+ }
+
+ // === 特征7: 最小壁厚min标注 ===
+ var minWallThickness = bag.GetDoubleOrNull(KeyMinWallThickness);
+ if (minWallThickness.HasValue && minWallThickness.Value > 0 && xInnerRight.HasValue)
+ {
+ var dimExtensionOffset = 0.0;
+ if (applyUnspecifiedFillet && unspecifiedFillet.HasValue)
+ {
+ var sWidth = Math.Abs((ox + visualOuterR) - (xInnerRight.Value));
+ var maxR = Math.Min(sWidth * 0.5, H * 0.5);
+ var rCalc = Math.Min(unspecifiedFillet.Value, maxR);
+ if (rCalc > 0.01) dimExtensionOffset = rCalc;
+ }
+
+ FeatureDrivenDrawer.DrawMinWallThicknessNote(ctx, xInnerRight.Value, ox + visualOuterR, oy, minWallThickness.Value, dimExtensionOffset);
+ }
+
+ // === 特征8: 零件轮廓 ===
+ if (ctx.IsMachined && outerDiaPrime.HasValue && outerDiaPrime.Value > 0 && heightPrime.HasValue && heightPrime.Value > 0)
+ {
+ // 1. 外径
+ double physicalPartOuterR = outerDiaPrime.Value / 2.0;
+ double visualPartOuterR = MapRadius(physicalPartOuterR);
+ var scaledOuterDiaPrime = visualPartOuterR * 2.0;
+
+ // 2. 内径
+ double? scaledInnerDiaPrime = null;
+ if (innerDiaPrime.HasValue && innerDiaPrime.Value > 0)
+ {
+ double physicalPartInnerR = innerDiaPrime.Value / 2.0;
+ double visualPartInnerR = MapRadius(physicalPartInnerR);
+ scaledInnerDiaPrime = visualPartInnerR * 2.0;
+ }
+
+ // 3. 高度
+ var scaledHeightPrime = heightPrime.Value;
+
+ DrawPartContourHalf(ctx, ox, oy, H, scaledOuterDiaPrime, scaledInnerDiaPrime, scaledHeightPrime);
+ }
+
+ // === 特征10: 标刻内容 HB5936-13 ===
+ if (ctx.IsMachined && innerDia.HasValue && innerDia.Value > 0)
+ {
+ var markingText = bag.GetString(KeyMarkingContent);
+ // 哪怕没有标刻内容,在"车加工-轧制-环形"中也常常需要显示默认标准
+ if (!string.IsNullOrWhiteSpace(markingText) || applyUnspecifiedFillet)
+ {
+ // 修改:接触线应该是左侧边(即内孔边界的垂直线)
+ var xTarget = ox + visualInnerR;
+ var yTargetTop = oy + H;
+
+ if (string.IsNullOrWhiteSpace(markingText))
+ {
+ markingText = "HB5936-13";
+ }
+
+ DrawMarkingLeaderToSide(ctx, xTarget, yTargetTop, markingText);
+ }
+ }
+
+ // === 特征9: 硬度符号 (HB) ===
+ // 【已移除】按用户需求,此模板不绘制红色方框中的硬度符号
+ }
+
+ private static void DrawMarkingLeaderToSide(FeatureDrivenDrawer.DrawingContext ctx, double xTarget, double yTargetTop, string markingText)
+ {
+ try
+ {
+ // 箭头起点:内孔左侧边的顶部向下5mm处 (接触线是左侧边)
+ var p1 = new Point3d(xTarget, yTargetTop - 5.0, 0);
+
+ // 转折点:向左上 (偏移角度随意,例如左10,上10)
+ var p2 = new Point3d(xTarget - 10, yTargetTop + 5, 0);
+
+ // 终点:水平向左
+ // 长度根据文字适配
+ double textLen = (string.IsNullOrEmpty(markingText) ? 10 : markingText.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; // 白色
+
+ ctx.Btr.AppendEntity(leader);
+ ctx.Tr.AddNewlyCreatedDBObject(leader, true);
+
+ var text = new DBText();
+ text.TextString = markingText;
+ text.Height = 3.5;
+ text.ColorIndex = 7;
+ 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 { }
+ }
+
+ #region 私有辅助绘图方法
+
+ private static void DrawForgingOuterContourHalf(FeatureDrivenDrawer.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);
+ poly.AddVertexAt(1, new Point2d(ox + radius, oy), 0, 0, 0);
+ poly.AddVertexAt(2, new Point2d(ox + radius, oy + height), 0, 0, 0);
+ poly.AddVertexAt(3, new Point2d(ox, oy + height), 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 DrawRingSymmetryAxis(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double height)
+ {
+ const double extend = 5.0;
+ const double frameMargin = 5.0;
+ const double lineSpacing = 3.0;
+
+ var y0 = oy - extend;
+ var y1 = oy + height + extend;
+
+ 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 + height;
+ }
+
+ var line1 = new Line(new Point3d(ox, y0, 0), new Point3d(ox, y1, 0));
+ ctx.Style?.Apply(line1, DrawingStyleManager.Role.BreakLine);
+ ctx.Btr.AppendEntity(line1);
+ ctx.Tr.AddNewlyCreatedDBObject(line1, true);
+
+ var line2 = new Line(new Point3d(ox - lineSpacing, y0, 0), new Point3d(ox - lineSpacing, y1, 0));
+ ctx.Style?.Apply(line2, DrawingStyleManager.Role.BreakLine);
+ ctx.Btr.AppendEntity(line2);
+ ctx.Tr.AddNewlyCreatedDBObject(line2, true);
+ }
+
+ private static void DrawOuterDiameterDimensionHalf(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double radius, double height,
+ double diameter, double? tolPlus, double? tolMinus, double? diameterPrime)
+ {
+ var diameterVal = ctx.OriginalBag?.GetDoubleOrNull(KeyOuterDiameter1) ?? diameter;
+ var diameterStr = ctx.OriginalBag?.GetString(KeyOuterDiameter1);
+ var tolPlusVal = ctx.OriginalBag?.GetDoubleOrNull(KeyOuterDiameter1TolPlus) ?? tolPlus;
+ var tolMinusVal = ctx.OriginalBag?.GetDoubleOrNull(KeyOuterDiameter1TolMinus) ?? tolMinus;
+ var tolPlusStr = ctx.OriginalBag?.GetString(KeyOuterDiameter1TolPlus);
+ var tolMinusStr = ctx.OriginalBag?.GetString(KeyOuterDiameter1TolMinus);
+
+ var diameterPrimeVal = diameterPrime;
+ if (ctx.OriginalBag != null)
+ {
+ var p = ctx.OriginalBag.GetDoubleOrNull(KeyOuterDiameter1Prime);
+ if (p.HasValue) diameterPrimeVal = p.Value;
+ }
+
+ var baseText = FeatureDrivenDrawer.BuildDimensionText($"%%c{FeatureDrivenDrawer.FormatDimNumber(diameterVal, diameterStr)}", tolPlusVal, tolMinusVal, tolPlusStr, tolMinusStr);
+ var dimText = diameterPrimeVal.HasValue && diameterPrimeVal.Value > 0
+ ? baseText + $"\\X(%%c{FeatureDrivenDrawer.FormatDimNumber(diameterPrimeVal.Value)})"
+ : baseText;
+
+ AddLinearDim(
+ ctx,
+ new Point3d(ox, oy, 0),
+ new Point3d(ox + radius, oy, 0),
+ new Point3d(ox + radius / 2, oy - 25, 0),
+ 0,
+ dimText,
+ ApplyHalfSideDimStyle);
+ }
+
+ private static void DrawInnerHoleHalf(FeatureDrivenDrawer.DrawingContext ctx, double oxAxis, double xInnerRight, double yBottom, double height)
+ {
+ var yTop = yBottom + height;
+ var lineRight = new Line(new Point3d(xInnerRight, yBottom, 0), new Point3d(xInnerRight, yTop, 0));
+ ctx.Style?.Apply(lineRight, DrawingStyleManager.Role.Hidden);
+ ctx.Btr.AppendEntity(lineRight);
+ ctx.Tr.AddNewlyCreatedDBObject(lineRight, true);
+ }
+
+ private static void DrawInnerDiameterDimensionHalf(FeatureDrivenDrawer.DrawingContext ctx, double oxAxis, double xInnerRight, double yBottom, double height,
+ double diameter, double? tolPlus, double? tolMinus, double? diameterPrime, double offsetY = 0)
+ {
+ var diameterVal = ctx.OriginalBag?.GetDoubleOrNull(KeyInnerDiameter2) ?? diameter;
+ var diameterStr = ctx.OriginalBag?.GetString(KeyInnerDiameter2);
+ var tolPlusVal = ctx.OriginalBag?.GetDoubleOrNull(KeyInnerDiameter2TolPlus) ?? tolPlus;
+ var tolMinusVal = ctx.OriginalBag?.GetDoubleOrNull(KeyInnerDiameter2TolMinus) ?? tolMinus;
+ var tolPlusStr = ctx.OriginalBag?.GetString(KeyInnerDiameter2TolPlus);
+ var tolMinusStr = ctx.OriginalBag?.GetString(KeyInnerDiameter2TolMinus);
+
+ var diameterPrimeVal = diameterPrime;
+ if (ctx.OriginalBag != null)
+ {
+ var p = ctx.OriginalBag.GetDoubleOrNull(KeyInnerDiameter2Prime);
+ if (p.HasValue) diameterPrimeVal = p.Value;
+ }
+
+ var baseText = FeatureDrivenDrawer.BuildDimensionText($"%%c{FeatureDrivenDrawer.FormatDimNumber(diameterVal, diameterStr)}", tolPlusVal, tolMinusVal, tolPlusStr, tolMinusStr);
+ var dimText = diameterPrimeVal.HasValue && diameterPrimeVal.Value > 0
+ ? baseText + $"\\X(%%c{FeatureDrivenDrawer.FormatDimNumber(diameterPrimeVal.Value)})"
+ : baseText;
+
+ double innerRadius = xInnerRight - oxAxis;
+ var dimLineY = yBottom - 10;
+ AddLinearDim(
+ ctx,
+ new Point3d(oxAxis, yBottom, 0),
+ new Point3d(xInnerRight, yBottom + offsetY, 0),
+ new Point3d(oxAxis + innerRadius / 2, dimLineY, 0),
+ 0,
+ dimText,
+ ApplyHalfSideDimStyle);
+ }
+
+ private static void DrawHeightDimensionHalf(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double radius,
+ double height, double? tolPlus, double? tolMinus, double? heightPrime, double indentX = 0)
+ {
+ var heightVal = ctx.OriginalBag?.GetDoubleOrNull(KeyHeight1) ?? height;
+ var heightStr = ctx.OriginalBag?.GetString(KeyHeight1);
+ var tolPlusVal = ctx.OriginalBag?.GetDoubleOrNull(KeyHeight1TolPlus) ?? tolPlus;
+ var tolMinusVal = ctx.OriginalBag?.GetDoubleOrNull(KeyHeight1TolMinus) ?? tolMinus;
+ var tolPlusStr = ctx.OriginalBag?.GetString(KeyHeight1TolPlus);
+ var tolMinusStr = ctx.OriginalBag?.GetString(KeyHeight1TolMinus);
+
+ var heightPrimeVal = heightPrime;
+ if (ctx.OriginalBag != null)
+ {
+ var p = ctx.OriginalBag.GetDoubleOrNull(KeyHeight1Prime);
+ if (p.HasValue) heightPrimeVal = p.Value;
+ }
+
+ var baseText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(heightVal, heightStr), tolPlusVal, tolMinusVal, tolPlusStr, tolMinusStr);
+ var dimText = heightPrimeVal.HasValue && heightPrimeVal.Value > 0
+ ? baseText + $"\\X({FeatureDrivenDrawer.FormatDimNumber(heightPrimeVal.Value)})"
+ : baseText;
+
+ var xLine = ox + radius - indentX;
+
+ FeatureDrivenDrawer.AddLinearDim(
+ ctx,
+ new Point3d(xLine, oy, 0),
+ new Point3d(xLine, oy + height, 0),
+ new Point3d(ox + radius + 20, oy + height / 2, 0),
+ 90,
+ dimText);
+ }
+
+ private static void DrawPartContourHalf(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double forgingHeight,
+ double outerDiaPrime, double? innerDiaPrime, double heightPrime)
+ {
+ var Rp = outerDiaPrime / 2.0;
+ var h = heightPrime;
+ var offsetY = (forgingHeight - h) / 2.0;
+ var y0 = oy + offsetY;
+
+ double minX = ox;
+ if (innerDiaPrime.HasValue && innerDiaPrime.Value > 0)
+ {
+ minX = ox + innerDiaPrime.Value / 2.0;
+ }
+ double maxX = ox + Rp;
+
+ var polyPart = new Polyline();
+ polyPart.AddVertexAt(0, new Point2d(minX, y0), 0, 0, 0);
+ polyPart.AddVertexAt(1, new Point2d(maxX, y0), 0, 0, 0);
+ polyPart.AddVertexAt(2, new Point2d(maxX, y0 + h), 0, 0, 0);
+ polyPart.AddVertexAt(3, new Point2d(minX, y0 + h), 0, 0, 0);
+ polyPart.Closed = true;
+
+ ctx.Style?.Apply(polyPart, DrawingStyleManager.Role.PartContour);
+ ctx.Btr.AppendEntity(polyPart);
+ ctx.Tr.AddNewlyCreatedDBObject(polyPart, true);
+ }
+
+ #endregion
+
+ #region 本地标注样式辅助方法 (从 FeatureDrivenDrawer 复制以保持隔离)
+
+ private static void ApplyHalfSideDimStyle(Dimension dim, FeatureDrivenDrawer.DrawingContext ctx)
+ {
+ TrySetDimProp(dim, "Dimse1", true);
+ TrySetDimProp(dim, "Dimse2", false);
+
+ try
+ {
+ TrySetDimProp(dim, "Dimsah", true);
+ EnsureNoneBlock(ctx.Db, ctx.Tr);
+
+ var bt = (BlockTable)ctx.Tr.GetObject(ctx.Db.BlockTableId, OpenMode.ForRead);
+ if (bt.Has("_NONE"))
+ {
+ dim.Dimblk1 = bt["_NONE"];
+ }
+ }
+ catch { }
+ }
+
+ private static void EnsureNoneBlock(Database db, Transaction tr)
+ {
+ try
+ {
+ var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
+ if (!bt.Has("_NONE"))
+ {
+ using (var btr = new BlockTableRecord())
+ {
+ btr.Name = "_NONE";
+ btr.Origin = Point3d.Origin;
+ bt.UpgradeOpen();
+ bt.Add(btr);
+ tr.AddNewlyCreatedDBObject(btr, 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;
+ }
+
+ #endregion
+ }
+}
diff --git a/CadParamPluging.csproj b/CadParamPluging.csproj
index 184e196..da56fcc 100644
--- a/CadParamPluging.csproj
+++ b/CadParamPluging.csproj
@@ -84,6 +84,7 @@
+