CadParamPluging/Cad/ShaftRawFreeForgeSquareShaftDrawer.cs

696 lines
32 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 ShaftRawFreeForgeSquareShaftDrawer
{
public static void Draw(CadContext ctx, ParamBag bag, Point3d center, double scaleFactor = 1.0)
{
if (ctx == null) throw new ArgumentNullException(nameof(ctx));
if (bag == null) throw new ArgumentNullException(nameof(bag));
var effectiveBag = scaleFactor < 1.0 ? ScaleParamBag(bag, scaleFactor) : bag;
var db = ctx.Database;
var tr = ctx.Transaction;
var prevDb = HostApplicationServices.WorkingDatabase;
HostApplicationServices.WorkingDatabase = db;
BlockTableRecord btr;
try
{
var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
}
finally
{
HostApplicationServices.WorkingDatabase = prevDb;
}
var context = new FeatureDrivenDrawer.DrawingContext
{
Ctx = ctx,
Bag = effectiveBag,
OriginalBag = bag,
Center = center,
DeliveryStatus = "毛料态",
StructuralFeature = "轴杆",
SpecialCondition = "方轴",
ProcessMethod = "自由锻",
Btr = btr,
Style = new DrawingStyleManager(db, tr)
};
DrawCore(context);
}
private static void DrawCore(FeatureDrivenDrawer.DrawingContext ctx)
{
var bag = ctx.Bag;
var size1 = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1);
var size2 = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2);
var size3 = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3);
var originalSize1 = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1);
if (!size1.HasValue || size1.Value <= 0 || !size2.HasValue || size2.Value <= 0)
{
return;
}
// 修正Size1 为横向总长Size2 为竖向高度
double S1 = size1.Value;
double S2 = size2.Value;
double S3 = size3.HasValue && size3.Value > 0 ? size3.Value : 0;
double originalS1 = originalSize1.HasValue ? originalSize1.Value : S1;
double ox = ctx.Center.X - S1 / 2.0;
double oy = ctx.Center.Y - S2 / 2.0;
var filletRParam = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftFilletRadiusMax);
double filletR = filletRParam.HasValue && filletRParam.Value > 0 ? filletRParam.Value : 0;
double maxR = Math.Min(S1 / 2.0, S2 / 2.0);
if (filletR > maxR) filletR = maxR;
// 判断是否需要断线
bool needBreakLines = originalS1 > 150;
const double lineSpacing = 3.5;
// 1. Draw Main View - 如果需要断线,则绘制带缺口的轮廓
double xBreak = ox + S1 / 4.0;
// 计算平滑相切数据模型
double arcHeight = S2 / 5.0;
double r = filletR;
double w = arcHeight;
double Rm = (S2 * S2) / (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) - (S2 / 2.0 - r) * (S2 / 2.0 - r))) : (Rm - w);
double xf_left = r > 0 ? xc_left - D_tangent : xInnerLeft;
double xInnerRight = ox + S1;
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 + S2 / 2.0) + (Rm / (Rm - r)) * ((oy + r) - (oy + S2 / 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 + S2 / 2.0) + (Rm / (Rm - r)) * ((oy + r) - (oy + S2 / 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 + S2 / 2.0) + (Rm / (Rm - r)) * ((oy + S2 - r) - (oy + S2 / 2.0)) : oy + S2;
double fx_R_tangTop = r > 0 ? xc_right + (Rm / (Rm - r)) * (xf_right - xc_right) : xInnerRight;
double fy_R_tangTop = r > 0 ? (oy + S2 / 2.0) + (Rm / (Rm - r)) * ((oy + S2 - r) - (oy + S2 / 2.0)) : oy + S2;
// 1. 绘制主体轮廓 (矩形 + 平滑相切圆角) 和左右端弧线一体化
double sectionOxArg = S3 > 0 ? (ox + S1 * 2.0 / 3.0 - S3 / 2.0) : 0;
double sectionWArg = S3;
DrawShaftRoundHeadUnifiedOutline(ctx, ox, oy, S1, S2, 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, sectionOxArg, sectionWArg);
// 2. 中心线 (贯穿左右水平方向)
double clY = oy + S2 / 2.0;
var centerLine = new Line(new Point3d(ox - 10, clY, 0), new Point3d(ox + S1 + 10, clY, 0));
ctx.Style?.Apply(centerLine, DrawingStyleManager.Role.Centerline);
ctx.Btr.AppendEntity(centerLine);
ctx.Tr.AddNewlyCreatedDBObject(centerLine, true);
// 4. Draw Break Lines if needed
if (needBreakLines)
{
DrawBreakLines(ctx, ox, oy, S1, S2);
}
// 3. Draw Section if S3 > 0
if (S3 > 0)
{
double sectionW = S3;
double sectionH = S2;
double sectionOx = ox + S1 * 2.0 / 3.0 - sectionW / 2.0; // 剖面位于右边1/3处
double sectionOy = oy;
double maxRSec = Math.Min(sectionW / 2.0, sectionH / 2.0);
double filletRSec = (filletR > maxRSec) ? maxRSec : filletR;
var sectionPoly = CreateRectPoly(sectionOx, sectionOy, sectionW, sectionH, filletRSec);
ctx.Style?.Apply(sectionPoly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(sectionPoly);
ctx.Tr.AddNewlyCreatedDBObject(sectionPoly, true);
CreateHatchForPolyline(ctx, sectionPoly);
}
// 4. Dimensions
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1) ?? S1;
var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize1);
var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1TolPlus);
var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1TolMinus);
var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize1TolPlus);
var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize1TolMinus);
var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr);
var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1Prime);
if (valPrime.HasValue && valPrime.Value > 0)
{
dimText += @"\X(" + FeatureDrivenDrawer.FormatDimNumber(valPrime.Value) + ")";
}
double dimY = oy - 25;
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);
}
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2) ?? S2;
var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize2);
var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2TolPlus);
var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2TolMinus);
var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize2TolPlus);
var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize2TolMinus);
var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr);
var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2Prime);
if (valPrime.HasValue && valPrime.Value > 0)
{
dimText += @"\X(" + FeatureDrivenDrawer.FormatDimNumber(valPrime.Value) + ")";
}
double dimX = ox + S1 + 20 + arcHeight;
FeatureDrivenDrawer.AddLinearDim(ctx, new Point3d(xf_right, oy, 0), new Point3d(xf_right, oy + S2, 0), new Point3d(dimX, ctx.Center.Y, 0), 90, dimText);
}
// 补加未注侧倒角标注指示
if (filletR > 0)
{
double cxRight = xf_right;
double cyTop = oy + S2 - filletR;
DrawHeadFilletRadiusLeader(ctx, cxRight, cyTop, filletR);
}
if (S3 > 0)
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3) ?? S3;
var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize3);
var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3TolPlus);
var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3TolMinus);
var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize3TolPlus);
var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize3TolMinus);
var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr);
var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3Prime);
if (valPrime.HasValue && valPrime.Value > 0)
{
dimText += @"\X(" + FeatureDrivenDrawer.FormatDimNumber(valPrime.Value) + ")";
}
double dimY = oy + S2 + 20;
double sectionOx = ox + S1 * 2.0 / 3.0 - S3 / 2.0; // 标注位置对应剖面
double dimOriginY = oy + S2 - filletR;
FeatureDrivenDrawer.AddLinearDim(ctx, new Point3d(sectionOx, dimOriginY, 0), new Point3d(sectionOx + S3, dimOriginY, 0), new Point3d(ctx.Center.X, dimY, 0), 0, dimText);
}
var hardnessVal = bag.GetString(FeatureDrivenDrawer.KeyHardness);
if (!string.IsNullOrWhiteSpace(hardnessVal) && hardnessVal != "空")
{
double xStart = (S3 > 0) ? ctx.Center.X : (ox + S1 / 2.0);
double yStart = oy;
FeatureDrivenDrawer.DrawHardnessSymbol(ctx, xStart, yStart, hardnessVal);
}
var markingText = bag.GetString(FeatureDrivenDrawer.KeyMarkingContent);
if (!string.IsNullOrWhiteSpace(markingText))
{
double xTarget = (S3 > 0) ? ctx.Center.X : (ox + S1 / 2.0);
double yTarget = oy + S2;
FeatureDrivenDrawer.DrawSpecialHBLeaderToTop(ctx, xTarget, yTarget, markingText);
}
var s1Prime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1Prime);
var s2Prime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2Prime);
if (s1Prime.HasValue && s1Prime.Value > 0 && s2Prime.HasValue && s2Prime.Value > 0)
{
// Size1 对应横向总长Size2 对应竖向高度
double pL = s1Prime.Value;
double pH = s2Prime.Value;
double pOx = ctx.Center.X - pL / 2.0;
double pOy = ctx.Center.Y - pH / 2.0;
if (needBreakLines)
{
DrawRectOutlineWithBreak(ctx, pOx, pOy, pL, pH, xBreak, lineSpacing, DrawingStyleManager.Role.PartContour);
}
else
{
DrawRectOutline(ctx, pOx, pOy, pL, pH, DrawingStyleManager.Role.PartContour);
}
}
}
/// <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);
}
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 sectionOx, double sectionW)
{
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 --------
Action<double> drawHoriz = (yLine) =>
{
var segments = new List<Tuple<double, double>>();
segments.Add(Tuple.Create(xf_left, xf_right));
if (needBreakLines)
{
var newSegs = new List<Tuple<double, double>>();
foreach(var seg in segments)
{
if (xBreak > seg.Item1 && (xBreak + breakWidth) < seg.Item2)
{
newSegs.Add(Tuple.Create(seg.Item1, xBreak));
newSegs.Add(Tuple.Create(xBreak + breakWidth, seg.Item2));
}
else newSegs.Add(seg);
}
segments = newSegs;
}
if (sectionW > 0)
{
double secR = r;
double maxR = Math.Min(sectionW / 2.0, H / 2.0);
if (secR > maxR) secR = maxR;
var newSegs = new List<Tuple<double, double>>();
foreach(var seg in segments)
{
if (sectionOx > seg.Item1 && (sectionOx + sectionW) < seg.Item2)
{
newSegs.Add(Tuple.Create(seg.Item1, sectionOx + secR));
newSegs.Add(Tuple.Create(sectionOx + sectionW - secR, seg.Item2));
}
else newSegs.Add(seg);
}
segments = newSegs;
}
foreach(var seg in segments)
{
if (seg.Item2 > seg.Item1 + 0.01) {
var l = new Line(new Point3d(seg.Item1, yLine, 0), new Point3d(seg.Item2, yLine, 0));
ctx.Style?.Apply(l, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(l);
ctx.Tr.AddNewlyCreatedDBObject(l, true);
}
}
};
drawHoriz(oy + H); // top
drawHoriz(oy); // bot
}
private static void DrawHeadFilletRadiusLeader(FeatureDrivenDrawer.DrawingContext ctx, double cx, double cy, double r)
{
try
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftFilletRadiusMax);
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 DrawRectWithFillets(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double w, double h, double r, DrawingStyleManager.Role role = DrawingStyleManager.Role.OutlineBold)
{
var poly = CreateRectPoly(x, y, w, h, r);
ctx.Style?.Apply(poly, role);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
}
private static Polyline CreateRectPoly(double x, double y, double w, double h, double r)
{
var poly = new Polyline();
if (r < 0.01)
{
poly.AddVertexAt(0, new Point2d(x, y), 0, 0, 0);
poly.AddVertexAt(1, new Point2d(x + w, y), 0, 0, 0);
poly.AddVertexAt(2, new Point2d(x + w, y + h), 0, 0, 0);
poly.AddVertexAt(3, new Point2d(x, y + h), 0, 0, 0);
}
else
{
var bulge = Math.Tan(Math.PI / 8.0);
poly.AddVertexAt(0, new Point2d(x + r, y), 0, 0, 0);
poly.AddVertexAt(1, new Point2d(x + w - r, y), bulge, 0, 0);
poly.AddVertexAt(2, new Point2d(x + w, y + r), 0, 0, 0);
poly.AddVertexAt(3, new Point2d(x + w, y + h - r), bulge, 0, 0);
poly.AddVertexAt(4, new Point2d(x + w - r, y + h), 0, 0, 0);
poly.AddVertexAt(5, new Point2d(x + r, y + h), bulge, 0, 0);
poly.AddVertexAt(6, new Point2d(x, y + h - r), 0, 0, 0);
poly.AddVertexAt(7, new Point2d(x, y + r), bulge, 0, 0);
}
poly.Closed = true;
return poly;
}
private static void DrawRectOutline(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double w, double h, DrawingStyleManager.Role role)
{
var poly = new Polyline();
poly.AddVertexAt(0, new Point2d(x, y), 0, 0, 0);
poly.AddVertexAt(1, new Point2d(x + w, y), 0, 0, 0);
poly.AddVertexAt(2, new Point2d(x + w, y + h), 0, 0, 0);
poly.AddVertexAt(3, new Point2d(x, y + h), 0, 0, 0);
poly.Closed = true;
ctx.Style?.Apply(poly, role);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
}
private static void CreateHatchForPolyline(FeatureDrivenDrawer.DrawingContext ctx, Polyline boundary)
{
try
{
var hatch = new Hatch();
hatch.SetDatabaseDefaults();
hatch.Normal = new Vector3d(0, 0, 1);
hatch.Elevation = 0.0;
ctx.Btr.AppendEntity(hatch);
ctx.Tr.AddNewlyCreatedDBObject(hatch, true);
hatch.SetHatchPattern(HatchPatternType.PreDefined, "ANSI31");
hatch.PatternScale = 10;
hatch.PatternAngle = 0;
hatch.Associative = false;
ctx.Style?.Apply(hatch, DrawingStyleManager.Role.Hatch);
var ids = new ObjectIdCollection();
ids.Add(boundary.ObjectId);
hatch.AppendLoop(HatchLoopTypes.External, ids);
hatch.EvaluateHatch(true);
}
catch
{
}
}
private static ParamBag ScaleParamBag(ParamBag original, double scaleFactor)
{
if (original == null) return null;
if (Math.Abs(scaleFactor - 1.0) < 0.000001) return original;
var newBag = new ParamBag();
foreach(var k in original.GetKeys())
{
var v = original.GetString(k);
if (k.Contains("SquareShaftSize") || k.Contains("Radius") || k.Contains("Prime"))
{
if (double.TryParse(v, out var d))
{
newBag.Set(k, (d * scaleFactor).ToString("0.###"));
}
else
{
newBag.Set(k, v);
}
}
else
{
newBag.Set(k, v);
}
}
return newBag;
}
// (Legacy EndArcs logic replaced by unified drawing)
/// <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]
// 左段
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);
}
}
}
}