CadParamPluging/Cad/Drawers/RingRawFreeForgeCenterPunchDrawer.cs

484 lines
22 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 Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using CadParamPluging.Common;
namespace CadParamPluging.Cad.Drawers
{
public static class RingRawFreeForgeCenterPunchDrawer
{
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));
// Apply scaling
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;
}
// Construct DrawingContext
// Note: SpecialCondition needs to be "中心冲孔"
var context = new FeatureDrivenDrawer.DrawingContext
{
Ctx = ctx,
Bag = effectiveBag,
OriginalBag = bag,
Center = center,
DeliveryStatus = "毛料态",
StructuralFeature = "环形",
SpecialCondition = "中心冲孔",
ProcessMethod = "自由锻",
Btr = btr,
// We need to instantiate DrawingStyleManager. Accessing internal constructor via reflection or if it's internal to assembly we are fine.
// Assuming same assembly.
Style = new DrawingStyleManager(db, tr)
};
DrawCore(context);
}
private static ParamBag ScaleParamBag(ParamBag original, double scaleFactor)
{
if (original == null || scaleFactor <= 0 || (Math.Abs(scaleFactor - 1.0) < 1e-6))
{
return original;
}
var scaled = new ParamBag();
// 需要缩放的尺寸参数Key列表
var sizeKeys = new System.Collections.Generic.HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
// 环形参数
FeatureDrivenDrawer.KeyOuterDiameter1, FeatureDrivenDrawer.KeyInnerDiameter2, FeatureDrivenDrawer.KeyHeight1,
FeatureDrivenDrawer.KeyOuterDiameter1Prime, FeatureDrivenDrawer.KeyInnerDiameter2Prime, FeatureDrivenDrawer.KeyHeight1Prime,
FeatureDrivenDrawer.KeyMinWallThickness,
// 圆角参数
FeatureDrivenDrawer.KeyUnspecifiedFilletRadiusMax, FeatureDrivenDrawer.KeyInnerRadiusMax,
// 包含公差参数以保持一致性
FeatureDrivenDrawer.KeyOuterDiameter1TolPlus, FeatureDrivenDrawer.KeyOuterDiameter1TolMinus,
FeatureDrivenDrawer.KeyInnerDiameter2TolPlus, FeatureDrivenDrawer.KeyInnerDiameter2TolMinus,
FeatureDrivenDrawer.KeyHeight1TolPlus, FeatureDrivenDrawer.KeyHeight1TolMinus
};
foreach (var key in original.GetKeys())
{
var value = original.GetString(key);
if (sizeKeys.Contains(key))
{
// 尝试解析为数值并缩放
if (double.TryParse(value, out var numValue))
{
var scaledValue = numValue * scaleFactor;
// 保留适当的小数位数,避免精度问题
scaled.Set(key, scaledValue.ToString("F4"));
}
else
{
scaled.Set(key, value);
}
}
else
{
// 非尺寸参数直接复制
scaled.Set(key, value);
}
}
return scaled;
}
private static void DrawCore(FeatureDrivenDrawer.DrawingContext ctx)
{
var bag = ctx.Bag;
var outerDia = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyOuterDiameter1);
var height = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1);
if (!outerDia.HasValue || !height.HasValue) return;
double W = outerDia.Value;
double H = height.Value;
double ox = ctx.Center.X - W / 2.0;
double oy = ctx.Center.Y - H / 2.0;
// Unconditionally retrieve variables for Part Contour (Prime parameters)
var outerDiaPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyOuterDiameter1Prime);
var innerDiaPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyInnerDiameter2Prime);
var heightPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1Prime);
// Radii
var outerFilletR = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyUnspecifiedFilletRadiusMax) ?? 0;
var innerFilletR = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyInnerRadiusMax) ?? 0;
// Pre-calculate inner hole parameters
var innerDia = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyInnerDiameter2);
var innerTolPlus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyInnerDiameter2TolPlus);
var innerTolMinus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyInnerDiameter2TolMinus);
double? xInnerLeft = null;
double? xInnerRight = null;
// Full Section: Draw Contour with Fillet for both sides
if (innerDia.HasValue && innerDia.Value > 0 && innerDia.Value < W)
{
double xInnerLeftVal = ctx.Center.X - innerDia.Value / 2.0;
double xInnerRightVal = ctx.Center.X + innerDia.Value / 2.0;
// Draw Left Section Contour (Outer Edge: ox, Inner Edge: xInnerLeftVal)
// Left Side of Left Section is Outer -> outerFilletR
// Right Side of Left Section is Inner -> innerFilletR
DrawSectionWithAsymmetricFillets(ctx, ox, xInnerLeftVal, oy, H, outerFilletR, innerFilletR);
if (innerFilletR > 0)
{
double cxLeft = xInnerLeftVal - innerFilletR;
double cyLeft = oy + H - innerFilletR;
DrawInnerRadiusLeader(ctx, cxLeft, cyLeft, innerFilletR, true);
}
// Draw Right Section Contour (Inner Edge: xInnerRightVal, Outer Edge: ox + W)
// Left Side of Right Section is Inner -> innerFilletR
// Right Side of Right Section is Outer -> outerFilletR
DrawSectionWithAsymmetricFillets(ctx, xInnerRightVal, ox + W, oy, H, innerFilletR, outerFilletR);
// Draw Connecting Lines (Hole Back View) - Top and Bottom
// Extend into the inner fillet radius
double lineStart = xInnerLeftVal - innerFilletR;
double lineEnd = xInnerRightVal + innerFilletR;
var connectingLineTop = new Line(new Point3d(lineStart, oy + H, 0), new Point3d(lineEnd, oy + H, 0));
connectingLineTop.ColorIndex = 7; // White
ctx.Btr.AppendEntity(connectingLineTop);
ctx.Tr.AddNewlyCreatedDBObject(connectingLineTop, true);
var connectingLineBottom = new Line(new Point3d(lineStart, oy, 0), new Point3d(lineEnd, oy, 0));
connectingLineBottom.ColorIndex = 7; // White
ctx.Btr.AppendEntity(connectingLineBottom);
ctx.Tr.AddNewlyCreatedDBObject(connectingLineBottom, true);
// Adjust Inner Dim to attach to vertical wall (offset by innerFilletR)
FeatureDrivenDrawer.DrawInnerDiameterDimension(ctx, xInnerLeftVal, xInnerRightVal, oy + innerFilletR, innerDia.Value, innerTolPlus, innerTolMinus, innerDiaPrime);
// Store values for later use in dimensions/notes
xInnerRight = xInnerRightVal;
xInnerLeft = xInnerLeftVal;
}
else
{
// Fallback if no inner hole (should not happen for a ring but safe to keep)
// FeatureDrivenDrawer.DrawForgingOuterContour(ctx, ox, oy, W, H);
}
// 1.1 Centerline
// 改为竖直中心线两头超出3mm
var cx = ctx.Center.X;
var vLine = new Line(new Point3d(cx, oy - 3, 0), new Point3d(cx, oy + H + 3, 0));
ctx.Style?.Apply(vLine, DrawingStyleManager.Role.Centerline);
ctx.Btr.AppendEntity(vLine);
ctx.Tr.AddNewlyCreatedDBObject(vLine, true);
// 2. Outer Diameter Dimension
var outerTolPlus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyOuterDiameter1TolPlus);
var outerTolMinus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyOuterDiameter1TolMinus);
// Adjust Y by outerFilletR
FeatureDrivenDrawer.DrawOuterDiameterDimension(ctx, ox, oy + outerFilletR, W, W, outerTolPlus, outerTolMinus, outerDiaPrime);
// 5. Height Dimension
var displayBag = ctx.OriginalBag ?? ctx.Bag;
var displayHeightVal = displayBag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1) ?? H;
var displayHeightStr = displayBag.GetString(FeatureDrivenDrawer.KeyHeight1);
var displayTolPlus = displayBag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1TolPlus);
var displayTolMinus = displayBag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1TolMinus);
var displayTolPlusStr = displayBag.GetString(FeatureDrivenDrawer.KeyHeight1TolPlus);
var displayTolMinusStr = displayBag.GetString(FeatureDrivenDrawer.KeyHeight1TolMinus);
var displayHeightPrime = displayBag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1Prime);
var heightBaseText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(displayHeightVal, displayHeightStr), displayTolPlus, displayTolMinus, displayTolPlusStr, displayTolMinusStr);
var heightDimText = heightBaseText;
if (displayHeightPrime.HasValue && displayHeightPrime.Value > 0)
{
heightDimText = heightBaseText + $"\\X({FeatureDrivenDrawer.FormatDimNumber(displayHeightPrime.Value)})";
}
// Custom Height Dimension Logic to ensure "Closed" look with fillets
// Move X definition points inward by outerFilletR
double dimX = ox + W - outerFilletR;
FeatureDrivenDrawer.AddLinearDim(
ctx,
new Point3d(dimX, oy, 0),
new Point3d(dimX, oy + H, 0),
new Point3d(ox + W + 25, oy + H / 2, 0),
90,
heightDimText);
// 7. Min Wall Thickness
var minWallThickness = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyMinWallThickness);
if (minWallThickness.HasValue && minWallThickness.Value > 0)
{
if (xInnerRight.HasValue)
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyMinWallThickness) ?? minWallThickness.Value;
var dimText = $"{FeatureDrivenDrawer.FormatDimNumber(val)}min";
FeatureDrivenDrawer.AddLinearDim(
ctx,
new Point3d(xInnerRight.Value, oy + innerFilletR, 0),
new Point3d(ox + W, oy + outerFilletR, 0),
new Point3d((xInnerRight.Value + ox + W) / 2, oy + innerFilletR - 25, 0),
0,
dimText);
}
}
// 8. Part Contour (Machined Parameters present)
if (outerDiaPrime.HasValue && outerDiaPrime.Value > 0 && heightPrime.HasValue && heightPrime.Value > 0)
{
FeatureDrivenDrawer.DrawPartContour(ctx, ctx.Center, outerDiaPrime.Value, innerDiaPrime, heightPrime.Value);
}
// 9. Hardness Symbol
var hardnessVal = bag.GetString(FeatureDrivenDrawer.KeyHardness);
if (!string.IsNullOrWhiteSpace(hardnessVal))
{
if (xInnerRight.HasValue)
{
double xStart = (xInnerRight.Value + ox + W) / 2.0;
double yStart = oy;
FeatureDrivenDrawer.DrawHardnessSymbol(ctx, xStart, yStart);
}
else
{
FeatureDrivenDrawer.DrawHardnessSymbol(ctx, ox + W / 2.0, oy);
}
}
// 10. Marking Content
var markingText = bag.GetString(FeatureDrivenDrawer.KeyMarkingContent);
if (!string.IsNullOrWhiteSpace(markingText))
{
if (xInnerRight.HasValue)
{
double xTarget = (xInnerRight.Value + ox + W) / 2.0;
double yTarget = oy + H;
FeatureDrivenDrawer.DrawSpecialHBLeaderToTop(ctx, xTarget, yTarget, markingText);
}
else
{
FeatureDrivenDrawer.DrawSpecialHBLeaderToTop(ctx, ox + W / 2.0, oy + H, markingText);
}
}
}
/// <summary>
/// Draws a section rectangle with potentially different fillet radii for left and right sides.
/// Also handles hatching.
/// rLeft: Radius for Top-Left and Bottom-Left corners.
/// rRight: Radius for Top-Right and Bottom-Right corners.
/// </summary>
private static void DrawSectionWithAsymmetricFillets(FeatureDrivenDrawer.DrawingContext ctx, double xLeft, double xRight, double yBottom, double height, double rLeft, double rRight)
{
var yTop = yBottom + height;
var width = xRight - xLeft;
// Constrain radii
var maxR = Math.Min(width * 0.5, height * 0.5);
var rl = Math.Min(rLeft, maxR);
var rr = Math.Min(rRight, maxR);
if (rl < 0) rl = 0;
if (rr < 0) rr = 0;
// If radii are negligible, draw rectangle
if (rl <= 0.01 && rr <= 0.01)
{
// ... (Logic from FeatureDrivenDrawer but combined)
// Use reuse logic or just implement simply.
// Simple Polyline
var simplePoly = new Polyline();
simplePoly.AddVertexAt(0, new Point2d(xLeft, yBottom), 0, 0, 0);
simplePoly.AddVertexAt(1, new Point2d(xRight, yBottom), 0, 0, 0);
simplePoly.AddVertexAt(2, new Point2d(xRight, yTop), 0, 0, 0);
simplePoly.AddVertexAt(3, new Point2d(xLeft, yTop), 0, 0, 0);
simplePoly.Closed = true;
ctx.Style?.Apply(simplePoly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(simplePoly);
ctx.Tr.AddNewlyCreatedDBObject(simplePoly, true);
// Hatch
CreateHatchForPolyline(ctx, simplePoly);
return;
}
var bulge = Math.Tan(Math.PI / 8.0);
var poly = new Polyline();
// 1. Bottom Line Start (xLeft + rl)
poly.AddVertexAt(0, new Point2d(xLeft + rl, yBottom), 0, 0, 0);
// 2. Bottom Line End / Bottom-Right Arc Start (xRight - rr)
poly.AddVertexAt(1, new Point2d(xRight - rr, yBottom), bulge, 0, 0);
// 3. Right Line Start / Bottom-Right Arc End (xRight, yBottom + rr)
poly.AddVertexAt(2, new Point2d(xRight, yBottom + rr), 0, 0, 0);
// 4. Right Line End / Top-Right Arc Start (xRight, yTop - rr)
poly.AddVertexAt(3, new Point2d(xRight, yTop - rr), bulge, 0, 0);
// 5. Top Line Start / Top-Right Arc End (xRight - rr, yTop)
poly.AddVertexAt(4, new Point2d(xRight - rr, yTop), 0, 0, 0);
// 6. Top Line End / Top-Left Arc Start (xLeft + rl, yTop)
poly.AddVertexAt(5, new Point2d(xLeft + rl, yTop), bulge, 0, 0);
// 7. Left Line Start / Top-Left Arc End (xLeft, yTop - rl)
poly.AddVertexAt(6, new Point2d(xLeft, yTop - rl), 0, 0, 0);
// 8. Left Line End / Bottom-Left Arc Start (xLeft, yBottom + rl)
poly.AddVertexAt(7, new Point2d(xLeft, yBottom + rl), bulge, 0, 0);
poly.Closed = true;
ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
// Hatch
CreateHatchForPolyline(ctx, poly);
}
private static void DrawInnerRadiusLeader(FeatureDrivenDrawer.DrawingContext ctx, double cx, double cy, double r, bool isLeftSection)
{
try
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeyInnerRadiusMax);
if (!val.HasValue || val.Value <= 0) return;
double angleDeg = isLeftSection ? 45 : 135;
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; // 箭头长度 (原为 3.0)
double arrowWidth = 1.5; // 箭头宽度 (原为 1.0)
double baseX = px + arrowLength * Math.Cos(angleRad);
double baseY = py + arrowLength * Math.Sin(angleRad);
double perpAngle = angleRad + Math.PI / 2;
double p1X = baseX + (arrowWidth / 2) * Math.Cos(perpAngle);
double p1Y = baseY + (arrowWidth / 2) * Math.Sin(perpAngle);
double p2X = baseX - (arrowWidth / 2) * Math.Cos(perpAngle);
double p2Y = baseY - (arrowWidth / 2) * Math.Sin(perpAngle);
var arrow = new Solid(new Point3d(px, py, 0), new Point3d(p1X, p1Y, 0), new Point3d(p2X, p2Y, 0));
arrow.ColorIndex = 4;
ctx.Btr.AppendEntity(arrow);
ctx.Tr.AddNewlyCreatedDBObject(arrow, true);
// 文字(与线对齐同角度)
var textStr = $"R\\U+2264{val.Value}";
var text = new DBText();
text.TextString = textStr;
text.Height = 3.5;
text.ColorIndex = 4;
// 倾斜文字角度
double textRotation = angleRad;
if (!isLeftSection)
{
// For the right side (135 degrees), we want the text to read left-to-right
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 CreateHatchForPolyline(FeatureDrivenDrawer.DrawingContext ctx, Polyline boundary)
{
try
{
var hatch = new Hatch();
hatch.SetDatabaseDefaults();
hatch.Normal = new Vector3d(0, 0, 1);
hatch.Elevation = 0.0;
ctx.Btr.AppendEntity(hatch);
ctx.Tr.AddNewlyCreatedDBObject(hatch, true);
hatch.SetHatchPattern(HatchPatternType.PreDefined, "ANSI31");
hatch.PatternScale = 10;
hatch.PatternAngle = 0;
hatch.Associative = false;
ctx.Style?.Apply(hatch, DrawingStyleManager.Role.Hatch);
var ids = new ObjectIdCollection();
ids.Add(boundary.ObjectId);
hatch.AppendLoop(HatchLoopTypes.External, ids);
hatch.EvaluateHatch(true);
}
catch
{
// ignore hatch errors
}
}
}
}