CadParamPluging/Cad/FeatureDrivenDrawer.cs
2025-12-18 14:47:17 +08:00

948 lines
38 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using CadParamPluging.Common;
namespace CadParamPluging.Cad
{
/// <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 KeyOuterDiameter1Prime = "OuterDiameter1Prime";
public const string KeyInnerDiameter2Prime = "InnerDiameter2Prime";
public const string KeyHeight1Prime = "Height1Prime";
// 可选特征参数
public const string KeyUnspecifiedFilletRadiusMax = "UnspecifiedFilletRadiusMax";
public const string KeyInnerRadiusMax = "InnerRadiusMax";
public const string KeyRoundHeadFilletRadiusMax = "RoundHeadFilletRadiusMax";
// 饼盘参数
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 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 KeySize1 = "Size1";
public const string KeySize2 = "Size2";
public const string KeySize3 = "Size3";
public const string KeySize1TolPlus = "Size1TolPlus";
public const string KeySize1TolMinus = "Size1TolMinus";
public const string KeySize2TolPlus = "Size2TolPlus";
public const string KeySize2TolMinus = "Size2TolMinus";
public const string KeySize3TolPlus = "Size3TolPlus";
public const string KeySize3TolMinus = "Size3TolMinus";
#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 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;
}
#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 = height + extraMargin * 2,
Height = outerDia + 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(KeySize1) ?? bag.GetDoubleOrNull("Size123") ?? 0;
var size2 = bag.GetDoubleOrNull(KeySize2) ?? 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="center">绘图中心点</param>
/// <param name="scaleFactor">缩放比例1.0表示不缩放)</param>
public static void Draw(CadContext ctx, ParamBag bag, string deliveryStatus, string structuralFeature,
string specialCondition = 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;
var btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
var context = new DrawingContext
{
Ctx = ctx,
Bag = effectiveBag,
Center = center ?? Point3d.Origin,
DeliveryStatus = deliveryStatus,
StructuralFeature = structuralFeature,
SpecialCondition = specialCondition,
Btr = btr
};
// 根据结构特征分发到对应绘制器
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; // 缺少高度,无法绘制
}
// 计算图形偏移,使其居中
double ox = ctx.Center.X - height.Value / 2.0;
double oy = ctx.Center.Y;
double R = outerDia.Value / 2.0;
// 加载虚线线型
TryLoadLinetype(ctx.Db, ctx.Tr, "DASHED");
// === 特征1: 锻件外轮廓(必绘) ===
DrawForgingOuterContour(ctx, ox, oy, R, height.Value);
// === 特征2: 外径公差标注(如果有公差参数) ===
var outerTolPlus = bag.GetDoubleOrNull(KeyOuterDiameter1TolPlus);
var outerTolMinus = bag.GetDoubleOrNull(KeyOuterDiameter1TolMinus);
DrawOuterDiameterDimension(ctx, ox, oy, R, outerDia.Value, outerTolPlus, outerTolMinus);
// === 特征3: 内孔(如果有内径参数) ===
var innerDia = bag.GetDoubleOrNull(KeyInnerDiameter2);
if (innerDia.HasValue && innerDia.Value > 0)
{
double r = innerDia.Value / 2.0;
var innerTolPlus = bag.GetDoubleOrNull(KeyInnerDiameter2TolPlus);
var innerTolMinus = bag.GetDoubleOrNull(KeyInnerDiameter2TolMinus);
DrawInnerHole(ctx, ox, oy, r, height.Value);
DrawInnerDiameterDimension(ctx, ox, oy, r, height.Value, innerDia.Value, innerTolPlus, innerTolMinus);
// === 特征4: 内径圆角如果有内径半径R参数且是中心冲孔 ===
var innerRadiusMax = bag.GetDoubleOrNull(KeyInnerRadiusMax);
if (innerRadiusMax.HasValue && innerRadiusMax.Value > 0 && ctx.IsCenterPunched)
{
DrawInnerFillets(ctx, ox, oy, r, height.Value, innerRadiusMax.Value);
}
}
// === 特征5: 高度/长度标注 ===
var heightTolPlus = bag.GetDoubleOrNull(KeyHeight1TolPlus);
var heightTolMinus = bag.GetDoubleOrNull(KeyHeight1TolMinus);
DrawHeightDimension(ctx, ox, oy, R, height.Value, heightTolPlus, heightTolMinus);
// === 特征6: 未注圆角(如果有该参数) ===
var unspecifiedFillet = bag.GetDoubleOrNull(KeyUnspecifiedFilletRadiusMax);
if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
{
DrawUnspecifiedFilletNote(ctx, ox, oy, R, height.Value, unspecifiedFillet.Value);
}
// === 特征7: 最小壁厚T标注如果有该参数 ===
var minWallThickness = bag.GetDoubleOrNull(KeyMinWallThickness);
if (minWallThickness.HasValue && minWallThickness.Value > 0 && innerDia.HasValue)
{
DrawMinWallThicknessNote(ctx, ox, oy, R, innerDia.Value / 2.0, minWallThickness.Value);
}
// === 特征8: 零件轮廓(车加工态) ===
if (ctx.IsMachined)
{
var outerDiaPrime = bag.GetDoubleOrNull(KeyOuterDiameter1Prime);
var innerDiaPrime = bag.GetDoubleOrNull(KeyInnerDiameter2Prime);
var heightPrime = bag.GetDoubleOrNull(KeyHeight1Prime);
if (outerDiaPrime.HasValue && outerDiaPrime.Value > 0 && heightPrime.HasValue && heightPrime.Value > 0)
{
DrawPartContour(ctx, ox, oy, height.Value, outerDiaPrime.Value, innerDiaPrime, heightPrime.Value);
}
}
}
private static void DrawForgingOuterContour(DrawingContext ctx, double ox, double oy, double R, double height)
{
var poly = new Polyline();
poly.AddVertexAt(0, new Point2d(ox, oy - R), 0, 0, 0);
poly.AddVertexAt(1, new Point2d(ox + height, oy - R), 0, 0, 0);
poly.AddVertexAt(2, new Point2d(ox + height, oy + R), 0, 0, 0);
poly.AddVertexAt(3, new Point2d(ox, oy + R), 0, 0, 0);
poly.Closed = true;
poly.ColorIndex = 7;
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
}
private static void DrawInnerHole(DrawingContext ctx, double ox, double oy, double r, double height)
{
var lineTop = new Line(new Point3d(ox, oy + r, 0), new Point3d(ox + height, oy + r, 0));
lineTop.ColorIndex = 2;
lineTop.Linetype = "DASHED";
ctx.Btr.AppendEntity(lineTop);
ctx.Tr.AddNewlyCreatedDBObject(lineTop, true);
var lineBot = new Line(new Point3d(ox, oy - r, 0), new Point3d(ox + height, oy - r, 0));
lineBot.ColorIndex = 2;
lineBot.Linetype = "DASHED";
ctx.Btr.AppendEntity(lineBot);
ctx.Tr.AddNewlyCreatedDBObject(lineBot, true);
}
private static void DrawInnerFillets(DrawingContext ctx, double ox, double oy, double r, double height, double filletR)
{
// 在内孔四角绘制圆角示意
// 左上角
DrawFilletArc(ctx, ox + filletR, oy + r - filletR, filletR, Math.PI / 2, Math.PI);
// 左下角
DrawFilletArc(ctx, ox + filletR, oy - r + filletR, filletR, Math.PI, Math.PI * 1.5);
// 右上角
DrawFilletArc(ctx, ox + height - filletR, oy + r - filletR, filletR, 0, Math.PI / 2);
// 右下角
DrawFilletArc(ctx, ox + height - filletR, oy - r + 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);
arc.ColorIndex = 7;
ctx.Btr.AppendEntity(arc);
ctx.Tr.AddNewlyCreatedDBObject(arc, true);
}
catch
{
// 忽略圆弧创建错误
}
}
private static void DrawOuterDiameterDimension(DrawingContext ctx, double ox, double oy, double R,
double diameter, double? tolPlus, double? tolMinus)
{
var dimText = BuildDimensionText($"%%c{diameter}", tolPlus, tolMinus);
AddLinearDim(ctx, new Point3d(ox, oy + R, 0), new Point3d(ox, oy - R, 0),
new Point3d(ox - 20, oy, 0), 90, dimText);
}
private static void DrawInnerDiameterDimension(DrawingContext ctx, double ox, double oy, double r,
double height, double diameter, double? tolPlus, double? tolMinus)
{
var dimText = BuildDimensionText($"%%c{diameter}", tolPlus, tolMinus);
AddLinearDim(ctx, new Point3d(ox, oy + r, 0), new Point3d(ox, oy - r, 0),
new Point3d(ox + height + 20, oy, 0), 90, dimText);
}
private static void DrawHeightDimension(DrawingContext ctx, double ox, double oy, double R,
double height, double? tolPlus, double? tolMinus)
{
var baseText = $"{height}min";
var dimText = BuildDimensionText(baseText, tolPlus, tolMinus);
AddLinearDim(ctx, new Point3d(ox, oy - R, 0), new Point3d(ox + height, oy - R, 0),
new Point3d(ox + height / 2, oy - R - 20, 0), 0, 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;
text.ColorIndex = 7;
ctx.Btr.AppendEntity(text);
ctx.Tr.AddNewlyCreatedDBObject(text, true);
}
catch
{
// 忽略
}
}
private static void DrawMinWallThicknessNote(DrawingContext ctx, double ox, double oy, double R, double r, double thickness)
{
// 壁厚标注线 - 在截面中间位置
try
{
// 在内外径之间画一条标注线
var midX = ox;
var midY = oy + (R + r) / 2;
var leader = new Line(new Point3d(midX, oy + r, 0), new Point3d(midX, oy + R, 0));
leader.ColorIndex = 4;
ctx.Btr.AppendEntity(leader);
ctx.Tr.AddNewlyCreatedDBObject(leader, true);
var text = new DBText();
text.TextString = $"T≥{thickness}";
text.Position = new Point3d(midX - 20, midY, 0);
text.Height = 4;
text.ColorIndex = 4;
ctx.Btr.AppendEntity(text);
ctx.Tr.AddNewlyCreatedDBObject(text, true);
}
catch
{
// 忽略
}
}
private static void DrawPartContour(DrawingContext ctx, double ox, double oy, double forgingHeight,
double outerDiaPrime, double? innerDiaPrime, double heightPrime)
{
double offsetX = (forgingHeight - heightPrime) / 2.0;
double Rp = outerDiaPrime / 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 + heightPrime, oy - Rp), 0, 0, 0);
polyPart.AddVertexAt(2, new Point2d(ox + offsetX + heightPrime, oy + Rp), 0, 0, 0);
polyPart.AddVertexAt(3, new Point2d(ox + offsetX, oy + Rp), 0, 0, 0);
polyPart.Closed = true;
polyPart.ColorIndex = 7;
ctx.Btr.AppendEntity(polyPart);
ctx.Tr.AddNewlyCreatedDBObject(polyPart, true);
// 填充
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 = 0.8;
hatch.PatternAngle = 0;
hatch.Associative = false;
hatch.ColorIndex = 7;
var ids = new ObjectIdCollection();
ids.Add(polyPart.ObjectId);
hatch.AppendLoop(HatchLoopTypes.External, ids);
hatch.EvaluateHatch(true);
}
catch
{
// 忽略
}
// 零件外径标注
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{outerDiaPrime}");
// 零件高度标注
AddLinearDim(ctx, new Point3d(ox + offsetX, oy - Rp, 0), new Point3d(ox + offsetX + heightPrime, oy - Rp, 0),
new Point3d(ox + offsetX + heightPrime / 2, oy - Rp - 10, 0), 0, $"{heightPrime}");
}
#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;
poly.ColorIndex = 7;
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);
// 未注圆角
var unspecifiedFillet = bag.GetDoubleOrNull(KeyUnspecifiedFilletRadiusMax);
if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
{
DrawUnspecifiedFilletNote(ctx, ox, oy + H, R, diameter.Value, unspecifiedFillet.Value);
}
}
#endregion
#region -
private static void DrawShaftFeatures(DrawingContext ctx)
{
var bag = ctx.Bag;
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;
poly.ColorIndex = 7;
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));
centerLine.ColorIndex = 1;
centerLine.Linetype = "CENTER";
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);
// 未注圆角
var unspecifiedFillet = bag.GetDoubleOrNull(KeyUnspecifiedFilletRadiusMax);
if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
{
DrawUnspecifiedFilletNote(ctx, ox, oy, R, L, unspecifiedFillet.Value);
}
// 圆头处圆角(如果有圆头)
if (ctx.HasRoundHead)
{
var roundHeadFillet = bag.GetDoubleOrNull(KeyRoundHeadFilletRadiusMax);
if (roundHeadFillet.HasValue && roundHeadFillet.Value > 0)
{
// 绘制圆头
DrawRoundHeadEnds(ctx, ox, oy, R, L, roundHeadFillet.Value);
}
}
}
private static void DrawRoundHeadEnds(DrawingContext ctx, double ox, double oy, double R, double L, double filletR)
{
// 左端圆头
try
{
var arcLeft = new Arc(new Point3d(ox, oy, 0), R, Math.PI / 2, Math.PI * 1.5);
arcLeft.ColorIndex = 7;
ctx.Btr.AppendEntity(arcLeft);
ctx.Tr.AddNewlyCreatedDBObject(arcLeft, true);
}
catch { }
// 右端圆头
try
{
var arcRight = new Arc(new Point3d(ox + L, oy, 0), R, -Math.PI / 2, Math.PI / 2);
arcRight.ColorIndex = 7;
ctx.Btr.AppendEntity(arcRight);
ctx.Tr.AddNewlyCreatedDBObject(arcRight, true);
}
catch { }
}
#endregion
#region -
private static void DrawBlockFeatures(DrawingContext ctx)
{
var bag = ctx.Bag;
// 尝试读取Size1/2/3如果没有则尝试通用尺寸
var size1 = bag.GetDoubleOrNull(KeySize1) ?? bag.GetDoubleOrNull("Size123");
var size2 = bag.GetDoubleOrNull(KeySize2);
var size3 = bag.GetDoubleOrNull(KeySize3);
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;
poly.ColorIndex = 7;
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
// 宽度标注 (Size1)
var tol1Plus = bag.GetDoubleOrNull(KeySize1TolPlus);
var tol1Minus = bag.GetDoubleOrNull(KeySize1TolMinus);
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);
// 高度标注 (Size2)
if (size2.HasValue && size2.Value > 0)
{
var tol2Plus = bag.GetDoubleOrNull(KeySize2TolPlus);
var tol2Minus = bag.GetDoubleOrNull(KeySize2TolMinus);
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);
}
// 深度标注 (Size3) - 如果有的话,以文字形式标注
if (depth > 0)
{
var tol3Plus = bag.GetDoubleOrNull(KeySize3TolPlus);
var tol3Minus = bag.GetDoubleOrNull(KeySize3TolMinus);
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;
text.ColorIndex = 7;
ctx.Btr.AppendEntity(text);
ctx.Tr.AddNewlyCreatedDBObject(text, true);
}
catch { }
}
// 未注圆角
var unspecifiedFillet = bag.GetDoubleOrNull(KeyUnspecifiedFilletRadiusMax);
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;
text.ColorIndex = 7;
ctx.Btr.AppendEntity(text);
ctx.Tr.AddNewlyCreatedDBObject(text, true);
}
catch { }
}
// 圆头处圆角
if (ctx.HasRoundHead)
{
var roundHeadFillet = bag.GetDoubleOrNull(KeyRoundHeadFilletRadiusMax);
if (roundHeadFillet.HasValue && roundHeadFillet.Value > 0)
{
// 绘制四角圆角
DrawFilletArc(ctx, ox + roundHeadFillet.Value, oy + roundHeadFillet.Value, roundHeadFillet.Value, Math.PI, Math.PI * 1.5);
DrawFilletArc(ctx, ox + width - roundHeadFillet.Value, oy + roundHeadFillet.Value, roundHeadFillet.Value, Math.PI * 1.5, Math.PI * 2);
DrawFilletArc(ctx, ox + width - roundHeadFillet.Value, oy + height - roundHeadFillet.Value, roundHeadFillet.Value, 0, Math.PI / 2);
DrawFilletArc(ctx, ox + roundHeadFillet.Value, oy + height - roundHeadFillet.Value, roundHeadFillet.Value, Math.PI / 2, Math.PI);
}
}
}
#endregion
#region
private static string BuildDimensionText(string baseText, double? tolPlus, double? tolMinus)
{
if (!tolPlus.HasValue && !tolMinus.HasValue)
{
return baseText;
}
var result = baseText;
// 公差格式: 基本尺寸 +上差/-下差
if (tolPlus.HasValue && tolMinus.HasValue)
{
var plusStr = tolPlus.Value >= 0 ? $"+{tolPlus.Value}" : $"{tolPlus.Value}";
var minusStr = tolMinus.Value >= 0 ? $"+{tolMinus.Value}" : $"{tolMinus.Value}";
result += $"({plusStr}/{minusStr})";
}
else if (tolPlus.HasValue)
{
var plusStr = tolPlus.Value >= 0 ? $"+{tolPlus.Value}" : $"{tolPlus.Value}";
result += $"({plusStr})";
}
else if (tolMinus.HasValue)
{
var minusStr = tolMinus.Value >= 0 ? $"+{tolMinus.Value}" : $"{tolMinus.Value}";
result += $"({minusStr})";
}
return result;
}
private static void AddLinearDim(DrawingContext ctx, Point3d pt1, Point3d pt2, Point3d dimLinePt,
double rotationDeg, string textOverride)
{
try
{
double rotRad = rotationDeg * Math.PI / 180.0;
var dim = new RotatedDimension(rotRad, pt1, pt2, dimLinePt, textOverride, ctx.Db.Dimstyle);
dim.ColorIndex = 4;
ctx.Btr.AppendEntity(dim);
ctx.Tr.AddNewlyCreatedDBObject(dim, true);
}
catch
{
// 忽略标注错误
}
}
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,
// 轴杆参数
KeyDiameter, KeyLength,
// 方形参数
KeySize1, KeySize2, KeySize3, "Size123",
// 圆角参数
KeyUnspecifiedFilletRadiusMax, KeyInnerRadiusMax, KeyRoundHeadFilletRadiusMax
};
// 公差参数也需要缩放
var toleranceKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
KeyOuterDiameter1TolPlus, KeyOuterDiameter1TolMinus,
KeyInnerDiameter2TolPlus, KeyInnerDiameter2TolMinus,
KeyHeight1TolPlus, KeyHeight1TolMinus,
KeyDiskDiameterTolPlus, KeyDiskDiameterTolMinus,
KeyDiskHeightTolPlus, KeyDiskHeightTolMinus,
KeyDiameterTolPlus, KeyDiameterTolMinus,
KeyLengthTolPlus, KeyLengthTolMinus,
KeySize1TolPlus, KeySize1TolMinus,
KeySize2TolPlus, KeySize2TolMinus,
KeySize3TolPlus, KeySize3TolMinus
};
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
}
}