401 lines
17 KiB
C#
401 lines
17 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 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(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);
|
||
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(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);
|
||
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(FeatureDrivenDrawer.KeyUnspecifiedFilletRadiusMax);
|
||
if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
|
||
{
|
||
DrawUnspecifiedFilletNote(ctx, ox, oy + H, R, diameter.Value, unspecifiedFillet.Value);
|
||
}
|
||
|
||
// 零件尺寸(如果有)
|
||
var diaPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyDiameterPrime);
|
||
var heightPrime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeyHeight1Prime);
|
||
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);
|
||
|
||
// 零件直径标注
|
||
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}");
|
||
}
|
||
|
||
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}}}";
|
||
}
|
||
}
|
||
}
|