696 lines
32 KiB
C#
696 lines
32 KiB
C#
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);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|