919 lines
42 KiB
C#
919 lines
42 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 BlockRawFreeForgeRoundHeadDrawer
|
||
{
|
||
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)
|
||
};
|
||
|
||
DrawBlockRawFreeForgeRoundHeadCore(context);
|
||
}
|
||
|
||
private static void DrawBlockRawFreeForgeRoundHeadCore(FeatureDrivenDrawer.DrawingContext ctx)
|
||
{
|
||
var bag = ctx.Bag;
|
||
|
||
// BoxSize1 (Width - 总长度)
|
||
// BoxSize2 (Height - 高度/直径)
|
||
var width = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize1);
|
||
var height = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize2);
|
||
|
||
if (!width.HasValue || width.Value <= 0 || !height.HasValue || height.Value <= 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
double H = height.Value;
|
||
double W = width.Value;
|
||
|
||
// 外轮廓圆弧:高度固定为 H/5
|
||
// 依据用户新需求 (2026-01-29): 黄色部分(圆弧高)是粉色部分(总高H)的1/5
|
||
double arcHeight = H / 5.0;
|
||
|
||
// 视觉比例:总宽度映射
|
||
double visualTotalW = H * 3.0; // 保持视觉宽高比约 3:1
|
||
|
||
// 绘图坐标计算 (保持居中)
|
||
double ox = ctx.Center.X - visualTotalW / 2.0; // 左边界 (圆弧最左端)
|
||
double oy = ctx.Center.Y - H / 2.0; // 底边
|
||
|
||
// 内框边界(从左圆弧弦线到右圆弧弦线)
|
||
// 注意:ox 是圆弧顶点,xInnerLeft 应该是弦线位置
|
||
double xInnerLeft = ox + arcHeight;
|
||
double xInnerRight = ox + visualTotalW - arcHeight;
|
||
double innerWidth = xInnerRight - xInnerLeft;
|
||
|
||
// 获取圆头处圆角半径 (BoxRoundHeadFilletRadiusMax) - 用于外侧圆角
|
||
// 依据用户需求:外侧圆角由“圆头处圆角半径”控制
|
||
var headFilletParam = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxRoundHeadFilletRadiusMax);
|
||
double headFilletR = headFilletParam.HasValue && headFilletParam.Value > 0
|
||
? headFilletParam.Value
|
||
: 0;
|
||
|
||
// 获取内框圆角参数:优先取 UnspecifiedFilletRadiusMax,如果没有则取 BoxFilletRadiusMax - 用于内部剖面
|
||
var innerFilletParam = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyUnspecifiedFilletRadiusMax);
|
||
if (!innerFilletParam.HasValue || innerFilletParam.Value <= 0)
|
||
{
|
||
innerFilletParam = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxFilletRadiusMax);
|
||
}
|
||
|
||
double sectionFilletR = innerFilletParam.HasValue && innerFilletParam.Value > 0
|
||
? innerFilletParam.Value
|
||
: 0;
|
||
|
||
// 2. 绘制分段式内框(左、中、右三段)以支持中间剖面区域的独立圆角
|
||
// 中间区域(剖面)作为主体,如果设置了圆角,四个角都应为圆角
|
||
|
||
// 计算视觉上的剖面宽度
|
||
// 依据用户需求:尺寸3 (BoxSize3) 对应剖面的宽
|
||
var size3 = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize3);
|
||
double visualSectionWidth;
|
||
|
||
if (size3.HasValue && size3.Value > 0)
|
||
{
|
||
// 按比例映射:VisualW / PhysicalW
|
||
double scale = visualTotalW / W;
|
||
visualSectionWidth = size3.Value * scale;
|
||
|
||
// 限制最大宽度,防止出错
|
||
if (visualSectionWidth > innerWidth * 0.95)
|
||
{
|
||
visualSectionWidth = innerWidth * 0.95;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 降级策略
|
||
visualSectionWidth = innerWidth / 3.0;
|
||
}
|
||
|
||
// 居中布置剖面
|
||
double sectionOffset = (innerWidth - visualSectionWidth) / 2.0;
|
||
double xSectionLeft = xInnerLeft + sectionOffset;
|
||
double xSectionRight = xSectionLeft + visualSectionWidth;
|
||
|
||
// 绘制中间剖面框(带圆角)
|
||
// 使用 sectionFilletR
|
||
DrawBoxSectionContourWithFillet(ctx, xSectionLeft, xSectionRight, oy, H, sectionFilletR);
|
||
|
||
// Calculate effective head fillet R (clamped by side frame width)
|
||
double sideFrameWidth = xSectionLeft - xInnerLeft;
|
||
double maxR = Math.Min(sideFrameWidth * 0.5, H * 0.5);
|
||
double effectiveHeadR = Math.Min(headFilletR, maxR);
|
||
|
||
double Rm = (H * H) / (8.0 * arcHeight) + arcHeight / 2.0;
|
||
double D_tangent = (Rm >= effectiveHeadR) ? Math.Sqrt(Math.Max(0, (Rm - effectiveHeadR) * (Rm - effectiveHeadR) - (H / 2.0 - effectiveHeadR) * (H / 2.0 - effectiveHeadR))) : (Rm - arcHeight);
|
||
|
||
double xf_left = effectiveHeadR > 0 ? (xInnerLeft + Rm - arcHeight) - D_tangent : xInnerLeft;
|
||
double xf_right = effectiveHeadR > 0 ? (xInnerRight - Rm + arcHeight) + D_tangent : xInnerRight;
|
||
|
||
double xc_left = xInnerLeft + Rm - arcHeight;
|
||
double fx_L_tang = effectiveHeadR > 0 ? xc_left + (Rm / (Rm - effectiveHeadR)) * (xf_left - xc_left) : xInnerLeft;
|
||
double fy_L_tangBot = effectiveHeadR > 0 ? (oy + H / 2.0) + (Rm / (Rm - effectiveHeadR)) * ((oy + effectiveHeadR) - (oy + H / 2.0)) : oy;
|
||
|
||
double xc_right = xInnerRight - Rm + arcHeight;
|
||
double fx_R_tang = effectiveHeadR > 0 ? xc_right + (Rm / (Rm - effectiveHeadR)) * (xf_right - xc_right) : xInnerRight;
|
||
double fy_R_tangBot = effectiveHeadR > 0 ? (oy + H / 2.0) + (Rm / (Rm - effectiveHeadR)) * ((oy + effectiveHeadR) - (oy + H / 2.0)) : oy;
|
||
|
||
// 绘制左侧框线(只画横向连接线)
|
||
DrawBoxSideFrame(ctx, xf_left, xSectionLeft + sectionFilletR, oy, H, 0, isLeft: true);
|
||
|
||
// 绘制右侧框线(只画横向连接线)
|
||
DrawBoxSideFrame(ctx, xSectionRight - sectionFilletR, xf_right, oy, H, 0, isLeft: false);
|
||
|
||
// 1. 绘制完整锻件外轮廓(方体有圆头 - 白色,大圆弧及外侧平滑过渡圆角)
|
||
DrawBlockRoundHeadOutline(ctx, ox, oy, visualTotalW, H, arcHeight, effectiveHeadR, xf_left, xf_right);
|
||
|
||
// 绘制圆角的斜向标注(如果存在圆角):4-R<=*
|
||
if (effectiveHeadR > 0)
|
||
{
|
||
// 左上角
|
||
double yTop = oy + H;
|
||
double cxLeft = xf_left;
|
||
double cyLeft = yTop - effectiveHeadR;
|
||
DrawHeadFilletRadiusLeader(ctx, cxLeft, cyLeft, effectiveHeadR, true);
|
||
|
||
// 根据需求,左右都标注了的话,只保留一个(左上角),去除右上角标注
|
||
// 右上角
|
||
// double cxRight = xInnerRight - effectiveHeadR;
|
||
// DrawHeadFilletRadiusLeader(ctx, cxRight, cyLeft, effectiveHeadR, false);
|
||
}
|
||
|
||
// 3. 剖面填充 - 只在中间区域
|
||
// 使用 sectionFilletR
|
||
if (sectionFilletR > 0.01)
|
||
{
|
||
DrawRingSectionHatchWithFillet(ctx, xSectionLeft, xSectionRight, oy, H, sectionFilletR);
|
||
}
|
||
else
|
||
{
|
||
DrawBlockSectionHatch(ctx, xSectionLeft, xSectionRight, oy, H);
|
||
}
|
||
|
||
// 5. 零件轮廓框(黄色双点划线矩形 - 在内框内,与锻件有一定间距)
|
||
var widthPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize1Prime);
|
||
var heightPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize2Prime);
|
||
if (widthPrime.HasValue && widthPrime.Value > 0 && heightPrime.HasValue && heightPrime.Value > 0)
|
||
{
|
||
double partH = heightPrime.Value;
|
||
double partW = widthPrime.Value;
|
||
|
||
// 计算零件在视觉上的宽度比例
|
||
double partWidthRatio = partW / W;
|
||
double visualPartW = innerWidth * partWidthRatio;
|
||
if (visualPartW > innerWidth) visualPartW = innerWidth * 0.9;
|
||
|
||
// 零件在锻件内居中
|
||
double partOffsetX = (innerWidth - visualPartW) / 2.0;
|
||
double partOffsetY = (H - partH) / 2.0;
|
||
|
||
double xPartLeft = xInnerLeft + partOffsetX;
|
||
double yPartBottom = oy + partOffsetY;
|
||
|
||
DrawBlockPartContour(ctx, xPartLeft, yPartBottom, visualPartW, partH);
|
||
}
|
||
|
||
// 6. 宽度标注 (BoxSize1) - 位于底部
|
||
// 标注从锻件最左端到最右端 (BoxSize1 对应 锻件总宽)
|
||
{
|
||
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize1) ?? W;
|
||
var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize1);
|
||
var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize1TolPlus);
|
||
var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize1TolMinus);
|
||
var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize1TolPlus);
|
||
var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize1TolMinus);
|
||
|
||
var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr);
|
||
|
||
// 添加零件尺寸 (Prime) 到下方,用括号包裹
|
||
var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize1Prime);
|
||
if (valPrime.HasValue && valPrime.Value > 0)
|
||
{
|
||
dimText += $"\\X({FeatureDrivenDrawer.FormatDimNumber(valPrime.Value, null)})";
|
||
}
|
||
|
||
// 修正:标注需涵盖内框宽度 (矩形部分)
|
||
|
||
// 修正:引线起点改为内框边界 (xInnerLeft/Right) 和高度底部上移圆角半径,确保闭合到白色线框
|
||
// 修正:引线起点严格匹配倒角与圆弧相切处的极限点坐标 (fx_L_tang, fy_L_tangBot)
|
||
AddLinearDim(
|
||
ctx,
|
||
new Point3d(fx_L_tang, fy_L_tangBot, 0),
|
||
new Point3d(fx_R_tang, fy_R_tangBot, 0),
|
||
new Point3d((fx_L_tang + fx_R_tang) / 2, oy - 25, 0),
|
||
0,
|
||
dimText);
|
||
}
|
||
|
||
// 7. 高度标注 (BoxSize2) - 位于右侧
|
||
// 标注从锻件顶部到底部
|
||
{
|
||
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize2) ?? H;
|
||
var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize2);
|
||
var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize2TolPlus);
|
||
var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize2TolMinus);
|
||
var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize2TolPlus);
|
||
var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize2TolMinus);
|
||
|
||
var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr);
|
||
|
||
// 添加零件尺寸 (Prime) 到下方
|
||
var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize2Prime);
|
||
if (valPrime.HasValue && valPrime.Value > 0)
|
||
{
|
||
dimText += $"\\X({FeatureDrivenDrawer.FormatDimNumber(valPrime.Value, null)})";
|
||
}
|
||
|
||
// 标注从圆弧最外侧开始(避免与圆弧轮廓线重叠)
|
||
double xOuterRight = ox + visualTotalW;
|
||
// 修正:标注界线起点应从圆弧顶端开始,往内缩进一个圆弧高度 arcHeight + headFilletR,定位在弦线上
|
||
double xDimOrigin = xOuterRight - (arcHeight + headFilletR);
|
||
|
||
AddLinearDim(
|
||
ctx,
|
||
new Point3d(xDimOrigin, oy, 0),
|
||
new Point3d(xDimOrigin, oy + H, 0),
|
||
new Point3d(xOuterRight + 20, oy + H / 2, 0),
|
||
90,
|
||
dimText);
|
||
}
|
||
|
||
// 8. 中间矩形宽度标注 (BoxSize3) - 位于上方
|
||
// 对应剖面区域宽度
|
||
{
|
||
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize3) ?? 0;
|
||
var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize3);
|
||
|
||
// 只有当有值时才标注
|
||
if (val > 0)
|
||
{
|
||
var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize3TolPlus);
|
||
var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize3TolMinus);
|
||
var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize3TolPlus);
|
||
var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeyBoxSize3TolMinus);
|
||
|
||
var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr);
|
||
|
||
// 添加零件尺寸 (Prime) 到下方
|
||
var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxSize3Prime);
|
||
if (valPrime.HasValue && valPrime.Value > 0)
|
||
{
|
||
dimText += $"\\X({FeatureDrivenDrawer.FormatDimNumber(valPrime.Value, null)})";
|
||
}
|
||
|
||
// 修正:引线向下延伸 sectionFilletR,以接触直边
|
||
// sectionFilletR 是剖面处的圆角半径
|
||
double dimYStart = oy + H - sectionFilletR;
|
||
AddLinearDim(
|
||
ctx,
|
||
new Point3d(xSectionLeft, dimYStart, 0),
|
||
new Point3d(xSectionRight, dimYStart, 0),
|
||
new Point3d((xSectionLeft + xSectionRight) / 2, oy + H + 15, 0),
|
||
0,
|
||
dimText);
|
||
}
|
||
}
|
||
|
||
// 9. 硬度符号 - 从剖面右侧引出
|
||
var hardnessVal = bag.GetString(FeatureDrivenDrawer.KeyHardness);
|
||
if (!string.IsNullOrWhiteSpace(hardnessVal) && hardnessVal != "空")
|
||
{
|
||
double xStart = xSectionRight;
|
||
double yStart = oy + H * 0.25;
|
||
FeatureDrivenDrawer.DrawHardnessSymbol(ctx, xStart, yStart, hardnessVal);
|
||
}
|
||
|
||
// 10. 标刻内容引线 - 从剖面左侧引出
|
||
var markingText = bag.GetString(FeatureDrivenDrawer.KeyMarkingContent);
|
||
if (!string.IsNullOrWhiteSpace(markingText))
|
||
{
|
||
double xTarget = xSectionLeft;
|
||
double yTarget = oy + H * 0.75;
|
||
DrawSpecialHBLeaderToTop(ctx, xTarget, yTarget, markingText);
|
||
}
|
||
}
|
||
|
||
private static void DrawBlockRoundHeadOutline(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double totalWidth, double height, double arcHeight, double innerFilletR, double xf_left, double xf_right)
|
||
{
|
||
try
|
||
{
|
||
double H = height;
|
||
double r = innerFilletR;
|
||
double w = arcHeight;
|
||
if (w < 0.1) return;
|
||
|
||
double Rm = (H * H) / (8.0 * w) + w / 2.0;
|
||
|
||
// Left side
|
||
double xInnerLeft = ox + w;
|
||
double xc_left = xInnerLeft + Rm - w;
|
||
|
||
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);
|
||
|
||
double fx_L_tangTop = r > 0 ? C_m_L.X + (Rm / (Rm - r)) * (C_fTop_L.X - C_m_L.X) : xInnerLeft;
|
||
double fy_L_tangTop = r > 0 ? C_m_L.Y + (Rm / (Rm - r)) * (C_fTop_L.Y - C_m_L.Y) : oy + H;
|
||
|
||
double fx_L_tangBot = r > 0 ? C_m_L.X + (Rm / (Rm - r)) * (C_fBot_L.X - C_m_L.X) : xInnerLeft;
|
||
double fy_L_tangBot = r > 0 ? C_m_L.Y + (Rm / (Rm - r)) * (C_fBot_L.Y - C_m_L.Y) : oy;
|
||
|
||
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_tangBot - 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_tangBot - 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_tangBot, 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_tangBot, fy_L_tangBot, 0));
|
||
ctx.Style?.Apply(leftClosureLine, DrawingStyleManager.Role.OutlineBold);
|
||
ctx.Btr.AppendEntity(leftClosureLine);
|
||
ctx.Tr.AddNewlyCreatedDBObject(leftClosureLine, true);
|
||
|
||
// Right side
|
||
double xInnerRight = ox + totalWidth - w;
|
||
double xc_right = xInnerRight - Rm + w;
|
||
|
||
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);
|
||
|
||
double fx_R_tangTop = r > 0 ? C_m_R.X + (Rm / (Rm - r)) * (C_fTop_R.X - C_m_R.X) : xInnerRight;
|
||
double fy_R_tangTop = r > 0 ? C_m_R.Y + (Rm / (Rm - r)) * (C_fTop_R.Y - C_m_R.Y) : oy + H;
|
||
|
||
double fx_R_tangBot = r > 0 ? C_m_R.X + (Rm / (Rm - r)) * (C_fBot_R.X - C_m_R.X) : xInnerRight;
|
||
double fy_R_tangBot = r > 0 ? C_m_R.Y + (Rm / (Rm - r)) * (C_fBot_R.Y - C_m_R.Y) : oy;
|
||
|
||
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_tangBot - 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_tangBot - 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_tangBot, 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_tangBot, fy_R_tangBot, 0));
|
||
ctx.Style?.Apply(rightClosureLine, DrawingStyleManager.Role.OutlineBold);
|
||
ctx.Btr.AppendEntity(rightClosureLine);
|
||
ctx.Tr.AddNewlyCreatedDBObject(rightClosureLine, true);
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private static void DrawBoxSectionContourWithFillet(FeatureDrivenDrawer.DrawingContext ctx, double xLeft, double xRight, double yBottom, double height, double filletR)
|
||
{
|
||
var yTop = yBottom + height;
|
||
var width = xRight - xLeft;
|
||
|
||
var maxR = Math.Min(width * 0.5, height * 0.5);
|
||
var r = Math.Min(filletR, maxR);
|
||
|
||
if (r <= 0.01)
|
||
{
|
||
var poly = new Polyline();
|
||
poly.AddVertexAt(0, new Point2d(xLeft, yBottom), 0, 0, 0);
|
||
poly.AddVertexAt(1, new Point2d(xRight, yBottom), 0, 0, 0);
|
||
poly.AddVertexAt(2, new Point2d(xRight, yTop), 0, 0, 0);
|
||
poly.AddVertexAt(3, new Point2d(xLeft, yTop), 0, 0, 0);
|
||
poly.Closed = true;
|
||
|
||
ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold);
|
||
ctx.Btr.AppendEntity(poly);
|
||
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
|
||
return;
|
||
}
|
||
|
||
var bulge = Math.Tan(Math.PI / 8.0);
|
||
|
||
var polyFillet = new Polyline();
|
||
|
||
polyFillet.AddVertexAt(0, new Point2d(xLeft + r, yBottom), 0, 0, 0);
|
||
polyFillet.AddVertexAt(1, new Point2d(xRight - r, yBottom), bulge, 0, 0);
|
||
polyFillet.AddVertexAt(2, new Point2d(xRight, yBottom + r), 0, 0, 0);
|
||
polyFillet.AddVertexAt(3, new Point2d(xRight, yTop - r), bulge, 0, 0);
|
||
polyFillet.AddVertexAt(4, new Point2d(xRight - r, yTop), 0, 0, 0);
|
||
polyFillet.AddVertexAt(5, new Point2d(xLeft + r, yTop), bulge, 0, 0);
|
||
polyFillet.AddVertexAt(6, new Point2d(xLeft, yTop - r), 0, 0, 0);
|
||
polyFillet.AddVertexAt(7, new Point2d(xLeft, yBottom + r), bulge, 0, 0);
|
||
|
||
polyFillet.Closed = true;
|
||
|
||
ctx.Style?.Apply(polyFillet, DrawingStyleManager.Role.OutlineBold);
|
||
ctx.Btr.AppendEntity(polyFillet);
|
||
ctx.Tr.AddNewlyCreatedDBObject(polyFillet, true);
|
||
}
|
||
|
||
private static void DrawBoxSideFrame(FeatureDrivenDrawer.DrawingContext ctx, double xStart, double xEnd, double yBottom, double height, double filletR, bool isLeft)
|
||
{
|
||
var yTop = yBottom + height;
|
||
var width = Math.Abs(xEnd - xStart);
|
||
if (width < 0.1) return;
|
||
|
||
var topPoly = new Polyline();
|
||
topPoly.AddVertexAt(0, new Point2d(xStart, yTop), 0, 0, 0);
|
||
topPoly.AddVertexAt(1, new Point2d(xEnd, yTop), 0, 0, 0);
|
||
|
||
ctx.Style?.Apply(topPoly, DrawingStyleManager.Role.OutlineBold);
|
||
ctx.Btr.AppendEntity(topPoly);
|
||
ctx.Tr.AddNewlyCreatedDBObject(topPoly, true);
|
||
|
||
var botPoly = new Polyline();
|
||
botPoly.AddVertexAt(0, new Point2d(xStart, yBottom), 0, 0, 0);
|
||
botPoly.AddVertexAt(1, new Point2d(xEnd, yBottom), 0, 0, 0);
|
||
|
||
ctx.Style?.Apply(botPoly, DrawingStyleManager.Role.OutlineBold);
|
||
ctx.Btr.AppendEntity(botPoly);
|
||
ctx.Tr.AddNewlyCreatedDBObject(botPoly, true);
|
||
}
|
||
|
||
private static void DrawRingSectionHatchWithFillet(FeatureDrivenDrawer.DrawingContext ctx, double xInnerRight, double xOuterRight, double yBottom, double height, double filletR)
|
||
{
|
||
if (xOuterRight <= xInnerRight)
|
||
{
|
||
return;
|
||
}
|
||
|
||
var availableWidth = xOuterRight - xInnerRight;
|
||
var maxR = Math.Min(availableWidth * 0.5, height * 0.5);
|
||
var r = Math.Min(filletR, maxR);
|
||
if (r <= 0.01)
|
||
{
|
||
DrawBlockSectionHatch(ctx, xInnerRight, xOuterRight, yBottom, height);
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
var yTop = yBottom + height;
|
||
var bulge = Math.Tan(Math.PI / 8.0);
|
||
|
||
var boundary = new Polyline();
|
||
boundary.AddVertexAt(0, new Point2d(xInnerRight + r, yBottom), 0, 0, 0);
|
||
boundary.AddVertexAt(1, new Point2d(xOuterRight - r, yBottom), bulge, 0, 0);
|
||
boundary.AddVertexAt(2, new Point2d(xOuterRight, yBottom + r), 0, 0, 0);
|
||
boundary.AddVertexAt(3, new Point2d(xOuterRight, yTop - r), bulge, 0, 0);
|
||
boundary.AddVertexAt(4, new Point2d(xOuterRight - r, yTop), 0, 0, 0);
|
||
boundary.AddVertexAt(5, new Point2d(xInnerRight + r, yTop), bulge, 0, 0);
|
||
boundary.AddVertexAt(6, new Point2d(xInnerRight, yTop - r), 0, 0, 0);
|
||
boundary.AddVertexAt(7, new Point2d(xInnerRight, yBottom + r), bulge, 0, 0);
|
||
boundary.Closed = true;
|
||
|
||
ctx.Btr.AppendEntity(boundary);
|
||
ctx.Tr.AddNewlyCreatedDBObject(boundary, true);
|
||
|
||
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);
|
||
|
||
try
|
||
{
|
||
boundary.Erase(true);
|
||
}
|
||
catch { }
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private static void DrawBlockSectionHatch(FeatureDrivenDrawer.DrawingContext ctx, double xLeft, double xRight, double yBottom, double height)
|
||
{
|
||
if (xRight <= xLeft)
|
||
{
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
var boundary = new Polyline();
|
||
boundary.AddVertexAt(0, new Point2d(xLeft, yBottom), 0, 0, 0);
|
||
boundary.AddVertexAt(1, new Point2d(xRight, yBottom), 0, 0, 0);
|
||
boundary.AddVertexAt(2, new Point2d(xRight, yBottom + height), 0, 0, 0);
|
||
boundary.AddVertexAt(3, new Point2d(xLeft, yBottom + height), 0, 0, 0);
|
||
boundary.Closed = true;
|
||
ctx.Btr.AppendEntity(boundary);
|
||
ctx.Tr.AddNewlyCreatedDBObject(boundary, true);
|
||
|
||
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);
|
||
|
||
try
|
||
{
|
||
boundary.Erase(true);
|
||
}
|
||
catch { }
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private static void DrawBlockPartContour(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double width, double height)
|
||
{
|
||
try
|
||
{
|
||
var poly = new Polyline();
|
||
poly.AddVertexAt(0, new Point2d(x, y), 0, 0, 0);
|
||
poly.AddVertexAt(1, new Point2d(x + width, y), 0, 0, 0);
|
||
poly.AddVertexAt(2, new Point2d(x + width, y + height), 0, 0, 0);
|
||
poly.AddVertexAt(3, new Point2d(x, y + height), 0, 0, 0);
|
||
poly.Closed = true;
|
||
|
||
ctx.Style?.Apply(poly, DrawingStyleManager.Role.PartContour);
|
||
ctx.Btr.AppendEntity(poly);
|
||
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private static void DrawHeadFilletRadiusLeader(FeatureDrivenDrawer.DrawingContext ctx, double cx, double cy, double r, bool isLeftSection)
|
||
{
|
||
try
|
||
{
|
||
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyBoxRoundHeadFilletRadiusMax);
|
||
if (!val.HasValue || val.Value <= 0) return;
|
||
|
||
// 左上角向左上(135),右上角向右上(45)
|
||
double angleDeg = isLeftSection ? 135 : 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 = $"4-R\\U+2264{val.Value}";
|
||
var text = new DBText();
|
||
text.TextString = textStr;
|
||
text.Height = 3.5;
|
||
text.ColorIndex = 4; // Cyan
|
||
|
||
// 倾斜文字角度
|
||
double textRotation = angleRad;
|
||
if (isLeftSection)
|
||
{
|
||
// 左侧角度是 135,文字应该 -45度(减去180)保证从左向右读
|
||
textRotation = angleRad - Math.PI;
|
||
}
|
||
text.Rotation = textRotation;
|
||
|
||
// 对齐设置
|
||
text.HorizontalMode = TextHorizontalMode.TextCenter;
|
||
text.VerticalMode = TextVerticalMode.TextBottom;
|
||
|
||
// 计算文字放置点,紧贴在线端上方
|
||
double offsetX = 2.0 * Math.Cos(textRotation + Math.PI / 2);
|
||
double offsetY = 2.0 * Math.Sin(textRotation + 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
|
||
{
|
||
// ignore
|
||
}
|
||
}
|
||
|
||
private static void DrawSpecialHBLeaderToTop(FeatureDrivenDrawer.DrawingContext ctx, double xTarget, double yTarget, string textContent)
|
||
{
|
||
try
|
||
{
|
||
var p1 = new Point3d(xTarget, yTarget, 0);
|
||
var p2 = new Point3d(xTarget - 10, yTarget + 10, 0);
|
||
|
||
double textLen = (string.IsNullOrEmpty(textContent) ? 10 : textContent.Length) * 2.5;
|
||
if (textLen < 20) textLen = 20;
|
||
|
||
var p3 = new Point3d(p2.X - textLen, p2.Y, 0);
|
||
|
||
var leader = new Leader();
|
||
leader.SetDatabaseDefaults();
|
||
leader.AppendVertex(p1);
|
||
leader.AppendVertex(p2);
|
||
leader.AppendVertex(p3);
|
||
leader.HasArrowHead = true;
|
||
leader.ColorIndex = 7; // 白色
|
||
leader.Layer = "0";
|
||
|
||
ctx.Btr.AppendEntity(leader);
|
||
ctx.Tr.AddNewlyCreatedDBObject(leader, true);
|
||
|
||
var text = new DBText();
|
||
text.TextString = textContent;
|
||
text.Height = 3.5;
|
||
text.ColorIndex = 7;
|
||
text.Layer = "0";
|
||
|
||
text.HorizontalMode = TextHorizontalMode.TextLeft;
|
||
text.VerticalMode = TextVerticalMode.TextBottom;
|
||
text.AlignmentPoint = new Point3d(p3.X, p3.Y + 1.0, 0);
|
||
text.Position = text.AlignmentPoint;
|
||
|
||
ctx.Btr.AppendEntity(text);
|
||
ctx.Tr.AddNewlyCreatedDBObject(text, true);
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private static void AddLinearDim(FeatureDrivenDrawer.DrawingContext ctx, Point3d pt1, Point3d pt2, Point3d dimLinePt,
|
||
double rotationDeg, string textOverride, Action<Dimension, FeatureDrivenDrawer.DrawingContext> customizer = null)
|
||
{
|
||
try
|
||
{
|
||
var prevDb = HostApplicationServices.WorkingDatabase;
|
||
HostApplicationServices.WorkingDatabase = ctx.Db;
|
||
try
|
||
{
|
||
double rotRad = rotationDeg * Math.PI / 180.0;
|
||
var dim = new RotatedDimension(rotRad, pt1, pt2, dimLinePt, textOverride, ctx.Db.Dimstyle);
|
||
try { dim.SetDatabaseDefaults(); } catch { }
|
||
dim.ColorIndex = 3;
|
||
|
||
if (!string.IsNullOrEmpty(textOverride))
|
||
{
|
||
dim.DimensionText = textOverride;
|
||
}
|
||
|
||
try { dim.Normal = Vector3d.ZAxis; } catch { }
|
||
TryApplyDimSizeOverrides(dim);
|
||
TryApplyDimLayoutOverrides(dim);
|
||
|
||
customizer?.Invoke(dim, ctx);
|
||
|
||
ctx.Style?.Apply(dim, DrawingStyleManager.Role.Dimension);
|
||
dim.ColorIndex = 3;
|
||
|
||
ctx.Btr.AppendEntity(dim);
|
||
ctx.Tr.AddNewlyCreatedDBObject(dim, true);
|
||
try { dim.RecomputeDimensionBlock(true); } catch { }
|
||
}
|
||
finally
|
||
{
|
||
HostApplicationServices.WorkingDatabase = prevDb;
|
||
}
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private static void TryApplyDimSizeOverrides(Dimension dim)
|
||
{
|
||
if (dim == null) return;
|
||
TrySetDimProp(dim, "Dimtxt", 3.5);
|
||
TrySetDimProp(dim, "Dimasz", 2.5);
|
||
TrySetDimProp(dim, "Dimgap", 1.0);
|
||
TrySetDimProp(dim, "Dimexe", 1.0);
|
||
TrySetDimProp(dim, "Dimexo", 0.0);
|
||
TrySetDimProp(dim, "Dimtofl", true);
|
||
TrySetDimProp(dim, "Dimatfit", 3);
|
||
TrySetDimProp(dim, "Dimtad", 1);
|
||
TrySetDimProp(dim, "Dimclrd", 3);
|
||
TrySetDimProp(dim, "Dimclre", 3);
|
||
TrySetDimProp(dim, "Dimclrt", 3);
|
||
}
|
||
|
||
private static void TryApplyDimLayoutOverrides(Dimension dim)
|
||
{
|
||
if (dim == null) return;
|
||
TrySetDimProp(dim, "Dimtih", false);
|
||
TrySetDimProp(dim, "Dimtoh", false);
|
||
TrySetDimProp(dim, "Dimse1", false);
|
||
TrySetDimProp(dim, "Dimse2", false);
|
||
}
|
||
|
||
private static void TrySetDimProp(object obj, string propName, double value)
|
||
{
|
||
if (obj == null) return;
|
||
try
|
||
{
|
||
var prop = obj.GetType().GetProperty(propName);
|
||
if (prop != null && prop.CanWrite && prop.PropertyType == typeof(double))
|
||
prop.SetValue(obj, value, null);
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private static void TrySetDimProp(object obj, string propName, bool value)
|
||
{
|
||
if (obj == null) return;
|
||
try
|
||
{
|
||
var prop = obj.GetType().GetProperty(propName);
|
||
if (prop != null && prop.CanWrite && prop.PropertyType == typeof(bool))
|
||
prop.SetValue(obj, value, null);
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private static void TrySetDimProp(object obj, string propName, int value)
|
||
{
|
||
if (obj == null) return;
|
||
try
|
||
{
|
||
var prop = obj.GetType().GetProperty(propName);
|
||
if (prop != null && prop.CanWrite && prop.PropertyType == typeof(int))
|
||
prop.SetValue(obj, value, null);
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private static ParamBag ScaleParamBag(ParamBag original, double scaleFactor)
|
||
{
|
||
if (original == null || Math.Abs(scaleFactor - 1.0) < 0.000001) return original;
|
||
var newBag = new ParamBag();
|
||
foreach(var k in original.GetKeys())
|
||
{
|
||
var v = original.GetString(k);
|
||
if (k.Contains("Diameter") || k.Contains("Length") || k.Contains("Radius") || k.Contains("Prime") || k.Contains("Height") || k.Contains("Thickness") || k.Contains("Size"))
|
||
{
|
||
if (double.TryParse(v, out var d))
|
||
{
|
||
newBag.Set(k, (d * scaleFactor).ToString("0.###"));
|
||
}
|
||
else { newBag.Set(k, v); }
|
||
}
|
||
else { newBag.Set(k, v); }
|
||
}
|
||
return newBag;
|
||
}
|
||
|
||
}
|
||
}
|