CadParamPluging/Cad/ShaftRawFreeForgeRoundShaftDrawer.cs

591 lines
28 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using CadParamPluging.Common;
namespace CadParamPluging.Cad
{
public static class ShaftRawFreeForgeRoundShaftDrawer
{
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 dia = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameter);
var len = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyLength);
if (!dia.HasValue || dia.Value <= 0 || !len.HasValue || len.Value <= 0)
{
return;
}
// 逻辑要求:长度是宽度,直径是高度 (Fixed)
double W = len.Value;
double H = dia.Value;
// 获取原始值用于判断断线(防止缩放干扰)
var originalLen = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyLength);
double originalW = originalLen.HasValue ? originalLen.Value : W;
double ox = ctx.Center.X - W / 2.0;
double oy = ctx.Center.Y - H / 2.0;
var filletRParam = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyShaftFilletRadiusMax);
double filletR = filletRParam.HasValue && filletRParam.Value > 0 ? filletRParam.Value : 0;
double maxR = Math.Min(W / 2.0, H / 2.0);
if (filletR > maxR) filletR = maxR;
// 判断是否需要断线
bool needBreakLines = originalW > 150;
const double lineSpacing = 3.5;
// 计算平滑相切数据模型
double arcHeight = H / 5.0;
double r = filletR;
double w = arcHeight;
double Rm = (H * H) / (8.0 * w) + w / 2.0;
double xInnerLeft = ox;
double xc_left = xInnerLeft - w + Rm;
double D_tangent = (Rm >= r) ? Math.Sqrt(Math.Max(0, (Rm - r) * (Rm - r) - (H / 2.0 - r) * (H / 2.0 - r))) : (Rm - w);
double xf_left = r > 0 ? xc_left - D_tangent : xInnerLeft;
double xInnerRight = ox + W;
double xc_right = xInnerRight + w - Rm;
double xf_right = r > 0 ? xc_right + D_tangent : xInnerRight;
double fx_L_tang = r > 0 ? xc_left + (Rm / (Rm - r)) * (xf_left - xc_left) : xInnerLeft;
double fy_L_tangBot = r > 0 ? (oy + H / 2.0) + (Rm / (Rm - r)) * ((oy + r) - (oy + H / 2.0)) : oy;
double fx_R_tang = r > 0 ? xc_right + (Rm / (Rm - r)) * (xf_right - xc_right) : xInnerRight;
double fy_R_tangBot = r > 0 ? (oy + H / 2.0) + (Rm / (Rm - r)) * ((oy + r) - (oy + H / 2.0)) : oy;
double fx_L_tangTop = r > 0 ? xc_left + (Rm / (Rm - r)) * (xf_left - xc_left) : xInnerLeft;
double fy_L_tangTop = r > 0 ? (oy + H / 2.0) + (Rm / (Rm - r)) * ((oy + H - r) - (oy + H / 2.0)) : oy + H;
double fx_R_tangTop = r > 0 ? xc_right + (Rm / (Rm - r)) * (xf_right - xc_right) : xInnerRight;
double fy_R_tangTop = r > 0 ? (oy + H / 2.0) + (Rm / (Rm - r)) * ((oy + H - r) - (oy + H / 2.0)) : oy + H;
double xBreak = ox + W / 4.0;
// 1. 绘制主体轮廓 (矩形 + 平滑相切圆角) 和 2. 绘制左右两端的弧线 一体化
DrawShaftRoundHeadUnifiedOutline(ctx, ox, oy, W, H, w, r, xf_left, xf_right, fx_L_tangTop, fy_L_tangTop, fx_L_tang, fy_L_tangBot, fx_R_tangTop, fy_R_tangTop, fx_R_tang, fy_R_tangBot, needBreakLines, xBreak, lineSpacing);
// 3. 绘制中心线 (横向,在中间位置)
DrawHorizontalCenterLine(ctx, ctx.Center.Y, ox, ox + W, needBreakLines, xBreak, lineSpacing);
// 4. 绘制断线 (如果需要)
if (needBreakLines)
{
DrawBreakLines(ctx, ox, oy, W, H);
}
// 3. 尺寸标注
// 3.1 长度标注 (底部) - 对应宽度W
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyLength) ?? W;
var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyLength);
var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyLengthTolPlus);
var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyLengthTolMinus);
var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyLengthTolPlus);
var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyLengthTolMinus);
var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr);
var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyLengthPrime);
if (valPrime.HasValue && valPrime.Value > 0)
{
dimText += @"\X(" + FeatureDrivenDrawer.FormatDimNumber(valPrime.Value) + ")";
}
double dimY = oy - 25;
// 修正:引线起点基于真正的倒角切点,保证垂线和尺寸界线接合完美
FeatureDrivenDrawer.AddLinearDim(ctx, new Point3d(fx_L_tang, fy_L_tangBot, 0), new Point3d(fx_R_tang, fy_R_tangBot, 0), new Point3d(ctx.Center.X, dimY, 0), 0, dimText);
}
// 3.2 直径标注 (右侧) - 对应高度H
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameter) ?? H;
var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyDiameter);
var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterTolPlus);
var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterTolMinus);
var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyDiameterTolPlus);
var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyDiameterTolMinus);
// 直径加上 %%c 符号
var dimText = "%%c" + FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr);
var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterPrime);
if (valPrime.HasValue && valPrime.Value > 0)
{
dimText += @"\X(%%c" + FeatureDrivenDrawer.FormatDimNumber(valPrime.Value) + ")";
}
double dimX = ox + W + 20 + arcHeight;
FeatureDrivenDrawer.AddLinearDim(ctx, new Point3d(xf_right, oy, 0), new Point3d(xf_right, oy + H, 0), new Point3d(dimX, ctx.Center.Y, 0), 90, dimText);
}
// 3.3 补加未注侧倒角标注指示
if (filletR > 0)
{
double cxRight = xf_right;
double cyTop = oy + H - filletR;
DrawHeadFilletRadiusLeader(ctx, cxRight, cyTop, filletR);
}
// 4. 硬度和标刻
var hardnessVal = bag.GetString(FeatureDrivenDrawer.KeyHardness);
if (!string.IsNullOrWhiteSpace(hardnessVal))
{
// 硬度放在底部中心位置
double xStart = ctx.Center.X;
double yStart = oy;
FeatureDrivenDrawer.DrawHardnessSymbol(ctx, xStart, yStart);
}
var markingText = bag.GetString(FeatureDrivenDrawer.KeyMarkingContent);
if (!string.IsNullOrWhiteSpace(markingText))
{
// 标刻引线指向顶部中心
double xTarget = ctx.Center.X;
double yTarget = oy + H;
FeatureDrivenDrawer.DrawSpecialHBLeaderToTop(ctx, xTarget, yTarget, markingText);
}
// 5. 零件轮廓 (Prime)
// 逻辑要求:零件参数也遵循 直径=宽度,长度=高度
var diaPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterPrime);
var lenPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyLengthPrime);
if (diaPrime.HasValue && diaPrime.Value > 0 && lenPrime.HasValue && lenPrime.Value > 0)
{
double pW = lenPrime.Value; // Length -> Width
double pH = diaPrime.Value; // Diameter -> Height
double pOx = ctx.Center.X - pW / 2.0;
double pOy = ctx.Center.Y - pH / 2.0;
if (needBreakLines)
{
// 使用与锻件相同的断线X坐标和间距
// double xBreak = ox + W / 4.0; // variable is already declared in outer scope
DrawRectOutlineWithBreak(ctx, pOx, pOy, pW, pH, xBreak, lineSpacing, DrawingStyleManager.Role.PartContour);
}
else
{
DrawRectOutline(ctx, pOx, pOy, pW, pH, DrawingStyleManager.Role.PartContour);
}
}
}
private static void DrawShaftRoundHeadUnifiedOutline(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double W, double H, double w, double r, double xf_left, double xf_right, double fx_L_tangTop, double fy_L_tangTop, double fx_L_tangBotX, double fy_L_tangBot, double fx_R_tangTop, double fy_R_tangTop, double fx_R_tangBotX, double fy_R_tangBot, bool needBreakLines, double xBreak, double breakWidth)
{
double Rm = (H * H) / (8.0 * w) + w / 2.0;
// -------- Left Unified End --------
double xInnerLeft = ox;
double xc_left = xInnerLeft - w + Rm;
Point2d C_m_L = new Point2d(xc_left, oy + H / 2.0);
Point2d C_fTop_L = new Point2d(xf_left, oy + H - r);
Point2d C_fBot_L = new Point2d(xf_left, oy + r);
var leftPoly = new Polyline();
if (r > 0.01)
{
double angTop1 = Math.PI / 2.0;
double angTop2 = Math.Atan2(fy_L_tangTop - C_fTop_L.Y, fx_L_tangTop - C_fTop_L.X);
double diffTop = angTop2 - angTop1;
while (diffTop < 0) diffTop += Math.PI * 2;
while (diffTop >= Math.PI * 2) diffTop -= Math.PI * 2;
double bulgeTop = Math.Tan(diffTop / 4.0);
double angM1 = Math.Atan2(fy_L_tangTop - C_m_L.Y, fx_L_tangTop - C_m_L.X);
double angM2 = Math.Atan2(fy_L_tangBot - C_m_L.Y, fx_L_tangBotX - C_m_L.X);
double diffM = angM2 - angM1;
while (diffM < 0) diffM += Math.PI * 2;
while (diffM >= Math.PI * 2) diffM -= Math.PI * 2;
double bulgeM = Math.Tan(diffM / 4.0);
double angBot1 = Math.Atan2(fy_L_tangBot - C_fBot_L.Y, fx_L_tangBotX - C_fBot_L.X);
double angBot2 = -Math.PI / 2.0;
double diffBot = angBot2 - angBot1;
while (diffBot < 0) diffBot += Math.PI * 2;
while (diffBot >= Math.PI * 2) diffBot -= Math.PI * 2;
double bulgeBot = Math.Tan(diffBot / 4.0);
leftPoly.AddVertexAt(0, new Point2d(xf_left, oy + H), bulgeTop, 0, 0);
leftPoly.AddVertexAt(1, new Point2d(fx_L_tangTop, fy_L_tangTop), bulgeM, 0, 0);
leftPoly.AddVertexAt(2, new Point2d(fx_L_tangBotX, fy_L_tangBot), bulgeBot, 0, 0);
leftPoly.AddVertexAt(3, new Point2d(xf_left, oy), 0, 0, 0);
}
else
{
double angM1 = Math.Atan2(oy + H - C_m_L.Y, xInnerLeft - C_m_L.X);
double angM2 = Math.Atan2(oy - C_m_L.Y, xInnerLeft - C_m_L.X);
double diffM = angM2 - angM1;
while (diffM < 0) diffM += Math.PI * 2;
while (diffM >= Math.PI * 2) diffM -= Math.PI * 2;
double bulgeM = Math.Tan(diffM / 4.0);
leftPoly.AddVertexAt(0, new Point2d(xInnerLeft, oy + H), bulgeM, 0, 0);
leftPoly.AddVertexAt(1, new Point2d(xInnerLeft, oy), 0, 0, 0);
}
ctx.Style?.Apply(leftPoly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(leftPoly);
ctx.Tr.AddNewlyCreatedDBObject(leftPoly, true);
var leftClosureLine = new Line(new Point3d(fx_L_tangTop, fy_L_tangTop, 0), new Point3d(fx_L_tangBotX, fy_L_tangBot, 0));
ctx.Style?.Apply(leftClosureLine, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(leftClosureLine);
ctx.Tr.AddNewlyCreatedDBObject(leftClosureLine, true);
// -------- Right Unified End --------
double xInnerRight = ox + W;
double xc_right = xInnerRight + w - Rm;
Point2d C_m_R = new Point2d(xc_right, oy + H / 2.0);
Point2d C_fTop_R = new Point2d(xf_right, oy + H - r);
Point2d C_fBot_R = new Point2d(xf_right, oy + r);
var rightPoly = new Polyline();
if (r > 0.01)
{
double angBot1 = -Math.PI / 2.0;
double angBot2 = Math.Atan2(fy_R_tangBot - C_fBot_R.Y, fx_R_tangBotX - C_fBot_R.X);
double diffBot = angBot2 - angBot1;
while (diffBot < 0) diffBot += Math.PI * 2;
while (diffBot >= Math.PI * 2) diffBot -= Math.PI * 2;
double bulgeBot = Math.Tan(diffBot / 4.0);
double angM1 = Math.Atan2(fy_R_tangBot - C_m_R.Y, fx_R_tangBotX - C_m_R.X);
double angM2 = Math.Atan2(fy_R_tangTop - C_m_R.Y, fx_R_tangTop - C_m_R.X);
double diffM = angM2 - angM1;
while (diffM < 0) diffM += Math.PI * 2;
while (diffM >= Math.PI * 2) diffM -= Math.PI * 2;
double bulgeM = Math.Tan(diffM / 4.0);
double angTop1 = Math.Atan2(fy_R_tangTop - C_fTop_R.Y, fx_R_tangTop - C_fTop_R.X);
double angTop2 = Math.PI / 2.0;
double diffTop = angTop2 - angTop1;
while (diffTop < 0) diffTop += Math.PI * 2;
while (diffTop >= Math.PI * 2) diffTop -= Math.PI * 2;
double bulgeTop = Math.Tan(diffTop / 4.0);
rightPoly.AddVertexAt(0, new Point2d(xf_right, oy), bulgeBot, 0, 0);
rightPoly.AddVertexAt(1, new Point2d(fx_R_tangBotX, fy_R_tangBot), bulgeM, 0, 0);
rightPoly.AddVertexAt(2, new Point2d(fx_R_tangTop, fy_R_tangTop), bulgeTop, 0, 0);
rightPoly.AddVertexAt(3, new Point2d(xf_right, oy + H), 0, 0, 0);
}
else
{
double angM1 = Math.Atan2(oy - C_m_R.Y, xInnerRight - C_m_R.X);
double angM2 = Math.Atan2(oy + H - C_m_R.Y, xInnerRight - C_m_R.X);
double diffM = angM2 - angM1;
while (diffM < 0) diffM += Math.PI * 2;
while (diffM >= Math.PI * 2) diffM -= Math.PI * 2;
double bulgeM = Math.Tan(diffM / 4.0);
rightPoly.AddVertexAt(0, new Point2d(xInnerRight, oy), bulgeM, 0, 0);
rightPoly.AddVertexAt(1, new Point2d(xInnerRight, oy + H), 0, 0, 0);
}
ctx.Style?.Apply(rightPoly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(rightPoly);
ctx.Tr.AddNewlyCreatedDBObject(rightPoly, true);
var rightClosureLine = new Line(new Point3d(fx_R_tangTop, fy_R_tangTop, 0), new Point3d(fx_R_tangBotX, fy_R_tangBot, 0));
ctx.Style?.Apply(rightClosureLine, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(rightClosureLine);
ctx.Tr.AddNewlyCreatedDBObject(rightClosureLine, true);
// -------- Horizontal Connectors --------
if (!needBreakLines)
{
var top = new Line(new Point3d(xf_left, oy + H, 0), new Point3d(xf_right, oy + H, 0));
var bot = new Line(new Point3d(xf_left, oy, 0), new Point3d(xf_right, oy, 0));
ctx.Style?.Apply(top, DrawingStyleManager.Role.OutlineBold);
ctx.Style?.Apply(bot, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(top);
ctx.Btr.AppendEntity(bot);
ctx.Tr.AddNewlyCreatedDBObject(top, true);
ctx.Tr.AddNewlyCreatedDBObject(bot, true);
}
else
{
var tL = new Line(new Point3d(xf_left, oy + H, 0), new Point3d(xBreak, oy + H, 0));
var tR = new Line(new Point3d(xBreak + breakWidth, oy + H, 0), new Point3d(xf_right, oy + H, 0));
var bL = new Line(new Point3d(xf_left, oy, 0), new Point3d(xBreak, oy, 0));
var bR = new Line(new Point3d(xBreak + breakWidth, oy, 0), new Point3d(xf_right, oy, 0));
ctx.Style?.Apply(tL, DrawingStyleManager.Role.OutlineBold);
ctx.Style?.Apply(tR, DrawingStyleManager.Role.OutlineBold);
ctx.Style?.Apply(bL, DrawingStyleManager.Role.OutlineBold);
ctx.Style?.Apply(bR, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(tL); ctx.Tr.AddNewlyCreatedDBObject(tL, true);
ctx.Btr.AppendEntity(tR); ctx.Tr.AddNewlyCreatedDBObject(tR, true);
ctx.Btr.AppendEntity(bL); ctx.Tr.AddNewlyCreatedDBObject(bL, true);
ctx.Btr.AppendEntity(bR); ctx.Tr.AddNewlyCreatedDBObject(bR, true);
}
}
// Legacy pure end arcs method removed as it is now unified inside DrawShaftRoundHeadUnifiedOutline
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 DrawHeadFilletRadiusLeader(FeatureDrivenDrawer.DrawingContext ctx, double cx, double cy, double r)
{
try
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyShaftFilletRadiusMax);
if (!val.HasValue || val.Value <= 0) return;
double angleDeg = 45; // 右上角向右上方画出
double angleRad = angleDeg * Math.PI / 180.0;
double px = cx + r * Math.Cos(angleRad);
double py = cy + r * Math.Sin(angleRad);
double ex = px + 25 * Math.Cos(angleRad);
double ey = py + 25 * Math.Sin(angleRad);
var line = new Line(new Point3d(px, py, 0), new Point3d(ex, ey, 0));
ctx.Style?.Apply(line, DrawingStyleManager.Role.Dimension);
line.ColorIndex = 4; // Cyan
ctx.Btr.AppendEntity(line);
ctx.Tr.AddNewlyCreatedDBObject(line, true);
double arrowLength = 5.0;
double arrowWidth = 1.5;
double baseX = px + arrowLength * Math.Cos(angleRad);
double baseY = py + arrowLength * Math.Sin(angleRad);
double perpAngle = angleRad + Math.PI / 2;
double p1X = baseX + (arrowWidth / 2) * Math.Cos(perpAngle);
double p1Y = baseY + (arrowWidth / 2) * Math.Sin(perpAngle);
double p2X = baseX - (arrowWidth / 2) * Math.Cos(perpAngle);
double p2Y = baseY - (arrowWidth / 2) * Math.Sin(perpAngle);
var arrow = new Solid(new Point3d(px, py, 0), new Point3d(p1X, p1Y, 0), new Point3d(p2X, p2Y, 0));
arrow.ColorIndex = 4;
ctx.Btr.AppendEntity(arrow);
ctx.Tr.AddNewlyCreatedDBObject(arrow, true);
var textStr = $"R\\U+2264{val.Value}";
var text = new DBText();
text.TextString = textStr;
text.Height = 3.5;
text.ColorIndex = 4; // Cyan
text.Rotation = angleRad;
text.HorizontalMode = TextHorizontalMode.TextCenter;
text.VerticalMode = TextVerticalMode.TextBottom;
double offsetX = 2.0 * Math.Cos(angleRad + Math.PI / 2);
double offsetY = 2.0 * Math.Sin(angleRad + Math.PI / 2);
var tp = new Point3d(ex + offsetX, ey + offsetY, 0);
text.AlignmentPoint = tp;
text.Position = tp;
ctx.Style?.Apply(text, DrawingStyleManager.Role.Text);
text.ColorIndex = 4;
ctx.Btr.AppendEntity(text);
ctx.Tr.AddNewlyCreatedDBObject(text, true);
}
catch { }
}
private static void DrawHorizontalCenterLine(FeatureDrivenDrawer.DrawingContext ctx, double centerY, double xLeft, double xRight, bool hasBreak = false, double xBreak = 0, double breakWidth = 0)
{
const double extend = 5.0;
if (!hasBreak)
{
var line = new Line(new Point3d(xLeft - extend, centerY, 0), new Point3d(xRight + extend, centerY, 0));
ctx.Style?.Apply(line, DrawingStyleManager.Role.Centerline);
ctx.Btr.AppendEntity(line);
ctx.Tr.AddNewlyCreatedDBObject(line, true);
}
else
{
// Left segment
var line1 = new Line(new Point3d(xLeft - extend, centerY, 0), new Point3d(xBreak, centerY, 0));
ctx.Style?.Apply(line1, DrawingStyleManager.Role.Centerline);
ctx.Btr.AppendEntity(line1);
ctx.Tr.AddNewlyCreatedDBObject(line1, true);
// Right segment
var line2 = new Line(new Point3d(xBreak + breakWidth, centerY, 0), new Point3d(xRight + extend, centerY, 0));
ctx.Style?.Apply(line2, DrawingStyleManager.Role.Centerline);
ctx.Btr.AppendEntity(line2);
ctx.Tr.AddNewlyCreatedDBObject(line2, true);
}
}
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("Diameter") || k.Contains("Length") || k.Contains("Radius") || k.Contains("Prime") || k.Contains("ShaftFillet"))
{
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;
}
/// <summary>
/// 绘制断线(使用 BreakLine 样式:白色 PHANTOM 双点划线)
/// </summary>
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);
}
// Legacy box-drawing method replaced.
/// <summary>
/// 绘制带断口的零件轮廓(在断线位置打断上下横线)
/// 支持自定义 Role (通常为 PartContour)
/// </summary>
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]
// 需要判断 xBreak 是否在当前矩形范围内
// 通常零件在锻件内部,且断线位置也会穿过零件
// 我们假设断线切断了矩形(如果 xBreak < x 或 xBreak > x+w应该做特殊处理这里暂不考虑极端情况
// 左段
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);
}
}
}
}