feat: 新增自由锻毛料态方轴和圆轴的CAD绘制功能。

This commit is contained in:
sladro 2026-02-05 11:40:52 +08:00
parent d876d663a4
commit 5c256c06d3
3 changed files with 241 additions and 243 deletions

View File

@ -8,20 +8,26 @@ namespace CadParamPluging.Cad
{
// 对应 TemplateSchemaDefaults.cs 中的定义
// ProjectType = "毛料态", DrawingType = "自由锻", SheetSize = "轴杆", Scale = "圆轴"
// 这里的 Scale 对应 SpecialCondition
public static readonly string Key = TemplateKeyBuilder.Build("毛料态", "自由锻", "轴杆", "圆轴");
public string TemplateKey => Key;
public FeatureDrivenDrawer.ExpectedDrawingSize CalculateExpectedSize(ParamBag bag, TemplateParams templateParams)
{
var diameter = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameter) ?? 0;
var length = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyLength) ?? 0;
var d = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameter) ?? 0;
var l = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyLength) ?? 0;
// 根据用户要求:直径是图纸宽度,长度是图纸高度
double activeWidth = d;
double activeHeight = l;
var extraMargin = 40;
return new FeatureDrivenDrawer.ExpectedDrawingSize
{
Width = length + extraMargin * 2,
Height = diameter + extraMargin * 2
Width = activeWidth + extraMargin * 2,
Height = activeHeight + extraMargin * 2
};
}

View File

@ -42,7 +42,7 @@ namespace CadParamPluging.Cad
SpecialCondition = "圆轴",
ProcessMethod = "自由锻",
Btr = btr,
Style = new DrawingStyleManager(db, tr) // Reusing existing StyleManager
Style = new DrawingStyleManager(db, tr)
};
DrawCore(context);
@ -52,132 +52,130 @@ namespace CadParamPluging.Cad
{
var bag = ctx.Bag;
// Parameters
var diameter = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameter);
var length = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyLength);
var dia = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameter);
var len = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyLength);
if (!diameter.HasValue || diameter.Value <= 0 || !length.HasValue || length.Value <= 0)
if (!dia.HasValue || dia.Value <= 0 || !len.HasValue || len.Value <= 0)
{
return;
}
double D = diameter.Value;
double L = length.Value;
// 逻辑要求:直径是宽度,长度是高度
double W = dia.Value;
double H = len.Value;
// Visual Size Calculation
// Keep aspect ratio but maybe limit if too extreme?
// For now, draw 1:1 visually unless scaled by scaleFactor (which is handled in bag).
// Calculate coordinates (Center is geometric center)
double ox = ctx.Center.X - L / 2.0;
double oy = ctx.Center.Y - D / 2.0;
double ox = ctx.Center.X - W / 2.0;
double oy = ctx.Center.Y - H / 2.0;
// 1. Draw Shaft Outline (Rectangle with optional fillets)
var filletRParam = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyShaftFilletRadiusMax);
double filletR = filletRParam.HasValue && filletRParam.Value > 0 ? filletRParam.Value : 0;
// Limit fillet radius
double maxR = Math.Min(D / 2.0, L / 2.0);
double maxR = Math.Min(W / 2.0, H / 2.0);
if (filletR > maxR) filletR = maxR;
DrawShaftOutline(ctx, ox, oy, L, D, filletR);
// 1. 绘制主体轮廓 (矩形 + 圆角) - 保持原来的白色边框
DrawRectWithFillets(ctx, ox, oy, W, H, filletR, DrawingStyleManager.Role.OutlineBold);
// 2. Draw Symmetry Axis
DrawSymmetryAxis(ctx, ox, oy, L, D);
// 2. 绘制左右两端的弧线(向外凸出)
// 弧高设为 H/5高度的1/5确保弧高小于半弦长
double arcHeight = H / 5.0;
DrawEndArcs(ctx, ox, oy, W, H, arcHeight);
// 3. Draw Part Contour (Yellow dashed)
var diameterPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterPrime);
var lengthPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyLengthPrime);
// 3. 绘制中心线 (横向,在中间位置)
DrawHorizontalCenterLine(ctx, ctx.Center.Y, ox, ox + W);
if (diameterPrime.HasValue && diameterPrime.Value > 0 && lengthPrime.HasValue && lengthPrime.Value > 0)
{
double partD = diameterPrime.Value;
double partL = lengthPrime.Value;
// Center part contour
double partOx = ctx.Center.X - partL / 2.0;
double partOy = ctx.Center.Y - partD / 2.0;
DrawPartContour(ctx, partOx, partOy, partL, partD);
}
// 4. Dimensions
// 3. 尺寸标注
// Length Dimension (Bottom)
// 3.1 直径标注 (底部)
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyLength) ?? L;
var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyLength);
var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyLengthTolPlus);
var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyLengthTolMinus);
var dimText = BuildDimensionText(FormatDimNumber(val, str), tolPlus, tolMinus);
// Add Part Length (Prime) below
var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyLengthPrime);
if (valPrime.HasValue && valPrime.Value > 0)
{
dimText += $"\\X({FormatDimNumber(valPrime.Value)})";
}
// Place below
double dimY = oy - 20; // Offset downwards? Usually dependent on margin
// Let's use a standard offset. If D is small, 20 is fine.
AddLinearDim(
ctx,
new Point3d(ox, oy, 0),
new Point3d(ox + L, oy, 0),
new Point3d(ctx.Center.X, dimY, 0),
0,
dimText);
}
// Diameter Dimension (Right side usually for shafts, or put on side)
// Vertical dimension for Diameter
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameter) ?? D;
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameter) ?? W;
var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyDiameter);
var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterTolPlus);
var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterTolMinus);
// Prefix with %%c for diameter
var dimText = BuildDimensionText("%%c" + FormatDimNumber(val, str), tolPlus, tolMinus);
// Add Part Diameter (Prime) below
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{FormatDimNumber(valPrime.Value)})";
dimText += @"\X(%%c" + FeatureDrivenDrawer.FormatDimNumber(valPrime.Value) + ")";
}
double dimX = ox + L + 20;
double dimY = oy - 25;
double dimOriginY = oy + filletR;
AddLinearDim(
ctx,
new Point3d(ox + L, oy, 0),
new Point3d(ox + L, oy + D, 0),
new Point3d(dimX, ctx.Center.Y, 0),
90,
dimText);
FeatureDrivenDrawer.AddLinearDim(ctx, new Point3d(ox, dimOriginY, 0), new Point3d(ox + W, dimOriginY, 0), new Point3d(ctx.Center.X, dimY, 0), 0, dimText);
}
// Unspecified Fillet Note
if (filletR > 0)
// 3.2 长度标注 (右侧)
{
// Usually text near the drawing or a general note.
// Ring template puts it at bottom left/right.
// Let's place it at top left.
// "未注圆角 R<=..."
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyLength) ?? H;
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 dimX = ox + W + 20;
double dimOriginX = ox + W - filletR;
// Construct text
string note = $"未注圆角 R≤{FormatDimNumber(filletR)}";
// Position: Top Left, slightly above
DrawSimpleText(ctx, new Point3d(ox, oy + D + 10, 0), note, 3.5);
FeatureDrivenDrawer.AddLinearDim(ctx, new Point3d(dimOriginX, oy, 0), new Point3d(dimOriginX, oy + H, 0), new Point3d(dimX, ctx.Center.Y, 0), 90, dimText);
}
// 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 = diaPrime.Value; // Diameter -> Width
double pH = lenPrime.Value; // Length -> Height
double pOx = ctx.Center.X - pW / 2.0;
double pOy = ctx.Center.Y - pH / 2.0;
DrawRectOutline(ctx, pOx, pOy, pW, pH, DrawingStyleManager.Role.PartContour);
}
}
private static void DrawShaftOutline(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double w, double h, double r)
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();
@ -192,54 +190,21 @@ namespace CadParamPluging.Cad
{
var bulge = Math.Tan(Math.PI / 8.0);
// Bottom-Left corner
poly.AddVertexAt(0, new Point2d(x + r, y), 0, 0, 0); // Start of bottom line
// Bottom-Right corner
poly.AddVertexAt(1, new Point2d(x + w - r, y), bulge, 0, 0); // Arc start
poly.AddVertexAt(2, new Point2d(x + w, y + r), 0, 0, 0); // Right line start
// Top-Right corner
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);
// Top-Left corner
poly.AddVertexAt(5, new Point2d(x + r, y + h), bulge, 0, 0);
poly.AddVertexAt(6, new Point2d(x, y + h - r), 0, 0, 0);
// Back to bottom-left arc
poly.AddVertexAt(7, new Point2d(x, y + r), bulge, 0, 0);
}
poly.Closed = true;
ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
// Hatching? Shafts are usually not hatched unless sectioned.
// "Raw State Free Forging" might be just the outline.
// Ring templates hatch because they are sections. Shaft is usually full view.
// But if user wants a "template", maybe it mimics others?
// Ring Free Forge has hatching. Block has hatching in section.
// If this is a SECTION of a shaft (which is just a circle?), no.
// Should be side view. No hatching typically.
return poly;
}
private static void DrawSymmetryAxis(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double w, double h)
{
// Horizontal axis? Shafts are usually horizontal.
// Center Y = y + h/2
double midY = y + h / 2.0;
double extend = w * 0.1;
if (extend > 15) extend = 15;
var line = new Line(new Point3d(x - extend, midY, 0), new Point3d(x + w + extend, midY, 0));
ctx.Style?.Apply(line, DrawingStyleManager.Role.Centerline);
ctx.Btr.AppendEntity(line);
ctx.Tr.AddNewlyCreatedDBObject(line, true);
}
private static void DrawPartContour(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double w, double h)
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);
@ -248,122 +213,92 @@ namespace CadParamPluging.Cad
poly.AddVertexAt(3, new Point2d(x, y + h), 0, 0, 0);
poly.Closed = true;
ctx.Style?.Apply(poly, DrawingStyleManager.Role.PartContour); // Yellow Dashed
ctx.Style?.Apply(poly, role);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
}
// --- Helpers copied/adapted to ensure isolation ---
/// <summary>
/// 绘制左右两端的弧线(向外凸出)
/// 使用Polyline的bulge凸度值绘制确保端点精确对齐
/// </summary>
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
// 计算凸度 bulge
// bulge = tan(theta/4),其中 theta 是圆弧对应的圆心角
// 或者使用 bulge = sagitta / (chordLength / 2) 的近似公式
// 更精确的公式bulge = 2 * sagitta / chordLength当弧线较小时
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
}
}
private static void DrawHorizontalCenterLine(FeatureDrivenDrawer.DrawingContext ctx, double centerY, double xLeft, double xRight)
{
const double extend = 5.0;
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);
}
private static ParamBag ScaleParamBag(ParamBag original, double scaleFactor)
{
if (original == null) return null;
if (Math.Abs(scaleFactor - 1.0) < 0.000001) return original;
// Simplified copy for specific keys
var newBag = new ParamBag();
foreach(var k in original.GetKeys())
{
var v = original.GetString(k);
if (IsScaleableKey(k) && double.TryParse(v, out var d))
{
newBag.Set(k, (d * scaleFactor).ToString("0.###"));
}
else
{
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;
}
private static bool IsScaleableKey(string key)
{
// List relevant keys for this template
return key.StartsWith("Diameter") || key.StartsWith("Length") || key.EndsWith("Prime") || key.Contains("Radius");
}
private static void AddLinearDim(FeatureDrivenDrawer.DrawingContext ctx, Point3d p1, Point3d p2, Point3d ptDim, double rot, string text)
{
try
{
var dim = new RotatedDimension();
dim.SetDatabaseDefaults();
dim.XLine1Point = p1;
dim.XLine2Point = p2;
dim.DimLinePoint = ptDim;
dim.Rotation = rot * Math.PI / 180.0;
dim.DimensionStyle = ctx.Db.Dimstyle;
dim.DimensionText = text;
// Force Green
dim.ColorIndex = 3;
// Basic overrides if possible
// Using reflection setup similar to other files
SetDimColor(dim, "Dimclrd", 3);
SetDimColor(dim, "Dimclre", 3);
SetDimColor(dim, "Dimclrt", 3);
SetDimBool(dim, "Dimtofl", true);
ctx.Style?.Apply(dim, DrawingStyleManager.Role.Dimension);
dim.ColorIndex = 3;
ctx.Btr.AppendEntity(dim);
ctx.Tr.AddNewlyCreatedDBObject(dim, true);
}
}
catch {}
}
private static void DrawSimpleText(FeatureDrivenDrawer.DrawingContext ctx, Point3d pos, string text, double height)
{
try
{
var mtxt = new MText();
mtxt.SetDatabaseDefaults();
mtxt.Location = pos;
mtxt.Contents = text;
mtxt.TextHeight = height;
mtxt.Attachment = AttachmentPoint.BottomLeft;
ctx.Style?.Apply(mtxt, DrawingStyleManager.Role.Text);
ctx.Btr.AppendEntity(mtxt);
ctx.Tr.AddNewlyCreatedDBObject(mtxt, true);
}
catch {}
}
private static string FormatDimNumber(double value, string rawInput = null)
{
// Simplified formatter
return value.ToString("0.###");
}
private static string BuildDimensionText(string baseText, double? tolPlus, double? tolMinus)
{
if (!tolPlus.HasValue && !tolMinus.HasValue) return baseText;
if (tolPlus.HasValue && tolMinus.HasValue && Math.Abs(Math.Abs(tolPlus.Value) - Math.Abs(tolMinus.Value)) < 0.00001)
{
return $"{baseText}%%p{Math.Abs(tolPlus.Value):0.###}";
}
string p = tolPlus.HasValue ? (tolPlus.Value >= 0 ? "+" : "") + tolPlus.Value.ToString("0.###") : "0";
string m = tolMinus.HasValue ? tolMinus.Value.ToString("0.###") : "0";
return $"{baseText}\\S{p}^{m};";
}
// Reflection helpers
private static void SetDimColor(Dimension dim, string prop, int colorIndex)
{
try {
var p = dim.GetType().GetProperty(prop);
if (p != null) p.SetValue(dim, Autodesk.AutoCAD.Colors.Color.FromColorIndex(Autodesk.AutoCAD.Colors.ColorMethod.ByAci, (short)colorIndex));
} catch {}
}
private static void SetDimBool(Dimension dim, string prop, bool val)
{
try { dim.GetType().GetProperty(prop)?.SetValue(dim, val); } catch {}
return newBag;
}
}
}

View File

@ -92,7 +92,15 @@ namespace CadParamPluging.Cad
DrawRectWithFillets(ctx, ox, oy, S1, S2, filletR, DrawingStyleManager.Role.OutlineBold);
}
// 2. Draw Break Lines if needed
// 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);
// 4. Draw Break Lines if needed
if (needBreakLines)
{
DrawBreakLines(ctx, ox, oy, S1, S2);
@ -387,6 +395,55 @@ namespace CadParamPluging.Cad
}
return newBag;
}
/// <summary>
/// 绘制左右两端的弧线(向外凸出)
/// 使用Polyline的bulge凸度值绘制确保端点精确对齐
/// </summary>
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
}
}
private static void DrawHorizontalCenterLine(FeatureDrivenDrawer.DrawingContext ctx, double centerY, double xLeft, double xRight)
{
const double extend = 5.0;
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);
}
}
}