CadParamPluging/Cad/FeatureDrivenDrawer.cs
2025-12-25 15:46:23 +08:00

1986 lines
80 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 System.Linq;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using CadParamPluging.Common;
namespace CadParamPluging.Cad
{
/// <summary>
/// 特征驱动绘图引擎 - 根据参数存在性动态绘制图形
/// </summary>
public static class FeatureDrivenDrawer
{
#region Key常量
// 环形参数
public const string KeyOuterDiameter1 = "OuterDiameter1";
public const string KeyOuterDiameter1TolPlus = "OuterDiameter1TolPlus";
public const string KeyOuterDiameter1TolMinus = "OuterDiameter1TolMinus";
public const string KeyInnerDiameter2 = "InnerDiameter2";
public const string KeyInnerDiameter2TolPlus = "InnerDiameter2TolPlus";
public const string KeyInnerDiameter2TolMinus = "InnerDiameter2TolMinus";
public const string KeyHeight1 = "Height1";
public const string KeyHeight1TolPlus = "Height1TolPlus";
public const string KeyHeight1TolMinus = "Height1TolMinus";
public const string KeyMinWallThickness = "MinWallThickness";
public const string KeyUnspecifiedFilletRadiusMax = "UnspecifiedFilletRadiusMax"; // 环形未注圆角
public const string KeyInnerRadiusMax = "InnerRadiusMax"; // 内径半径R≤中心冲孔
// 环形零件尺寸(车加工态)
public const string KeyOuterDiameter1Prime = "OuterDiameter1Prime";
public const string KeyInnerDiameter2Prime = "InnerDiameter2Prime";
public const string KeyHeight1Prime = "Height1Prime";
// 饼盘参数
public const string KeyDiskDiameter = "DiskDiameter";
public const string KeyDiskDiameterTolPlus = "DiskDiameterTolPlus";
public const string KeyDiskDiameterTolMinus = "DiskDiameterTolMinus";
public const string KeyDiskHeight = "DiskHeight";
public const string KeyDiskHeightTolPlus = "DiskHeightTolPlus";
public const string KeyDiskHeightTolMinus = "DiskHeightTolMinus";
public const string KeyDiskFilletRadiusMax = "DiskFilletRadiusMax"; // 饼盘未注圆角
public const string KeyDiskDiameterPrime = "DiskDiameterPrime"; // 饼盘零件直径
public const string KeyDiskHeightPrime = "DiskHeightPrime"; // 饼盘零件高度
// 轴杆参数(圆轴)
public const string KeyDiameter = "Diameter";
public const string KeyDiameterTolPlus = "DiameterTolPlus";
public const string KeyDiameterTolMinus = "DiameterTolMinus";
public const string KeyLength = "Length";
public const string KeyLengthTolPlus = "LengthTolPlus";
public const string KeyLengthTolMinus = "LengthTolMinus";
public const string KeyShaftFilletRadiusMax = "ShaftFilletRadiusMax"; // 轴杆未注圆角
public const string KeyDiameterPrime = "DiameterPrime"; // 轴杆零件直径
public const string KeyLengthPrime = "LengthPrime"; // 轴杆零件长度
// 方体参数
public const string KeyBoxSize1 = "BoxSize1";
public const string KeyBoxSize1TolPlus = "BoxSize1TolPlus";
public const string KeyBoxSize1TolMinus = "BoxSize1TolMinus";
public const string KeyBoxSize2 = "BoxSize2";
public const string KeyBoxSize2TolPlus = "BoxSize2TolPlus";
public const string KeyBoxSize2TolMinus = "BoxSize2TolMinus";
public const string KeyBoxSize3 = "BoxSize3";
public const string KeyBoxSize3TolPlus = "BoxSize3TolPlus";
public const string KeyBoxSize3TolMinus = "BoxSize3TolMinus";
public const string KeyBoxFilletRadiusMax = "BoxFilletRadiusMax"; // 方体未注圆角
public const string KeyBoxRoundHeadFilletRadiusMax = "BoxRoundHeadFilletRadiusMax"; // 方体圆头处圆角
public const string KeyBoxSize1Prime = "BoxSize1Prime"; // 方体零件尺寸1
public const string KeyBoxSize2Prime = "BoxSize2Prime"; // 方体零件尺寸2
public const string KeyBoxSize3Prime = "BoxSize3Prime"; // 方体零件尺寸3
#endregion
#region
public class DrawingContext
{
public CadContext Ctx { get; set; }
public ParamBag Bag { get; set; }
public Point3d Center { get; set; }
public string DeliveryStatus { get; set; }
public string StructuralFeature { get; set; }
public string SpecialCondition { get; set; }
public string ProcessMethod { get; set; }
internal DrawingStyleManager Style { get; set; }
public Database Db => Ctx?.Database;
public Transaction Tr => Ctx?.Transaction;
public BlockTableRecord Btr { get; set; }
public bool IsMachined => !string.IsNullOrWhiteSpace(DeliveryStatus)
&& DeliveryStatus.IndexOf("车加工", StringComparison.OrdinalIgnoreCase) >= 0;
public bool IsCenterPunched => !string.IsNullOrWhiteSpace(SpecialCondition)
&& SpecialCondition.IndexOf("中心冲孔", StringComparison.OrdinalIgnoreCase) >= 0;
public bool HasRoundHead => !string.IsNullOrWhiteSpace(SpecialCondition)
&& SpecialCondition.IndexOf("有圆头", StringComparison.OrdinalIgnoreCase) >= 0;
/// <summary>
/// 是否为轧制工艺(轧制时只画右半边图)
/// </summary>
public bool IsRolling => !string.IsNullOrWhiteSpace(ProcessMethod)
&& ProcessMethod.IndexOf("轧制", StringComparison.OrdinalIgnoreCase) >= 0;
}
#endregion
#region
/// <summary>
/// 预期图形尺寸
/// </summary>
public class ExpectedDrawingSize
{
public double Width { get; set; }
public double Height { get; set; }
public bool IsValid => Width > 0 && Height > 0;
}
/// <summary>
/// 根据参数计算预期绘制图形的尺寸(不包含标注,仅计算图形主体)
/// </summary>
public static ExpectedDrawingSize CalculateExpectedSize(ParamBag bag, string structuralFeature)
{
if (bag == null)
{
return new ExpectedDrawingSize();
}
if (IsRing(structuralFeature))
{
return CalculateRingSize(bag);
}
if (IsDisk(structuralFeature))
{
return CalculateDiskSize(bag);
}
if (IsShaft(structuralFeature))
{
return CalculateShaftSize(bag);
}
if (IsBlock(structuralFeature))
{
return CalculateBlockSize(bag);
}
return new ExpectedDrawingSize();
}
private static ExpectedDrawingSize CalculateRingSize(ParamBag bag)
{
var outerDia = bag.GetDoubleOrNull(KeyOuterDiameter1) ?? 0;
var height = bag.GetDoubleOrNull(KeyHeight1) ?? 0;
// 环形图形:宽度=外径X方向高度=高度参数Y方向
// 加上标注的额外空间约40像素每侧
var extraMargin = 40;
return new ExpectedDrawingSize
{
Width = outerDia + extraMargin * 2,
Height = height + extraMargin * 2
};
}
private static ExpectedDrawingSize CalculateDiskSize(ParamBag bag)
{
var diameter = bag.GetDoubleOrNull(KeyDiskDiameter) ?? 0;
var height = bag.GetDoubleOrNull(KeyDiskHeight) ?? 0;
var extraMargin = 40;
return new ExpectedDrawingSize
{
Width = diameter + extraMargin * 2,
Height = height + extraMargin * 2
};
}
private static ExpectedDrawingSize CalculateShaftSize(ParamBag bag)
{
var diameter = bag.GetDoubleOrNull(KeyDiameter) ?? 0;
var length = bag.GetDoubleOrNull(KeyLength) ?? 0;
var extraMargin = 40;
return new ExpectedDrawingSize
{
Width = length + extraMargin * 2,
Height = diameter + extraMargin * 2
};
}
private static ExpectedDrawingSize CalculateBlockSize(ParamBag bag)
{
var size1 = bag.GetDoubleOrNull(KeyBoxSize1) ?? 0;
var size2 = bag.GetDoubleOrNull(KeyBoxSize2) ?? size1;
var extraMargin = 40;
return new ExpectedDrawingSize
{
Width = size1 + extraMargin * 2,
Height = size2 + extraMargin * 2
};
}
#endregion
#region
/// <summary>
/// 绘制图形(带缩放支持)
/// </summary>
/// <param name="ctx">CAD上下文</param>
/// <param name="bag">参数包</param>
/// <param name="deliveryStatus">交付状态</param>
/// <param name="structuralFeature">结构特征</param>
/// <param name="specialCondition">特殊条件</param>
/// <param name="processMethod">工艺方法(轧制/自由锻)</param>
/// <param name="center">绘图中心点</param>
/// <param name="scaleFactor">缩放比例1.0表示不缩放)</param>
public static void Draw(CadContext ctx, ParamBag bag, string deliveryStatus, string structuralFeature,
string specialCondition = null, string processMethod = null, Point3d? center = null, 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;
// Important: templates & cleanup operate on ModelSpace; draw there to avoid PaperSpace-related dimension issues.
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 DrawingContext
{
Ctx = ctx,
Bag = effectiveBag,
Center = center ?? Point3d.Origin,
DeliveryStatus = deliveryStatus,
StructuralFeature = structuralFeature,
SpecialCondition = specialCondition,
ProcessMethod = processMethod,
Btr = btr,
Style = new DrawingStyleManager(db, tr)
};
// 根据结构特征分发到对应绘制器
if (IsRing(structuralFeature))
{
DrawRingFeatures(context);
}
else if (IsDisk(structuralFeature))
{
DrawDiskFeatures(context);
}
else if (IsShaft(structuralFeature))
{
DrawShaftFeatures(context);
}
else if (IsBlock(structuralFeature))
{
DrawBlockFeatures(context);
}
}
#endregion
#region
private static bool IsRing(string feature)
{
return !string.IsNullOrWhiteSpace(feature)
&& feature.IndexOf("环形", StringComparison.OrdinalIgnoreCase) >= 0;
}
private static bool IsDisk(string feature)
{
return !string.IsNullOrWhiteSpace(feature)
&& (feature.IndexOf("饼盘", StringComparison.OrdinalIgnoreCase) >= 0
|| feature.IndexOf("饼", StringComparison.OrdinalIgnoreCase) >= 0
|| feature.IndexOf("盘", StringComparison.OrdinalIgnoreCase) >= 0);
}
private static bool IsShaft(string feature)
{
return !string.IsNullOrWhiteSpace(feature)
&& (feature.IndexOf("轴杆", StringComparison.OrdinalIgnoreCase) >= 0
|| feature.IndexOf("轴", StringComparison.OrdinalIgnoreCase) >= 0
|| feature.IndexOf("杆", StringComparison.OrdinalIgnoreCase) >= 0);
}
private static bool IsBlock(string feature)
{
return !string.IsNullOrWhiteSpace(feature)
&& feature.IndexOf("方体", StringComparison.OrdinalIgnoreCase) >= 0;
}
#endregion
#region -
private static void DrawRingFeatures(DrawingContext ctx)
{
var bag = ctx.Bag;
// 必需参数检测
var outerDia = bag.GetDoubleOrNull(KeyOuterDiameter1);
var height = bag.GetDoubleOrNull(KeyHeight1);
if (!outerDia.HasValue || outerDia.Value <= 0)
{
return; // 缺少外径,无法绘制
}
if (!height.HasValue || height.Value <= 0)
{
return; // 缺少高度,无法绘制
}
// 判断是轧制还是自由锻
if (ctx.IsRolling)
{
// 轧制:只画右半边图
DrawRingFeaturesHalf(ctx, outerDia.Value, height.Value);
}
else
{
// 自由锻:画全图
DrawRingFeaturesFull(ctx, outerDia.Value, height.Value);
}
}
/// <summary>
/// 轧制工艺 - 只画右半边图
/// </summary>
private static void DrawRingFeaturesHalf(DrawingContext ctx, double outerDia, double height)
{
var bag = ctx.Bag;
double R = outerDia / 2.0; // 外半径
double H = height;
// 轧制时图形只画右半边,但要保持居中
// 半图宽度为R要居中则起点为 Center.X - R/2
double ox = ctx.Center.X - R / 2.0; // 对称轴位置(左边界)
double oy = ctx.Center.Y - H / 2.0;
// 车加工态零件尺寸
double? outerDiaPrime = null;
double? innerDiaPrime = null;
double? heightPrime = null;
if (ctx.IsMachined)
{
outerDiaPrime = bag.GetDoubleOrNull(KeyOuterDiameter1Prime);
innerDiaPrime = bag.GetDoubleOrNull(KeyInnerDiameter2Prime);
heightPrime = bag.GetDoubleOrNull(KeyHeight1Prime);
}
// === 特征1: 锻件外轮廓(右半边,三条边:下、右、上,左边开口) ===
DrawForgingOuterContourHalf(ctx, ox, oy, R, H);
// === 特征1.1: 对称轴(垂直中心线) ===
DrawRingSymmetryAxis(ctx, ox, oy, H);
// === 特征2: 外径公差标注 ===
var outerTolPlus = bag.GetDoubleOrNull(KeyOuterDiameter1TolPlus);
var outerTolMinus = bag.GetDoubleOrNull(KeyOuterDiameter1TolMinus);
DrawOuterDiameterDimensionHalf(ctx, ox, oy, R, H, outerDia, outerTolPlus, outerTolMinus, outerDiaPrime);
// === 特征3: 内孔/内径(如果有内径参数) ===
var innerDia = bag.GetDoubleOrNull(KeyInnerDiameter2);
double? xInnerRight = null;
if (innerDia.HasValue && innerDia.Value > 0 && innerDia.Value < outerDia)
{
double innerR = innerDia.Value / 2.0;
xInnerRight = ox + innerR;
var innerTolPlus = bag.GetDoubleOrNull(KeyInnerDiameter2TolPlus);
var innerTolMinus = bag.GetDoubleOrNull(KeyInnerDiameter2TolMinus);
// 只画右侧内孔线
DrawInnerHoleHalf(ctx, ox, xInnerRight.Value, oy, H);
DrawInnerDiameterDimensionHalf(ctx, ox, xInnerRight.Value, oy, H, innerDia.Value, innerTolPlus, innerTolMinus, innerDiaPrime);
// === 特征4: 内径圆角(只画右侧) ===
var innerRadiusMax = bag.GetDoubleOrNull(KeyInnerRadiusMax);
if (innerRadiusMax.HasValue && innerRadiusMax.Value > 0 && ctx.IsCenterPunched)
{
DrawInnerFilletsHalf(ctx, xInnerRight.Value, oy, H, innerRadiusMax.Value);
}
// === 特征4.1: 剖面线(右半边环形截面) ===
DrawRingSectionHatch(ctx, xInnerRight.Value, ox + R, oy, H);
// 剖面左侧竖线应为粗实线(剖切边界)
DrawSectionInnerBoundaryBold(ctx, xInnerRight.Value, oy, H);
}
// === 特征5: 高度标注 ===
var heightTolPlus = bag.GetDoubleOrNull(KeyHeight1TolPlus);
var heightTolMinus = bag.GetDoubleOrNull(KeyHeight1TolMinus);
DrawHeightDimensionHalf(ctx, ox, oy, R, H, heightTolPlus, heightTolMinus, heightPrime);
// === 特征6: 未注圆角 ===
var unspecifiedFillet = bag.GetDoubleOrNull(KeyUnspecifiedFilletRadiusMax);
if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
{
DrawUnspecifiedFilletNote(ctx, ox, oy, H, R, unspecifiedFillet.Value);
}
// === 特征7: 最小壁厚min标注 ===
var minWallThickness = bag.GetDoubleOrNull(KeyMinWallThickness);
if (minWallThickness.HasValue && minWallThickness.Value > 0 && xInnerRight.HasValue)
{
DrawMinWallThicknessNote(ctx, xInnerRight.Value, ox + R, oy, minWallThickness.Value);
}
// === 特征8: 零件轮廓(车加工态,右半边) ===
if (ctx.IsMachined && outerDiaPrime.HasValue && outerDiaPrime.Value > 0 && heightPrime.HasValue && heightPrime.Value > 0)
{
DrawPartContourHalf(ctx, ox, oy, H, outerDiaPrime.Value, innerDiaPrime, heightPrime.Value);
}
// === 特征9: 硬度符号 ===
TryDrawHardnessSymbol(ctx, ox + R, oy, H);
}
/// <summary>
/// 自由锻工艺 - 画全图
/// </summary>
private static void DrawRingFeaturesFull(DrawingContext ctx, double outerDia, double height)
{
var bag = ctx.Bag;
double W = outerDia;
double H = height;
double ox = ctx.Center.X - W / 2.0;
double oy = ctx.Center.Y - H / 2.0;
// 车加工态零件尺寸(用于括号尺寸与零件轮廓)
double? outerDiaPrime = null;
double? innerDiaPrime = null;
double? heightPrime = null;
if (ctx.IsMachined)
{
outerDiaPrime = bag.GetDoubleOrNull(KeyOuterDiameter1Prime);
innerDiaPrime = bag.GetDoubleOrNull(KeyInnerDiameter2Prime);
heightPrime = bag.GetDoubleOrNull(KeyHeight1Prime);
}
// === 特征1: 锻件外轮廓(必绘) ===
DrawForgingOuterContour(ctx, ox, oy, W, H);
// === 特征1.1: 中心线 ===
DrawRingCenterline(ctx, ox, oy, W, H);
// === 特征2: 外径公差标注(如果有公差参数) ===
var outerTolPlus = bag.GetDoubleOrNull(KeyOuterDiameter1TolPlus);
var outerTolMinus = bag.GetDoubleOrNull(KeyOuterDiameter1TolMinus);
DrawOuterDiameterDimension(ctx, ox, oy, W, outerDia, outerTolPlus, outerTolMinus, outerDiaPrime);
// === 特征3: 内孔/内径(如果有内径参数) ===
var innerDia = bag.GetDoubleOrNull(KeyInnerDiameter2);
double? xInnerLeft = null;
double? xInnerRight = null;
if (innerDia.HasValue && innerDia.Value > 0 && innerDia.Value < W)
{
xInnerLeft = ctx.Center.X - innerDia.Value / 2.0;
xInnerRight = ctx.Center.X + innerDia.Value / 2.0;
var innerTolPlus = bag.GetDoubleOrNull(KeyInnerDiameter2TolPlus);
var innerTolMinus = bag.GetDoubleOrNull(KeyInnerDiameter2TolMinus);
DrawInnerHole(ctx, xInnerLeft.Value, xInnerRight.Value, oy, H);
DrawInnerDiameterDimension(ctx, xInnerLeft.Value, xInnerRight.Value, oy, innerDia.Value, innerTolPlus, innerTolMinus, innerDiaPrime);
// === 特征4: 内径圆角如果有内径半径R参数且是中心冲孔 ===
var innerRadiusMax = bag.GetDoubleOrNull(KeyInnerRadiusMax);
if (innerRadiusMax.HasValue && innerRadiusMax.Value > 0 && ctx.IsCenterPunched)
{
DrawInnerFillets(ctx, xInnerLeft.Value, xInnerRight.Value, oy, H, innerRadiusMax.Value);
}
// === 特征4.1: 剖面线(仅剖切端部区域) ===
DrawRingSectionHatch(ctx, xInnerRight.Value, ox + W, oy, H);
// 剖面左侧竖线应为粗实线(剖切边界)
DrawSectionInnerBoundaryBold(ctx, xInnerRight.Value, oy, H);
}
// === 特征5: 高度标注 ===
var heightTolPlus = bag.GetDoubleOrNull(KeyHeight1TolPlus);
var heightTolMinus = bag.GetDoubleOrNull(KeyHeight1TolMinus);
DrawHeightDimension(ctx, ox, oy, W, H, heightTolPlus, heightTolMinus, heightPrime);
// === 特征6: 未注圆角(如果有该参数) ===
var unspecifiedFillet = bag.GetDoubleOrNull(KeyUnspecifiedFilletRadiusMax);
if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
{
// 复用现有位置逻辑:右上角
DrawUnspecifiedFilletNote(ctx, ox, oy, H, W, unspecifiedFillet.Value);
}
// === 特征7: 最小壁厚min标注如果有该参数 ===
var minWallThickness = bag.GetDoubleOrNull(KeyMinWallThickness);
if (minWallThickness.HasValue && minWallThickness.Value > 0 && xInnerRight.HasValue)
{
DrawMinWallThicknessNote(ctx, xInnerRight.Value, ox + W, oy, minWallThickness.Value);
}
// === 特征8: 零件轮廓(车加工态,双点划线) ===
if (ctx.IsMachined && outerDiaPrime.HasValue && outerDiaPrime.Value > 0 && heightPrime.HasValue && heightPrime.Value > 0)
{
DrawPartContour(ctx, ctx.Center, outerDiaPrime.Value, innerDiaPrime, heightPrime.Value);
}
// === 特征9: 硬度符号(有要求才画) ===
TryDrawHardnessSymbol(ctx, ox + W, oy, H);
}
private static void DrawSectionInnerBoundaryBold(DrawingContext ctx, double x, double yBottom, double height)
{
try
{
var line = new Line(new Point3d(x, yBottom, 0), new Point3d(x, yBottom + height, 0));
ctx.Style?.Apply(line, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(line);
ctx.Tr.AddNewlyCreatedDBObject(line, true);
}
catch
{
// ignore
}
}
private static void DrawForgingOuterContour(DrawingContext ctx, double ox, double oy, double width, double height)
{
var poly = new Polyline();
poly.AddVertexAt(0, new Point2d(ox, oy), 0, 0, 0);
poly.AddVertexAt(1, new Point2d(ox + width, oy), 0, 0, 0);
poly.AddVertexAt(2, new Point2d(ox + width, oy + height), 0, 0, 0);
poly.AddVertexAt(3, new Point2d(ox, oy + height), 0, 0, 0);
poly.Closed = true;
ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
}
private static void DrawRingCenterline(DrawingContext ctx, double ox, double oy, double width, double height)
{
var cy = oy + height / 2.0;
var line = new Line(new Point3d(ox - 10, cy, 0), new Point3d(ox + width + 10, cy, 0));
ctx.Style?.Apply(line, DrawingStyleManager.Role.Centerline);
ctx.Btr.AppendEntity(line);
ctx.Tr.AddNewlyCreatedDBObject(line, true);
}
#region
/// <summary>
/// 轧制:绘制右半边外轮廓(开口多段线)
/// </summary>
private static void DrawForgingOuterContourHalf(DrawingContext ctx, double ox, double oy, double radius, double height)
{
// 右半边轮廓:下边、右边、上边(左边开口)
var poly = new Polyline();
poly.AddVertexAt(0, new Point2d(ox, oy), 0, 0, 0); // 左下(对称轴下端)
poly.AddVertexAt(1, new Point2d(ox + radius, oy), 0, 0, 0); // 右下
poly.AddVertexAt(2, new Point2d(ox + radius, oy + height), 0, 0, 0); // 右上
poly.AddVertexAt(3, new Point2d(ox, oy + height), 0, 0, 0); // 左上(对称轴上端)
poly.Closed = false; // 不闭合,左边开口
ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
}
/// <summary>
/// 轧制:绘制对称轴(垂直中心线)
/// </summary>
private static void DrawRingSymmetryAxis(DrawingContext ctx, double ox, double oy, double height)
{
const double extend = 5.0; // 中心线在轮廓上下各延长一点(与其它中心线的延长量保持一致)
const double frameMargin = 5.0; // 避免越过图框边界
var y0 = oy - extend;
var y1 = oy + height + extend;
// 若能检测到白色外框,则把中心线端点夹在图框内(留出少量安全边距)。
try
{
var frameExtents = TemplateDrawingService.ComputeWhiteFrameExtents(ctx?.Ctx);
if (frameExtents.HasValue)
{
var frame = frameExtents.Value;
y0 = Math.Max(y0, frame.MinPoint.Y + frameMargin);
y1 = Math.Min(y1, frame.MaxPoint.Y - frameMargin);
}
}
catch
{
// ignore
}
// 极端情况下(图框过小/检测异常导致端点反转)退回到原始高度。
if (y1 <= y0)
{
y0 = oy;
y1 = oy + height;
}
var line = new Line(new Point3d(ox, y0, 0), new Point3d(ox, y1, 0));
ctx.Style?.Apply(line, DrawingStyleManager.Role.Centerline);
ctx.Btr.AppendEntity(line);
ctx.Tr.AddNewlyCreatedDBObject(line, true);
}
/// <summary>
/// 轧制:外径标注(从对称轴到右边,标注在图形下方偏内)
/// </summary>
private static void DrawOuterDiameterDimensionHalf(DrawingContext ctx, double ox, double oy, double radius, double height,
double diameter, double? tolPlus, double? tolMinus, double? diameterPrime)
{
var baseText = BuildDimensionText($"%%c{FormatDimNumber(diameter)}", tolPlus, tolMinus);
var dimText = diameterPrime.HasValue && diameterPrime.Value > 0
? baseText + $"\\X(%%c{FormatDimNumber(diameterPrime.Value)})"
: baseText;
// 标注放在图形底部稍下方
AddLinearDim(
ctx,
new Point3d(ox, oy, 0),
new Point3d(ox + radius, oy, 0),
new Point3d(ox + radius / 2, oy - 20, 0),
0,
dimText);
}
/// <summary>
/// 轧制:只画右侧内孔线
/// </summary>
private static void DrawInnerHoleHalf(DrawingContext ctx, double oxAxis, double xInnerRight, double yBottom, double height)
{
var yTop = yBottom + height;
// 只画右侧内孔竖线
var lineRight = new Line(new Point3d(xInnerRight, yBottom, 0), new Point3d(xInnerRight, yTop, 0));
ctx.Style?.Apply(lineRight, DrawingStyleManager.Role.Hidden);
ctx.Btr.AppendEntity(lineRight);
ctx.Tr.AddNewlyCreatedDBObject(lineRight, true);
}
/// <summary>
/// 轧制:内径标注(从对称轴到右边内孔,放到下方并与最小壁厚标注共线)
/// </summary>
private static void DrawInnerDiameterDimensionHalf(DrawingContext ctx, double oxAxis, double xInnerRight, double yBottom, double height,
double diameter, double? tolPlus, double? tolMinus, double? diameterPrime)
{
var baseText = BuildDimensionText($"%%c{FormatDimNumber(diameter)}", tolPlus, tolMinus);
var dimText = diameterPrime.HasValue && diameterPrime.Value > 0
? baseText + $"\\X(%%c{FormatDimNumber(diameterPrime.Value)})"
: baseText;
double innerRadius = xInnerRight - oxAxis;
// 放到下方,并与最小壁厚(30min)同一条水平尺寸线yBottom - 10
var dimLineY = yBottom - 10;
AddLinearDim(
ctx,
new Point3d(oxAxis, yBottom, 0),
new Point3d(xInnerRight, yBottom, 0),
new Point3d(oxAxis + innerRadius / 2, dimLineY, 0),
0,
dimText);
}
/// <summary>
/// 轧制:只画右侧内径圆角
/// </summary>
private static void DrawInnerFilletsHalf(DrawingContext ctx, double xInnerRight, double yBottom, double height, double filletR)
{
var yTop = yBottom + height;
// 只画右侧两个圆角
// 右上角
DrawFilletArc(ctx, xInnerRight - filletR, yTop - filletR, filletR, 0, Math.PI / 2);
// 右下角
DrawFilletArc(ctx, xInnerRight - filletR, yBottom + filletR, filletR, Math.PI * 1.5, Math.PI * 2);
}
/// <summary>
/// 轧制:高度标注(在右侧)
/// </summary>
private static void DrawHeightDimensionHalf(DrawingContext ctx, double ox, double oy, double radius,
double height, double? tolPlus, double? tolMinus, double? heightPrime)
{
var baseText = BuildDimensionText(FormatDimNumber(height), tolPlus, tolMinus);
var dimText = heightPrime.HasValue && heightPrime.Value > 0
? baseText + $"\\X({FormatDimNumber(heightPrime.Value)})"
: baseText;
AddLinearDim(
ctx,
new Point3d(ox + radius, oy, 0),
new Point3d(ox + radius, oy + height, 0),
new Point3d(ox + radius + 20, oy + height / 2, 0),
90,
dimText);
}
/// <summary>
/// 轧制:零件轮廓(右半边)
/// </summary>
private static void DrawPartContourHalf(DrawingContext ctx, double ox, double oy, double forgingHeight,
double outerDiaPrime, double? innerDiaPrime, double heightPrime)
{
var Rp = outerDiaPrime / 2.0;
var h = heightPrime;
// 零件轮廓居中于锻件轮廓内
var offsetY = (forgingHeight - h) / 2.0;
var y0 = oy + offsetY;
// 右半边零件轮廓(开口)
var polyPart = new Polyline();
polyPart.AddVertexAt(0, new Point2d(ox, y0), 0, 0, 0);
polyPart.AddVertexAt(1, new Point2d(ox + Rp, y0), 0, 0, 0);
polyPart.AddVertexAt(2, new Point2d(ox + Rp, y0 + h), 0, 0, 0);
polyPart.AddVertexAt(3, new Point2d(ox, y0 + h), 0, 0, 0);
polyPart.Closed = false; // 不闭合
ctx.Style?.Apply(polyPart, DrawingStyleManager.Role.PartContour);
ctx.Btr.AppendEntity(polyPart);
ctx.Tr.AddNewlyCreatedDBObject(polyPart, true);
// 右侧内径轮廓
if (innerDiaPrime.HasValue && innerDiaPrime.Value > 0 && innerDiaPrime.Value < outerDiaPrime)
{
var xiR = ox + innerDiaPrime.Value / 2.0;
var yTop = y0 + h;
var lineInner = new Line(new Point3d(xiR, y0, 0), new Point3d(xiR, yTop, 0));
ctx.Style?.Apply(lineInner, DrawingStyleManager.Role.PartContour);
ctx.Btr.AppendEntity(lineInner);
ctx.Tr.AddNewlyCreatedDBObject(lineInner, true);
}
}
#endregion
private static void DrawInnerHole(DrawingContext ctx, double xInnerLeft, double xInnerRight, double yBottom, double height)
{
var yTop = yBottom + height;
var lineLeft = new Line(new Point3d(xInnerLeft, yBottom, 0), new Point3d(xInnerLeft, yTop, 0));
ctx.Style?.Apply(lineLeft, DrawingStyleManager.Role.Hidden);
ctx.Btr.AppendEntity(lineLeft);
ctx.Tr.AddNewlyCreatedDBObject(lineLeft, true);
var lineRight = new Line(new Point3d(xInnerRight, yBottom, 0), new Point3d(xInnerRight, yTop, 0));
ctx.Style?.Apply(lineRight, DrawingStyleManager.Role.Hidden);
ctx.Btr.AppendEntity(lineRight);
ctx.Tr.AddNewlyCreatedDBObject(lineRight, true);
}
private static void DrawInnerFillets(DrawingContext ctx, double xInnerLeft, double xInnerRight, double yBottom, double height, double filletR)
{
// 在内径四角绘制圆角示意
var yTop = yBottom + height;
// 左上角
DrawFilletArc(ctx, xInnerLeft + filletR, yTop - filletR, filletR, Math.PI / 2, Math.PI);
// 左下角
DrawFilletArc(ctx, xInnerLeft + filletR, yBottom + filletR, filletR, Math.PI, Math.PI * 1.5);
// 右上角
DrawFilletArc(ctx, xInnerRight - filletR, yTop - filletR, filletR, 0, Math.PI / 2);
// 右下角
DrawFilletArc(ctx, xInnerRight - filletR, yBottom + filletR, filletR, Math.PI * 1.5, Math.PI * 2);
}
private static void DrawFilletArc(DrawingContext ctx, double cx, double cy, double r, double startAngle, double endAngle)
{
try
{
var arc = new Arc(new Point3d(cx, cy, 0), r, startAngle, endAngle);
ctx.Style?.Apply(arc, DrawingStyleManager.Role.OutlineThin);
ctx.Btr.AppendEntity(arc);
ctx.Tr.AddNewlyCreatedDBObject(arc, true);
}
catch
{
// 忽略圆弧创建错误
}
}
private static void DrawOuterDiameterDimension(DrawingContext ctx, double ox, double oy, double width,
double diameter, double? tolPlus, double? tolMinus, double? diameterPrime)
{
var baseText = BuildDimensionText($"%%c{FormatDimNumber(diameter)}", tolPlus, tolMinus);
var dimText = diameterPrime.HasValue && diameterPrime.Value > 0
? baseText + $"\\X(%%c{FormatDimNumber(diameterPrime.Value)})"
: baseText;
AddLinearDim(
ctx,
new Point3d(ox, oy, 0),
new Point3d(ox + width, oy, 0),
new Point3d(ox + width / 2, oy - 40, 0),
0,
dimText);
}
private static void DrawInnerDiameterDimension(DrawingContext ctx, double xInnerLeft, double xInnerRight, double yBottom,
double diameter, double? tolPlus, double? tolMinus, double? diameterPrime)
{
var baseText = BuildDimensionText($"%%c{FormatDimNumber(diameter)}", tolPlus, tolMinus);
var dimText = diameterPrime.HasValue && diameterPrime.Value > 0
? baseText + $"\\X(%%c{FormatDimNumber(diameterPrime.Value)})"
: baseText;
AddLinearDim(
ctx,
new Point3d(xInnerLeft, yBottom, 0),
new Point3d(xInnerRight, yBottom, 0),
new Point3d((xInnerLeft + xInnerRight) / 2, yBottom - 25, 0),
0,
dimText);
}
private static void DrawHeightDimension(DrawingContext ctx, double ox, double oy, double width,
double height, double? tolPlus, double? tolMinus, double? heightPrime)
{
var baseText = BuildDimensionText(FormatDimNumber(height), tolPlus, tolMinus);
var dimText = heightPrime.HasValue && heightPrime.Value > 0
? baseText + $"\\X({FormatDimNumber(heightPrime.Value)})"
: baseText;
AddLinearDim(
ctx,
new Point3d(ox + width, oy, 0),
new Point3d(ox + width, oy + height, 0),
new Point3d(ox + width + 20, oy + height / 2, 0),
90,
dimText);
}
private static void DrawUnspecifiedFilletNote(DrawingContext ctx, double ox, double oy, double R, double height, double filletR)
{
// 在图纸右上角添加文字说明
try
{
var text = new DBText();
text.TextString = $"未注圆角半径R≤{filletR}";
text.Position = new Point3d(ox + height + 10, oy + R + 15, 0);
text.Height = 5;
ctx.Style?.Apply(text, DrawingStyleManager.Role.Text);
ctx.Btr.AppendEntity(text);
ctx.Tr.AddNewlyCreatedDBObject(text, true);
}
catch
{
// 忽略
}
}
private static void DrawMinWallThicknessNote(DrawingContext ctx, double xInnerRight, double xOuterRight, double yBottom, double thickness)
{
var dimText = $"{FormatDimNumber(thickness)}min";
AddLinearDim(
ctx,
new Point3d(xInnerRight, yBottom, 0),
new Point3d(xOuterRight, yBottom, 0),
new Point3d((xInnerRight + xOuterRight) / 2, yBottom - 10, 0),
0,
dimText);
}
private static void DrawPartContour(DrawingContext ctx, Point3d center,
double outerDiaPrime, double? innerDiaPrime, double heightPrime)
{
var w = outerDiaPrime;
var h = heightPrime;
var x0 = center.X - w / 2.0;
var y0 = center.Y - h / 2.0;
var polyPart = new Polyline();
polyPart.AddVertexAt(0, new Point2d(x0, y0), 0, 0, 0);
polyPart.AddVertexAt(1, new Point2d(x0 + w, y0), 0, 0, 0);
polyPart.AddVertexAt(2, new Point2d(x0 + w, y0 + h), 0, 0, 0);
polyPart.AddVertexAt(3, new Point2d(x0, y0 + h), 0, 0, 0);
polyPart.Closed = true;
ctx.Style?.Apply(polyPart, DrawingStyleManager.Role.PartContour);
ctx.Btr.AppendEntity(polyPart);
ctx.Tr.AddNewlyCreatedDBObject(polyPart, true);
// 内径(车加工态)轮廓
if (innerDiaPrime.HasValue && innerDiaPrime.Value > 0 && innerDiaPrime.Value < w)
{
var xiL = center.X - innerDiaPrime.Value / 2.0;
var xiR = center.X + innerDiaPrime.Value / 2.0;
var yTop = y0 + h;
var l1 = new Line(new Point3d(xiL, y0, 0), new Point3d(xiL, yTop, 0));
ctx.Style?.Apply(l1, DrawingStyleManager.Role.PartContour);
ctx.Btr.AppendEntity(l1);
ctx.Tr.AddNewlyCreatedDBObject(l1, true);
var l2 = new Line(new Point3d(xiR, y0, 0), new Point3d(xiR, yTop, 0));
ctx.Style?.Apply(l2, DrawingStyleManager.Role.PartContour);
ctx.Btr.AppendEntity(l2);
ctx.Tr.AddNewlyCreatedDBObject(l2, true);
}
}
private static void DrawRingSectionHatch(DrawingContext ctx, double xInnerRight, double xOuterRight, double yBottom, double height)
{
if (xOuterRight <= xInnerRight)
{
return;
}
try
{
// 临时边界(用于剖面填充),填充后删除边界
var boundary = new Polyline();
boundary.AddVertexAt(0, new Point2d(xInnerRight, yBottom), 0, 0, 0);
boundary.AddVertexAt(1, new Point2d(xOuterRight, yBottom), 0, 0, 0);
boundary.AddVertexAt(2, new Point2d(xOuterRight, yBottom + height), 0, 0, 0);
boundary.AddVertexAt(3, new Point2d(xInnerRight, 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
{
// ignore
}
}
catch
{
// ignore
}
}
private static string FormatDimNumber(double value)
{
try
{
return value.ToString("0.###");
}
catch
{
return value.ToString();
}
}
private static void TryDrawHardnessSymbol(DrawingContext ctx, double xRight, double yBottom, double height)
{
if (ctx == null || ctx.Bag == null)
{
return;
}
var raw = ctx.Bag.GetString("Hardness");
if (string.IsNullOrWhiteSpace(raw))
{
return;
}
var upper = raw.Trim().ToUpperInvariant();
string symbol;
if (upper.Contains("HB"))
{
symbol = "HB";
}
else if (upper.Contains("HRC"))
{
symbol = "HRC";
}
else if (upper.Contains("HV"))
{
symbol = "HV";
}
else
{
symbol = ExtractLeadingLetters(upper);
if (string.IsNullOrWhiteSpace(symbol))
{
symbol = "HB";
}
}
try
{
var attach = new Point3d(xRight - 2, yBottom + height * 0.25, 0);
var circleCenter = new Point3d(xRight + 25, yBottom + height * 0.25, 0);
const double circleR = 6;
var leader = new Line(attach, new Point3d(circleCenter.X - circleR, circleCenter.Y, 0));
ctx.Style?.Apply(leader, DrawingStyleManager.Role.Text);
ctx.Btr.AppendEntity(leader);
ctx.Tr.AddNewlyCreatedDBObject(leader, true);
var circle = new Circle(circleCenter, new Vector3d(0, 0, 1), circleR);
ctx.Style?.Apply(circle, DrawingStyleManager.Role.Text);
ctx.Btr.AppendEntity(circle);
ctx.Tr.AddNewlyCreatedDBObject(circle, true);
var text = new DBText();
text.TextString = symbol;
text.Height = 3.5;
text.HorizontalMode = TextHorizontalMode.TextCenter;
text.VerticalMode = TextVerticalMode.TextVerticalMid;
text.AlignmentPoint = circleCenter;
text.Position = circleCenter;
ctx.Style?.Apply(text, DrawingStyleManager.Role.Text);
ctx.Btr.AppendEntity(text);
ctx.Tr.AddNewlyCreatedDBObject(text, true);
}
catch
{
// ignore
}
}
private static string ExtractLeadingLetters(string s)
{
if (string.IsNullOrEmpty(s))
{
return string.Empty;
}
var chars = new List<char>();
foreach (var c in s)
{
if (c >= 'A' && c <= 'Z')
{
chars.Add(c);
}
else
{
if (chars.Count > 0)
{
break;
}
}
}
return chars.Count == 0 ? string.Empty : new string(chars.ToArray());
}
#endregion
#region -
private static void DrawDiskFeatures(DrawingContext ctx)
{
var bag = ctx.Bag;
var diameter = bag.GetDoubleOrNull(KeyDiskDiameter);
var height = bag.GetDoubleOrNull(KeyDiskHeight);
if (!diameter.HasValue || diameter.Value <= 0) return;
if (!height.HasValue || height.Value <= 0) return;
double ox = ctx.Center.X - diameter.Value / 2.0;
double oy = ctx.Center.Y - height.Value / 2.0;
double R = diameter.Value / 2.0;
double H = height.Value;
// 绘制饼盘轮廓(俯视图为圆,侧视图为矩形)
// 这里绘制侧视图
var poly = new Polyline();
poly.AddVertexAt(0, new Point2d(ox, oy), 0, 0, 0);
poly.AddVertexAt(1, new Point2d(ox + diameter.Value, oy), 0, 0, 0);
poly.AddVertexAt(2, new Point2d(ox + diameter.Value, oy + H), 0, 0, 0);
poly.AddVertexAt(3, new Point2d(ox, oy + H), 0, 0, 0);
poly.Closed = true;
ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
// 直径标注
var diaTolPlus = bag.GetDoubleOrNull(KeyDiskDiameterTolPlus);
var diaTolMinus = bag.GetDoubleOrNull(KeyDiskDiameterTolMinus);
var diaDimText = BuildDimensionText($"%%c{diameter.Value}", diaTolPlus, diaTolMinus);
AddLinearDim(ctx, new Point3d(ox, oy, 0), new Point3d(ox + diameter.Value, oy, 0),
new Point3d(ctx.Center.X, oy - 20, 0), 0, diaDimText);
// 高度标注
var htTolPlus = bag.GetDoubleOrNull(KeyDiskHeightTolPlus);
var htTolMinus = bag.GetDoubleOrNull(KeyDiskHeightTolMinus);
var htDimText = BuildDimensionText($"{H}", htTolPlus, htTolMinus);
AddLinearDim(ctx, new Point3d(ox + diameter.Value, oy, 0), new Point3d(ox + diameter.Value, oy + H, 0),
new Point3d(ox + diameter.Value + 20, ctx.Center.Y, 0), 90, htDimText);
// 未注圆角使用饼盘专用Key
var unspecifiedFillet = bag.GetDoubleOrNull(KeyDiskFilletRadiusMax);
if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
{
DrawUnspecifiedFilletNote(ctx, ox, oy + H, R, diameter.Value, unspecifiedFillet.Value);
}
// 零件尺寸(如果有)
var diaPrime = bag.GetDoubleOrNull(KeyDiskDiameterPrime);
var heightPrime = bag.GetDoubleOrNull(KeyDiskHeightPrime);
if (diaPrime.HasValue && diaPrime.Value > 0 && heightPrime.HasValue && heightPrime.Value > 0)
{
DrawDiskPartContour(ctx, ox, oy, diameter.Value, H, diaPrime.Value, heightPrime.Value);
}
}
private static void DrawDiskPartContour(DrawingContext ctx, double ox, double oy,
double forgingDia, double forgingH, double partDia, double partH)
{
double offsetX = (forgingDia - partDia) / 2.0;
double offsetY = (forgingH - partH) / 2.0;
var polyPart = new Polyline();
polyPart.AddVertexAt(0, new Point2d(ox + offsetX, oy + offsetY), 0, 0, 0);
polyPart.AddVertexAt(1, new Point2d(ox + offsetX + partDia, oy + offsetY), 0, 0, 0);
polyPart.AddVertexAt(2, new Point2d(ox + offsetX + partDia, oy + offsetY + partH), 0, 0, 0);
polyPart.AddVertexAt(3, new Point2d(ox + offsetX, oy + offsetY + partH), 0, 0, 0);
polyPart.Closed = true;
ctx.Style?.Apply(polyPart, DrawingStyleManager.Role.PartContour);
ctx.Btr.AppendEntity(polyPart);
ctx.Tr.AddNewlyCreatedDBObject(polyPart, true);
// 不再对零件轮廓整块填充剖面线
// 零件直径标注
AddLinearDim(ctx, new Point3d(ox + offsetX, oy + offsetY, 0),
new Point3d(ox + offsetX + partDia, oy + offsetY, 0),
new Point3d(ox + offsetX + partDia / 2, oy + offsetY - 10, 0), 0, $"%%c{partDia}");
// 零件高度标注
AddLinearDim(ctx, new Point3d(ox + offsetX + partDia, oy + offsetY, 0),
new Point3d(ox + offsetX + partDia, oy + offsetY + partH, 0),
new Point3d(ox + offsetX + partDia + 10, oy + offsetY + partH / 2, 0), 90, $"{partH}");
}
#endregion
#region -
private static void DrawShaftFeatures(DrawingContext ctx)
{
var bag = ctx.Bag;
// 圆轴使用Diameter/Length方轴使用BoxSize1/2/3
var isSquareShaft = !string.IsNullOrWhiteSpace(ctx.SpecialCondition)
&& ctx.SpecialCondition.IndexOf("方轴", StringComparison.OrdinalIgnoreCase) >= 0;
if (isSquareShaft)
{
// 方轴使用方体参数绘制
DrawSquareShaftFeatures(ctx);
return;
}
// 圆轴绘制
var diameter = bag.GetDoubleOrNull(KeyDiameter);
var length = bag.GetDoubleOrNull(KeyLength);
if (!diameter.HasValue || diameter.Value <= 0) return;
if (!length.HasValue || length.Value <= 0) return;
double ox = ctx.Center.X - length.Value / 2.0;
double oy = ctx.Center.Y;
double R = diameter.Value / 2.0;
double L = length.Value;
TryLoadLinetype(ctx.Db, ctx.Tr, "CENTER");
// 绘制轴杆轮廓(侧视图为矩形)
var poly = new Polyline();
poly.AddVertexAt(0, new Point2d(ox, oy - R), 0, 0, 0);
poly.AddVertexAt(1, new Point2d(ox + L, oy - R), 0, 0, 0);
poly.AddVertexAt(2, new Point2d(ox + L, oy + R), 0, 0, 0);
poly.AddVertexAt(3, new Point2d(ox, oy + R), 0, 0, 0);
poly.Closed = true;
ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
// 中心线
var centerLine = new Line(new Point3d(ox - 10, oy, 0), new Point3d(ox + L + 10, oy, 0));
ctx.Style?.Apply(centerLine, DrawingStyleManager.Role.Centerline);
ctx.Btr.AppendEntity(centerLine);
ctx.Tr.AddNewlyCreatedDBObject(centerLine, true);
// 直径标注
var diaTolPlus = bag.GetDoubleOrNull(KeyDiameterTolPlus);
var diaTolMinus = bag.GetDoubleOrNull(KeyDiameterTolMinus);
var diaDimText = BuildDimensionText($"%%c{diameter.Value}", diaTolPlus, diaTolMinus);
AddLinearDim(ctx, new Point3d(ox, oy + R, 0), new Point3d(ox, oy - R, 0),
new Point3d(ox - 20, oy, 0), 90, diaDimText);
// 长度标注
var lenTolPlus = bag.GetDoubleOrNull(KeyLengthTolPlus);
var lenTolMinus = bag.GetDoubleOrNull(KeyLengthTolMinus);
var lenDimText = BuildDimensionText($"{L}", lenTolPlus, lenTolMinus);
AddLinearDim(ctx, new Point3d(ox, oy - R, 0), new Point3d(ox + L, oy - R, 0),
new Point3d(ctx.Center.X, oy - R - 20, 0), 0, lenDimText);
// 未注圆角使用轴杆专用Key
var unspecifiedFillet = bag.GetDoubleOrNull(KeyShaftFilletRadiusMax);
if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
{
DrawUnspecifiedFilletNote(ctx, ox, oy, R, L, unspecifiedFillet.Value);
}
// 零件尺寸(如果有)
var diaPrime = bag.GetDoubleOrNull(KeyDiameterPrime);
var lenPrime = bag.GetDoubleOrNull(KeyLengthPrime);
if (diaPrime.HasValue && diaPrime.Value > 0 && lenPrime.HasValue && lenPrime.Value > 0)
{
DrawShaftPartContour(ctx, ox, oy, R, L, diaPrime.Value, lenPrime.Value);
}
}
/// <summary>
/// 方轴绘制(使用方体参数)
/// </summary>
private static void DrawSquareShaftFeatures(DrawingContext ctx)
{
var bag = ctx.Bag;
var size1 = bag.GetDoubleOrNull(KeyBoxSize1);
var size2 = bag.GetDoubleOrNull(KeyBoxSize2);
var size3 = bag.GetDoubleOrNull(KeyBoxSize3);
if (!size1.HasValue || size1.Value <= 0) return;
double width = size1.Value;
double height = size2.HasValue && size2.Value > 0 ? size2.Value : size1.Value;
double depth = size3.HasValue && size3.Value > 0 ? size3.Value : 0;
double ox = ctx.Center.X - width / 2.0;
double oy = ctx.Center.Y - height / 2.0;
// 绘制正视图(矩形)
var poly = new Polyline();
poly.AddVertexAt(0, new Point2d(ox, oy), 0, 0, 0);
poly.AddVertexAt(1, new Point2d(ox + width, oy), 0, 0, 0);
poly.AddVertexAt(2, new Point2d(ox + width, oy + height), 0, 0, 0);
poly.AddVertexAt(3, new Point2d(ox, oy + height), 0, 0, 0);
poly.Closed = true;
ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
// 尺寸1标注
var tol1Plus = bag.GetDoubleOrNull(KeyBoxSize1TolPlus);
var tol1Minus = bag.GetDoubleOrNull(KeyBoxSize1TolMinus);
var dim1Text = BuildDimensionText($"{width}", tol1Plus, tol1Minus);
AddLinearDim(ctx, new Point3d(ox, oy, 0), new Point3d(ox + width, oy, 0),
new Point3d(ctx.Center.X, oy - 20, 0), 0, dim1Text);
// 尺寸2标注
if (size2.HasValue && size2.Value > 0)
{
var tol2Plus = bag.GetDoubleOrNull(KeyBoxSize2TolPlus);
var tol2Minus = bag.GetDoubleOrNull(KeyBoxSize2TolMinus);
var dim2Text = BuildDimensionText($"{height}", tol2Plus, tol2Minus);
AddLinearDim(ctx, new Point3d(ox + width, oy, 0), new Point3d(ox + width, oy + height, 0),
new Point3d(ox + width + 20, ctx.Center.Y, 0), 90, dim2Text);
}
// 尺寸3标注
if (depth > 0)
{
var tol3Plus = bag.GetDoubleOrNull(KeyBoxSize3TolPlus);
var tol3Minus = bag.GetDoubleOrNull(KeyBoxSize3TolMinus);
var dim3Text = BuildDimensionText($"深度:{depth}", tol3Plus, tol3Minus);
try
{
var text = new DBText();
text.TextString = dim3Text;
text.Position = new Point3d(ox + width + 10, oy + height + 10, 0);
text.Height = 5;
ctx.Style?.Apply(text, DrawingStyleManager.Role.Text);
ctx.Btr.AppendEntity(text);
ctx.Tr.AddNewlyCreatedDBObject(text, true);
}
catch { }
}
// 未注圆角使用方体专用Key
var unspecifiedFillet = bag.GetDoubleOrNull(KeyBoxFilletRadiusMax);
if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
{
try
{
var text = new DBText();
text.TextString = $"未注圆角半径R≤{unspecifiedFillet.Value}";
text.Position = new Point3d(ox + width + 10, oy + height + 20, 0);
text.Height = 5;
ctx.Style?.Apply(text, DrawingStyleManager.Role.Text);
ctx.Btr.AppendEntity(text);
ctx.Tr.AddNewlyCreatedDBObject(text, true);
}
catch { }
}
// 零件尺寸
var size1Prime = bag.GetDoubleOrNull(KeyBoxSize1Prime);
var size2Prime = bag.GetDoubleOrNull(KeyBoxSize2Prime);
var size3Prime = bag.GetDoubleOrNull(KeyBoxSize3Prime);
if (size1Prime.HasValue && size1Prime.Value > 0)
{
DrawBlockPartContour(ctx, ox, oy, width, height,
size1Prime.Value, size2Prime ?? size1Prime.Value, size3Prime);
}
}
private static void DrawShaftPartContour(DrawingContext ctx, double ox, double oy,
double R, double L, double partDia, double partLen)
{
double offsetX = (L - partLen) / 2.0;
double Rp = partDia / 2.0;
var polyPart = new Polyline();
polyPart.AddVertexAt(0, new Point2d(ox + offsetX, oy - Rp), 0, 0, 0);
polyPart.AddVertexAt(1, new Point2d(ox + offsetX + partLen, oy - Rp), 0, 0, 0);
polyPart.AddVertexAt(2, new Point2d(ox + offsetX + partLen, oy + Rp), 0, 0, 0);
polyPart.AddVertexAt(3, new Point2d(ox + offsetX, oy + Rp), 0, 0, 0);
polyPart.Closed = true;
ctx.Style?.Apply(polyPart, DrawingStyleManager.Role.PartContour);
ctx.Btr.AppendEntity(polyPart);
ctx.Tr.AddNewlyCreatedDBObject(polyPart, true);
// 不再对零件轮廓整块填充剖面线
// 零件直径标注
AddLinearDim(ctx, new Point3d(ox + offsetX, oy + Rp, 0), new Point3d(ox + offsetX, oy - Rp, 0),
new Point3d(ox + offsetX - 10, oy, 0), 90, $"%%c{partDia}");
// 零件长度标注
AddLinearDim(ctx, new Point3d(ox + offsetX, oy - Rp, 0), new Point3d(ox + offsetX + partLen, oy - Rp, 0),
new Point3d(ox + offsetX + partLen / 2, oy - Rp - 10, 0), 0, $"{partLen}");
}
#endregion
#region -
private static void DrawBlockFeatures(DrawingContext ctx)
{
var bag = ctx.Bag;
// 使用方体专用参数
var size1 = bag.GetDoubleOrNull(KeyBoxSize1);
var size2 = bag.GetDoubleOrNull(KeyBoxSize2);
var size3 = bag.GetDoubleOrNull(KeyBoxSize3);
if (!size1.HasValue || size1.Value <= 0) return;
// 默认为正方形或使用size1
double width = size1.Value;
double height = size2.HasValue && size2.Value > 0 ? size2.Value : size1.Value;
double depth = size3.HasValue && size3.Value > 0 ? size3.Value : 0;
double ox = ctx.Center.X - width / 2.0;
double oy = ctx.Center.Y - height / 2.0;
// 绘制正视图(矩形)
var poly = new Polyline();
poly.AddVertexAt(0, new Point2d(ox, oy), 0, 0, 0);
poly.AddVertexAt(1, new Point2d(ox + width, oy), 0, 0, 0);
poly.AddVertexAt(2, new Point2d(ox + width, oy + height), 0, 0, 0);
poly.AddVertexAt(3, new Point2d(ox, oy + height), 0, 0, 0);
poly.Closed = true;
ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
// 宽度标注 (BoxSize1)
var tol1Plus = bag.GetDoubleOrNull(KeyBoxSize1TolPlus);
var tol1Minus = bag.GetDoubleOrNull(KeyBoxSize1TolMinus);
var dim1Text = BuildDimensionText($"{width}", tol1Plus, tol1Minus);
AddLinearDim(ctx, new Point3d(ox, oy, 0), new Point3d(ox + width, oy, 0),
new Point3d(ctx.Center.X, oy - 20, 0), 0, dim1Text);
// 高度标注 (BoxSize2)
if (size2.HasValue && size2.Value > 0)
{
var tol2Plus = bag.GetDoubleOrNull(KeyBoxSize2TolPlus);
var tol2Minus = bag.GetDoubleOrNull(KeyBoxSize2TolMinus);
var dim2Text = BuildDimensionText($"{height}", tol2Plus, tol2Minus);
AddLinearDim(ctx, new Point3d(ox + width, oy, 0), new Point3d(ox + width, oy + height, 0),
new Point3d(ox + width + 20, ctx.Center.Y, 0), 90, dim2Text);
}
// 深度标注 (BoxSize3) - 如果有的话,以文字形式标注
if (depth > 0)
{
var tol3Plus = bag.GetDoubleOrNull(KeyBoxSize3TolPlus);
var tol3Minus = bag.GetDoubleOrNull(KeyBoxSize3TolMinus);
var dim3Text = BuildDimensionText($"深度:{depth}", tol3Plus, tol3Minus);
try
{
var text = new DBText();
text.TextString = dim3Text;
text.Position = new Point3d(ox + width + 10, oy + height + 10, 0);
text.Height = 5;
ctx.Style?.Apply(text, DrawingStyleManager.Role.Text);
ctx.Btr.AppendEntity(text);
ctx.Tr.AddNewlyCreatedDBObject(text, true);
}
catch { }
}
// 未注圆角使用方体专用Key
var unspecifiedFillet = bag.GetDoubleOrNull(KeyBoxFilletRadiusMax);
if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
{
try
{
var text = new DBText();
text.TextString = $"未注圆角半径R≤{unspecifiedFillet.Value}";
text.Position = new Point3d(ox + width + 10, oy + height + 20, 0);
text.Height = 5;
ctx.Style?.Apply(text, DrawingStyleManager.Role.Text);
ctx.Btr.AppendEntity(text);
ctx.Tr.AddNewlyCreatedDBObject(text, true);
}
catch { }
}
// 有圆头时,绘制两端半圆形圆头
if (ctx.HasRoundHead)
{
double R = height / 2.0; // 圆头半径 = 高度/2示意性
double centerY = oy + height / 2.0;
// 左端圆头(半圆)
try
{
var arcLeft = new Arc(new Point3d(ox, centerY, 0), R, Math.PI / 2, Math.PI * 1.5);
ctx.Style?.Apply(arcLeft, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(arcLeft);
ctx.Tr.AddNewlyCreatedDBObject(arcLeft, true);
}
catch { }
// 右端圆头(半圆)
try
{
var arcRight = new Arc(new Point3d(ox + width, centerY, 0), R, -Math.PI / 2, Math.PI / 2);
ctx.Style?.Apply(arcRight, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(arcRight);
ctx.Tr.AddNewlyCreatedDBObject(arcRight, true);
}
catch { }
}
// 零件尺寸
var size1Prime = bag.GetDoubleOrNull(KeyBoxSize1Prime);
var size2Prime = bag.GetDoubleOrNull(KeyBoxSize2Prime);
var size3Prime = bag.GetDoubleOrNull(KeyBoxSize3Prime);
if (size1Prime.HasValue && size1Prime.Value > 0)
{
DrawBlockPartContour(ctx, ox, oy, width, height,
size1Prime.Value, size2Prime ?? size1Prime.Value, size3Prime);
}
}
private static void DrawBlockPartContour(DrawingContext ctx, double ox, double oy,
double forgingW, double forgingH, double partW, double partH, double? partD)
{
double offsetX = (forgingW - partW) / 2.0;
double offsetY = (forgingH - partH) / 2.0;
var polyPart = new Polyline();
polyPart.AddVertexAt(0, new Point2d(ox + offsetX, oy + offsetY), 0, 0, 0);
polyPart.AddVertexAt(1, new Point2d(ox + offsetX + partW, oy + offsetY), 0, 0, 0);
polyPart.AddVertexAt(2, new Point2d(ox + offsetX + partW, oy + offsetY + partH), 0, 0, 0);
polyPart.AddVertexAt(3, new Point2d(ox + offsetX, oy + offsetY + partH), 0, 0, 0);
polyPart.Closed = true;
ctx.Style?.Apply(polyPart, DrawingStyleManager.Role.PartContour);
ctx.Btr.AppendEntity(polyPart);
ctx.Tr.AddNewlyCreatedDBObject(polyPart, true);
// 不再对零件轮廓整块填充剖面线
// 零件尺寸1标注
AddLinearDim(ctx, new Point3d(ox + offsetX, oy + offsetY, 0),
new Point3d(ox + offsetX + partW, oy + offsetY, 0),
new Point3d(ox + offsetX + partW / 2, oy + offsetY - 10, 0), 0, $"{partW}");
// 零件尺寸2标注
AddLinearDim(ctx, new Point3d(ox + offsetX + partW, oy + offsetY, 0),
new Point3d(ox + offsetX + partW, oy + offsetY + partH, 0),
new Point3d(ox + offsetX + partW + 10, oy + offsetY + partH / 2, 0), 90, $"{partH}");
// 零件尺寸3标注如果有
if (partD.HasValue && partD.Value > 0)
{
try
{
var text = new DBText();
text.TextString = $"深度:{partD.Value}";
text.Position = new Point3d(ox + offsetX + partW + 10, oy + offsetY + partH + 5, 0);
text.Height = 4;
ctx.Style?.Apply(text, DrawingStyleManager.Role.Text);
ctx.Btr.AppendEntity(text);
ctx.Tr.AddNewlyCreatedDBObject(text, true);
}
catch { }
}
}
#endregion
#region
private static string BuildDimensionText(string baseText, double? tolPlus, double? tolMinus)
{
if (!tolPlus.HasValue && !tolMinus.HasValue)
{
return baseText;
}
// 公差显示为上下并排(堆叠文本)。
// AutoCAD MText stack: \Supper#lower; => 上下堆叠且无分隔线。
// 这里将公差缩小到 0.7 倍以贴近常见标注样式。
const double tolScale = 0.7;
var plusStr = string.Empty;
var minusStr = string.Empty;
if (tolPlus.HasValue)
{
plusStr = tolPlus.Value >= 0
? $"+{FormatDimNumber(tolPlus.Value)}"
: $"{FormatDimNumber(tolPlus.Value)}";
}
if (tolMinus.HasValue)
{
// 下偏差通常显示为负号;如果传入为正数则强制加上负号。
minusStr = tolMinus.Value <= 0
? $"{FormatDimNumber(tolMinus.Value)}"
: $"-{FormatDimNumber(tolMinus.Value)}";
}
if (tolPlus.HasValue && tolMinus.HasValue)
{
return $"{baseText}{{\\H{tolScale}x;\\S{plusStr}#{minusStr};}}";
}
// 只有单边公差时,仍缩小显示。
var single = tolPlus.HasValue ? plusStr : minusStr;
return $"{baseText}{{\\H{tolScale}x;{single}}}";
}
private static void AddLinearDim(DrawingContext ctx, Point3d pt1, Point3d pt2, Point3d dimLinePt,
double rotationDeg, string textOverride)
{
try
{
var prevDb = HostApplicationServices.WorkingDatabase;
HostApplicationServices.WorkingDatabase = ctx.Db;
try
{
double rotRad = rotationDeg * Math.PI / 180.0;
// Use current drawing's dimension style (template-controlled).
var dim = new RotatedDimension(rotRad, pt1, pt2, dimLinePt, textOverride, ctx.Db.Dimstyle);
try { dim.SetDatabaseDefaults(); } catch { }
try { dim.Normal = Vector3d.ZAxis; } catch { }
TryApplyDimSizeOverrides(dim);
TryApplyDimLayoutOverrides(dim, pt1, pt2, dimLinePt, rotRad);
ctx.Style?.Apply(dim, DrawingStyleManager.Role.Dimension);
ctx.Btr.AppendEntity(dim);
ctx.Tr.AddNewlyCreatedDBObject(dim, true);
// Ensure dimension graphics (including text) are computed and persisted in the DWG.
// Some CAD viewers may otherwise show '*' placeholders.
try
{
dim.RecomputeDimensionBlock(true);
}
catch
{
// ignore
}
}
finally
{
HostApplicationServices.WorkingDatabase = prevDb;
}
}
catch
{
// 忽略标注错误
}
}
private static void TryApplyDimSizeOverrides(Dimension dim)
{
if (dim == null)
{
return;
}
// Template dimstyle may have very small DIMTXT; apply per-dimension overrides to keep it readable.
// Values are in drawing units (typically mm).
TrySetDimProp(dim, "Dimtxt", 3.5);
TrySetDimProp(dim, "Dimasz", 2.5);
TrySetDimProp(dim, "Dimgap", 1.0);
TrySetDimProp(dim, "Dimexe", 1.0);
TrySetDimProp(dim, "Dimexo", 1.0);
}
private static void TryApplyDimLayoutOverrides(Dimension dim, Point3d pt1, Point3d pt2, Point3d dimLinePt, double rotRad)
{
if (dim == null)
{
return;
}
// 1) 文本与尺寸线平行(避免模板把文字强制水平)。
TrySetDimProp(dim, "Dimtih", (short)0);
TrySetDimProp(dim, "Dimtoh", (short)0);
// 2) 不抑制尺寸界线(修复半圆图左侧中心线位置“尺寸界线为空”的情况)。
TrySetDimProp(dim, "Dimse1", false);
TrySetDimProp(dim, "Dimse2", false);
// 3) 尺寸线位于尺寸(文字)上方:将文字整体移到尺寸线的“下方”(相对尺寸线法向的顺时针侧)。
try
{
var dimtxt = TryGetDoubleProp(dim, "Dimtxt") ?? 3.5;
var dimgap = TryGetDoubleProp(dim, "Dimgap") ?? 1.0;
var offset = Math.Max(1.0, dimtxt + dimgap);
var v = new Vector3d(-Math.Sin(rotRad), Math.Cos(rotRad), 0); // 尺寸线法向(逆时针)
var q1 = ProjectToLineAlongNormal(pt1, dimLinePt, v);
var q2 = ProjectToLineAlongNormal(pt2, dimLinePt, v);
var mid = new Point3d((q1.X + q2.X) / 2.0, (q1.Y + q2.Y) / 2.0, 0);
var textPos = mid - v.MultiplyBy(offset);
TrySetDimProp(dim, "TextPosition", textPos);
TrySetDimProp(dim, "TextRotation", rotRad);
}
catch
{
// ignore
}
}
private static Point3d ProjectToLineAlongNormal(Point3d p, Point3d linePoint, Vector3d normal)
{
// 线:通过 linePoint方向与 normal 垂直(即 (x-linePoint)·normal = 0
// 沿 normal 方向投影q = p - normal * ((p-linePoint)·normal)
var d = (p - linePoint).DotProduct(normal);
return p - normal.MultiplyBy(d);
}
private static double? TryGetDoubleProp(object obj, string propName)
{
if (obj == null || string.IsNullOrWhiteSpace(propName))
{
return null;
}
try
{
var prop = obj.GetType().GetProperty(propName);
if (prop == null || !prop.CanRead)
{
return null;
}
var v = prop.GetValue(obj, null);
if (v is double d) return d;
if (v is float f) return f;
if (v is int i) return i;
if (v is short s) return s;
return null;
}
catch
{
return null;
}
}
private static void TrySetDimProp(object obj, string propName, double value)
{
if (obj == null || string.IsNullOrWhiteSpace(propName))
{
return;
}
try
{
var prop = obj.GetType().GetProperty(propName);
if (prop == null || !prop.CanWrite)
{
return;
}
if (prop.PropertyType == typeof(double))
{
prop.SetValue(obj, value, null);
return;
}
if (prop.PropertyType == typeof(float))
{
prop.SetValue(obj, (float)value, null);
return;
}
if (prop.PropertyType == typeof(int))
{
prop.SetValue(obj, (int)Math.Round(value), null);
return;
}
if (prop.PropertyType == typeof(short))
{
prop.SetValue(obj, (short)Math.Round(value), null);
return;
}
if (prop.PropertyType == typeof(bool))
{
prop.SetValue(obj, Math.Abs(value) > 0.000001, null);
return;
}
}
catch
{
// ignore
}
}
private static void TrySetDimProp(object obj, string propName, bool value)
{
if (obj == null || string.IsNullOrWhiteSpace(propName))
{
return;
}
try
{
var prop = obj.GetType().GetProperty(propName);
if (prop == null || !prop.CanWrite)
{
return;
}
if (prop.PropertyType == typeof(bool))
{
prop.SetValue(obj, value, null);
return;
}
if (prop.PropertyType == typeof(short))
{
prop.SetValue(obj, (short)(value ? 1 : 0), null);
return;
}
if (prop.PropertyType == typeof(int))
{
prop.SetValue(obj, value ? 1 : 0, null);
}
}
catch
{
// ignore
}
}
private static void TrySetDimProp(object obj, string propName, short value)
{
if (obj == null || string.IsNullOrWhiteSpace(propName))
{
return;
}
try
{
var prop = obj.GetType().GetProperty(propName);
if (prop == null || !prop.CanWrite)
{
return;
}
if (prop.PropertyType == typeof(short))
{
prop.SetValue(obj, value, null);
return;
}
if (prop.PropertyType == typeof(int))
{
prop.SetValue(obj, (int)value, null);
return;
}
if (prop.PropertyType == typeof(double))
{
prop.SetValue(obj, (double)value, null);
}
}
catch
{
// ignore
}
}
private static void TrySetDimProp(object obj, string propName, Point3d value)
{
if (obj == null || string.IsNullOrWhiteSpace(propName))
{
return;
}
try
{
var prop = obj.GetType().GetProperty(propName);
if (prop == null || !prop.CanWrite)
{
return;
}
if (prop.PropertyType == typeof(Point3d))
{
prop.SetValue(obj, value, null);
}
}
catch
{
// ignore
}
}
private static void TryLoadLinetype(Database db, Transaction tr, string linetypeName)
{
try
{
var linetypeTbl = (LinetypeTable)tr.GetObject(db.LinetypeTableId, OpenMode.ForRead);
if (!linetypeTbl.Has(linetypeName))
{
try
{
db.LoadLineTypeFile(linetypeName, "acad.lin");
}
catch { }
}
}
catch { }
}
/// <summary>
/// 对参数包中的尺寸参数应用缩放比例
/// </summary>
private static ParamBag ScaleParamBag(ParamBag original, double scaleFactor)
{
if (original == null || scaleFactor <= 0 || scaleFactor >= 1.0)
{
return original;
}
var scaled = new ParamBag();
// 需要缩放的尺寸参数Key列表
var sizeKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
// 环形参数
KeyOuterDiameter1, KeyInnerDiameter2, KeyHeight1,
KeyOuterDiameter1Prime, KeyInnerDiameter2Prime, KeyHeight1Prime,
KeyMinWallThickness,
// 饼盘参数
KeyDiskDiameter, KeyDiskHeight,
KeyDiskDiameterPrime, KeyDiskHeightPrime,
// 轴杆参数
KeyDiameter, KeyLength,
KeyDiameterPrime, KeyLengthPrime,
// 方体参数
KeyBoxSize1, KeyBoxSize2, KeyBoxSize3,
KeyBoxSize1Prime, KeyBoxSize2Prime, KeyBoxSize3Prime,
// 圆角参数
KeyUnspecifiedFilletRadiusMax, KeyInnerRadiusMax,
KeyDiskFilletRadiusMax, KeyShaftFilletRadiusMax,
KeyBoxFilletRadiusMax, KeyBoxRoundHeadFilletRadiusMax
};
// 公差参数也需要缩放
var toleranceKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
KeyOuterDiameter1TolPlus, KeyOuterDiameter1TolMinus,
KeyInnerDiameter2TolPlus, KeyInnerDiameter2TolMinus,
KeyHeight1TolPlus, KeyHeight1TolMinus,
KeyDiskDiameterTolPlus, KeyDiskDiameterTolMinus,
KeyDiskHeightTolPlus, KeyDiskHeightTolMinus,
KeyDiameterTolPlus, KeyDiameterTolMinus,
KeyLengthTolPlus, KeyLengthTolMinus,
KeyBoxSize1TolPlus, KeyBoxSize1TolMinus,
KeyBoxSize2TolPlus, KeyBoxSize2TolMinus,
KeyBoxSize3TolPlus, KeyBoxSize3TolMinus
};
foreach (var key in original.GetKeys())
{
var value = original.GetString(key);
if (sizeKeys.Contains(key) || toleranceKeys.Contains(key))
{
// 尝试解析为数值并缩放
if (double.TryParse(value, out var numValue))
{
var scaledValue = numValue * scaleFactor;
// 保留适当的小数位数
scaled.Set(key, scaledValue.ToString("F2"));
}
else
{
scaled.Set(key, value);
}
}
else
{
// 非尺寸参数直接复制
scaled.Set(key, value);
}
}
return scaled;
}
#endregion
}
}