458 lines
19 KiB
C#
458 lines
19 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Autodesk.AutoCAD.DatabaseServices;
|
|
using Autodesk.AutoCAD.Geometry;
|
|
using CadParamPluging.Common;
|
|
|
|
namespace CadParamPluging.Cad
|
|
{
|
|
public static class DiskRawFreeForgeDrawer
|
|
{
|
|
public static void Draw(CadContext ctx, ParamBag bag, Point3d center, double scaleFactor = 1.0)
|
|
{
|
|
if (ctx == null) throw new ArgumentNullException(nameof(ctx));
|
|
if (bag == null) throw new ArgumentNullException(nameof(bag));
|
|
|
|
var effectiveBag = scaleFactor < 1.0 ? ScaleParamBag(bag, scaleFactor) : bag;
|
|
|
|
var db = ctx.Database;
|
|
var tr = ctx.Transaction;
|
|
|
|
var prevDb = HostApplicationServices.WorkingDatabase;
|
|
HostApplicationServices.WorkingDatabase = db;
|
|
BlockTableRecord btr;
|
|
try
|
|
{
|
|
var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
|
|
btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
|
|
}
|
|
finally
|
|
{
|
|
HostApplicationServices.WorkingDatabase = prevDb;
|
|
}
|
|
|
|
var context = new FeatureDrivenDrawer.DrawingContext
|
|
{
|
|
Ctx = ctx,
|
|
Bag = effectiveBag,
|
|
OriginalBag = bag,
|
|
Center = center,
|
|
DeliveryStatus = "毛料态",
|
|
StructuralFeature = "饼盘",
|
|
ProcessMethod = "自由锻",
|
|
Btr = btr,
|
|
Style = new DrawingStyleManager(db, tr)
|
|
};
|
|
|
|
DrawDiskFeatures(context);
|
|
}
|
|
|
|
private static void DrawDiskFeatures(FeatureDrivenDrawer.DrawingContext ctx)
|
|
{
|
|
var bag = ctx.Bag;
|
|
|
|
var diameter = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameter);
|
|
var height = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1);
|
|
|
|
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 unspecifiedFillet = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyUnspecifiedFilletRadiusMax);
|
|
double r = unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0 ? unspecifiedFillet.Value : 0;
|
|
|
|
// 安全检查:圆角不能超过宽或高的一半
|
|
double maxR = Math.Min(diameter.Value * 0.5, H * 0.5);
|
|
r = Math.Min(r, maxR);
|
|
|
|
// 绘制饼盘轮廓(俯视图为圆,侧视图为矩形,根据 R 控制圆角弧度)
|
|
var poly = new Polyline();
|
|
if (r > 0.01)
|
|
{
|
|
var bulge = Math.Tan(Math.PI / 8.0);
|
|
double xLeft = ox;
|
|
double xRight = ox + diameter.Value;
|
|
double yBottom = oy;
|
|
double yTop = oy + H;
|
|
|
|
poly.AddVertexAt(0, new Point2d(xLeft + r, yBottom), 0, 0, 0);
|
|
poly.AddVertexAt(1, new Point2d(xRight - r, yBottom), bulge, 0, 0);
|
|
poly.AddVertexAt(2, new Point2d(xRight, yBottom + r), 0, 0, 0);
|
|
poly.AddVertexAt(3, new Point2d(xRight, yTop - r), bulge, 0, 0);
|
|
poly.AddVertexAt(4, new Point2d(xRight - r, yTop), 0, 0, 0);
|
|
poly.AddVertexAt(5, new Point2d(xLeft + r, yTop), bulge, 0, 0);
|
|
poly.AddVertexAt(6, new Point2d(xLeft, yTop - r), 0, 0, 0);
|
|
poly.AddVertexAt(7, new Point2d(xLeft, yBottom + r), bulge, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
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);
|
|
|
|
// 绘制中心线 (点划线)
|
|
const double extendLine = 5.0;
|
|
const double frameMargin = 5.0;
|
|
var y0 = oy - extendLine;
|
|
var y1 = oy + H + extendLine;
|
|
|
|
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 { }
|
|
|
|
if (y1 <= y0)
|
|
{
|
|
y0 = oy;
|
|
y1 = oy + H;
|
|
}
|
|
|
|
var centerLine = new Line(new Point3d(ctx.Center.X, y0, 0), new Point3d(ctx.Center.X, y1, 0));
|
|
ctx.Style?.Apply(centerLine, DrawingStyleManager.Role.Centerline);
|
|
ctx.Btr.AppendEntity(centerLine);
|
|
ctx.Tr.AddNewlyCreatedDBObject(centerLine, true);
|
|
|
|
var diaPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterPrime);
|
|
var heightPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1Prime);
|
|
|
|
// 直径标注
|
|
var diaTolPlus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterTolPlus);
|
|
var diaTolMinus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterTolMinus);
|
|
var diameterStr = bag.GetString(FeatureDrivenDrawer.KeyDiameter);
|
|
var diaTolPlusStr = bag.GetString(FeatureDrivenDrawer.KeyDiameterTolPlus);
|
|
var diaTolMinusStr = bag.GetString(FeatureDrivenDrawer.KeyDiameterTolMinus);
|
|
|
|
var diaDimText = BuildDimensionText($"%%c{FormatDimNumber(diameter.Value, diameterStr)}", diaTolPlus, diaTolMinus, diaTolPlusStr, diaTolMinusStr);
|
|
if (diaPrime.HasValue && diaPrime.Value > 0)
|
|
{
|
|
diaDimText += $"\\X(%%c{FormatDimNumber(diaPrime.Value)})";
|
|
}
|
|
|
|
// 为避免标注界线悬空,根据 r 的存在小幅调整起点
|
|
AddLinearDim(ctx, new Point3d(ox, oy + r, 0), new Point3d(ox + diameter.Value, oy + r, 0),
|
|
new Point3d(ctx.Center.X, oy - 20, 0), 0, diaDimText);
|
|
|
|
// 高度标注
|
|
var htTolPlus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1TolPlus);
|
|
var htTolMinus = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1TolMinus);
|
|
var heightStr = bag.GetString(FeatureDrivenDrawer.KeyHeight1);
|
|
var htTolPlusStr = bag.GetString(FeatureDrivenDrawer.KeyHeight1TolPlus);
|
|
var htTolMinusStr = bag.GetString(FeatureDrivenDrawer.KeyHeight1TolMinus);
|
|
|
|
var htDimText = BuildDimensionText(FormatDimNumber(H, heightStr), htTolPlus, htTolMinus, htTolPlusStr, htTolMinusStr);
|
|
if (heightPrime.HasValue && heightPrime.Value > 0)
|
|
{
|
|
htDimText += $"\\X({FormatDimNumber(heightPrime.Value)})";
|
|
}
|
|
|
|
AddLinearDim(ctx, new Point3d(ox + diameter.Value - r, oy, 0), new Point3d(ox + diameter.Value - r, oy + H, 0),
|
|
new Point3d(ox + diameter.Value + 20, ctx.Center.Y, 0), 90, htDimText);
|
|
|
|
// 添加未注圆角文字标注
|
|
if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
|
|
{
|
|
DrawUnspecifiedFilletNote(ctx, ox, oy + H, R, diameter.Value, unspecifiedFillet.Value);
|
|
}
|
|
|
|
// 零件轮廓(如果有)
|
|
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(FeatureDrivenDrawer.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);
|
|
}
|
|
|
|
private static void DrawUnspecifiedFilletNote(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double R, double height, double filletR)
|
|
{
|
|
try
|
|
{
|
|
// Try to get original value to avoid scaling
|
|
var val = filletR;
|
|
if (ctx.OriginalBag != null)
|
|
{
|
|
double? original = ctx.OriginalBag.GetDoubleOrNull(FeatureDrivenDrawer.KeyUnspecifiedFilletRadiusMax);
|
|
if (original.HasValue) val = original.Value;
|
|
}
|
|
|
|
var text = new DBText();
|
|
text.TextString = $"未注圆角半径R≤{val}";
|
|
// Position logic copied from FeatureDrivenDrawer (may need adjustment if generic logic was weird)
|
|
// In FeatureDrivenDrawer: text.Position = new Point3d(ox + height + 10, oy + R + 15, 0);
|
|
// ox, oy passed in were Top Left or similar?
|
|
// In DrawDiskFeatures: DrawUnspecifiedFilletNote(ctx, ox, oy + H, R, diameter.Value, unspecifiedFillet.Value);
|
|
// ox is Left X. oy+H is Top Y.
|
|
// R passed is Radius (Diameter/2). height passed is Diameter (Circle diameter?).
|
|
// Let's verify arguments in DrawDiskFeatures call:
|
|
// DrawUnspecifiedFilletNote(ctx, ox, oy + H, R, diameter.Value, unspecifiedFillet.Value);
|
|
// Arg3 (R) = R (Radius). Arg4 (height) = diameter.
|
|
// Inside DrawUnspecifiedFilletNote:
|
|
// Position = new Point3d(ox + height + 10, oy + R + 15, 0);
|
|
// ox + diameter + 10 -> Right of the drawing.
|
|
// oy + R + 15 -> Top Y + Radius + 15 -> Above the drawing?
|
|
|
|
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
|
|
{
|
|
// ignore
|
|
}
|
|
}
|
|
|
|
private static ParamBag ScaleParamBag(ParamBag original, double scaleFactor)
|
|
{
|
|
if (original == null || Math.Abs(scaleFactor - 1.0) < 0.000001) return original;
|
|
var newBag = new ParamBag();
|
|
foreach(var k in original.GetKeys())
|
|
{
|
|
var v = original.GetString(k);
|
|
if (k.Contains("Diameter") || k.Contains("Length") || k.Contains("Radius") || k.Contains("Prime") || k.Contains("Height") || k.Contains("Thickness") || k.Contains("Size"))
|
|
{
|
|
if (double.TryParse(v, out var d))
|
|
{
|
|
newBag.Set(k, (d * scaleFactor).ToString("0.###"));
|
|
}
|
|
else { newBag.Set(k, v); }
|
|
}
|
|
else { newBag.Set(k, v); }
|
|
}
|
|
return newBag;
|
|
}
|
|
|
|
// --- Helper Methods Copied for Isolation ---
|
|
|
|
private static void AddLinearDim(FeatureDrivenDrawer.DrawingContext ctx, Point3d pt1, Point3d pt2, Point3d dimLinePt,
|
|
double rotationDeg, string textOverride, Action<Dimension, FeatureDrivenDrawer.DrawingContext> customizer = null)
|
|
{
|
|
try
|
|
{
|
|
var prevDb = HostApplicationServices.WorkingDatabase;
|
|
HostApplicationServices.WorkingDatabase = ctx.Db;
|
|
try
|
|
{
|
|
double rotRad = rotationDeg * Math.PI / 180.0;
|
|
var dim = new RotatedDimension(rotRad, pt1, pt2, dimLinePt, textOverride, ctx.Db.Dimstyle);
|
|
try { dim.SetDatabaseDefaults(); } catch { }
|
|
dim.ColorIndex = 3;
|
|
|
|
if (!string.IsNullOrEmpty(textOverride))
|
|
{
|
|
dim.DimensionText = textOverride;
|
|
}
|
|
|
|
try { dim.Normal = Vector3d.ZAxis; } catch { }
|
|
TryApplyDimSizeOverrides(dim);
|
|
TryApplyDimLayoutOverrides(dim);
|
|
|
|
customizer?.Invoke(dim, ctx);
|
|
|
|
ctx.Style?.Apply(dim, DrawingStyleManager.Role.Dimension);
|
|
dim.ColorIndex = 3;
|
|
|
|
ctx.Btr.AppendEntity(dim);
|
|
ctx.Tr.AddNewlyCreatedDBObject(dim, true);
|
|
try { dim.RecomputeDimensionBlock(true); } catch { }
|
|
}
|
|
finally
|
|
{
|
|
HostApplicationServices.WorkingDatabase = prevDb;
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private static void TryApplyDimSizeOverrides(Dimension dim)
|
|
{
|
|
if (dim == null) return;
|
|
TrySetDimProp(dim, "Dimtxt", 3.5);
|
|
TrySetDimProp(dim, "Dimasz", 2.5);
|
|
TrySetDimProp(dim, "Dimgap", 1.0);
|
|
TrySetDimProp(dim, "Dimexe", 1.0);
|
|
TrySetDimProp(dim, "Dimexo", 0.0);
|
|
TrySetDimProp(dim, "Dimtofl", true);
|
|
TrySetDimProp(dim, "Dimatfit", 3);
|
|
TrySetDimProp(dim, "Dimtad", 1);
|
|
TrySetDimProp(dim, "Dimclrd", 3);
|
|
TrySetDimProp(dim, "Dimclre", 3);
|
|
TrySetDimProp(dim, "Dimclrt", 3);
|
|
}
|
|
|
|
private static void TryApplyDimLayoutOverrides(Dimension dim)
|
|
{
|
|
if (dim == null) return;
|
|
TrySetDimProp(dim, "Dimtih", false);
|
|
TrySetDimProp(dim, "Dimtoh", false);
|
|
TrySetDimProp(dim, "Dimse1", false);
|
|
TrySetDimProp(dim, "Dimse2", false);
|
|
}
|
|
|
|
private static void TrySetDimProp(object obj, string propName, double value)
|
|
{
|
|
if (obj == null) return;
|
|
try
|
|
{
|
|
var prop = obj.GetType().GetProperty(propName);
|
|
if (prop != null && prop.CanWrite && prop.PropertyType == typeof(double))
|
|
prop.SetValue(obj, value, null);
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private static void TrySetDimProp(object obj, string propName, bool value)
|
|
{
|
|
if (obj == null) return;
|
|
try
|
|
{
|
|
var prop = obj.GetType().GetProperty(propName);
|
|
if (prop != null && prop.CanWrite && prop.PropertyType == typeof(bool))
|
|
prop.SetValue(obj, value, null);
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private static void TrySetDimProp(object obj, string propName, int value)
|
|
{
|
|
if (obj == null) return;
|
|
try
|
|
{
|
|
var prop = obj.GetType().GetProperty(propName);
|
|
if (prop != null && prop.CanWrite && prop.PropertyType == typeof(int))
|
|
prop.SetValue(obj, value, null);
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private static string FormatDimNumber(double value, string rawInput = null)
|
|
{
|
|
try
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(rawInput) && double.TryParse(rawInput, out var d) && Math.Abs(d - value) < 0.000001)
|
|
{
|
|
int decIndex = rawInput.IndexOf('.');
|
|
int decimals = 0;
|
|
if (decIndex >= 0)
|
|
{
|
|
decimals = rawInput.Length - decIndex - 1;
|
|
}
|
|
if (decimals == 0) return value.ToString("0");
|
|
return value.ToString("0." + new string('0', decimals));
|
|
}
|
|
|
|
string str = value.ToString("0.##########");
|
|
int decimalIndex = str.IndexOf('.');
|
|
if (decimalIndex < 0)
|
|
{
|
|
return str;
|
|
}
|
|
|
|
int autoDecimals = str.Length - decimalIndex - 1;
|
|
|
|
if (autoDecimals == 0) return str;
|
|
|
|
string format = "0." + new string('0', autoDecimals);
|
|
return value.ToString(format);
|
|
}
|
|
catch
|
|
{
|
|
return value.ToString();
|
|
}
|
|
}
|
|
|
|
private static string BuildDimensionText(string baseText, double? tolPlus, double? tolMinus, string tolPlusStr = null, string tolMinusStr = null)
|
|
{
|
|
if (!tolPlus.HasValue && !tolMinus.HasValue)
|
|
{
|
|
return baseText;
|
|
}
|
|
|
|
bool isSymmetrical = false;
|
|
if (tolPlus.HasValue && tolMinus.HasValue)
|
|
{
|
|
if (Math.Abs(Math.Abs(tolPlus.Value) - Math.Abs(tolMinus.Value)) < 0.000001)
|
|
{
|
|
isSymmetrical = true;
|
|
}
|
|
}
|
|
|
|
if (isSymmetrical)
|
|
{
|
|
var val = Math.Abs(tolPlus.Value);
|
|
return $"{baseText}%%p{FormatDimNumber(val, tolPlusStr)}";
|
|
}
|
|
|
|
const double tolScale = 0.7;
|
|
var plusStr = string.Empty;
|
|
var minusStr = string.Empty;
|
|
|
|
if (tolPlus.HasValue)
|
|
{
|
|
plusStr = tolPlus.Value >= 0
|
|
? $"+{FormatDimNumber(tolPlus.Value, tolPlusStr)}"
|
|
: $"{FormatDimNumber(tolPlus.Value, tolPlusStr)}";
|
|
}
|
|
|
|
if (tolMinus.HasValue)
|
|
{
|
|
double vm = tolMinus.Value;
|
|
string formattedVal = FormatDimNumber(Math.Abs(vm), tolMinusStr);
|
|
|
|
if (Math.Abs(vm) < 0.000001)
|
|
{
|
|
minusStr = formattedVal;
|
|
}
|
|
else
|
|
{
|
|
minusStr = $"-{formattedVal}";
|
|
}
|
|
}
|
|
|
|
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}}}";
|
|
}
|
|
}
|
|
}
|