CadParamPluging/Cad/ShaftRawFreeForgeSquareShaftDrawer.cs

511 lines
23 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
{
public static class ShaftRawFreeForgeSquareShaftDrawer
{
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 = "轴杆",
SpecialCondition = "方轴",
ProcessMethod = "自由锻",
Btr = btr,
Style = new DrawingStyleManager(db, tr)
};
DrawCore(context);
}
private static void DrawCore(FeatureDrivenDrawer.DrawingContext ctx)
{
var bag = ctx.Bag;
var size1 = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1);
var size2 = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2);
var size3 = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3);
var originalSize1 = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1);
if (!size1.HasValue || size1.Value <= 0 || !size2.HasValue || size2.Value <= 0)
{
return;
}
double S1 = size1.Value;
double S2 = size2.Value;
double S3 = size3.HasValue && size3.Value > 0 ? size3.Value : 0;
double originalS1 = originalSize1.HasValue ? originalSize1.Value : S1;
double ox = ctx.Center.X - S1 / 2.0;
double oy = ctx.Center.Y - S2 / 2.0;
var filletRParam = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftFilletRadiusMax);
double filletR = filletRParam.HasValue && filletRParam.Value > 0 ? filletRParam.Value : 0;
double maxR = Math.Min(S1 / 2.0, S2 / 2.0);
if (filletR > maxR) filletR = maxR;
// 判断是否需要断线
bool needBreakLines = originalS1 > 150;
const double lineSpacing = 3.5;
// 1. Draw Main View - 如果需要断线,则绘制带缺口的轮廓
double xBreak = ox + S1 / 4.0;
// 1. Draw Main View - 如果需要断线,则绘制带缺口的轮廓
if (needBreakLines)
{
DrawRectWithBreak(ctx, ox, oy, S1, S2, filletR, xBreak, lineSpacing);
}
else
{
DrawRectWithFillets(ctx, ox, oy, S1, S2, filletR, DrawingStyleManager.Role.OutlineBold);
}
// 2. 绘制左右两端的弧线(向外凸出)
// 弧高设为 S2/5尺寸2的1/5
double arcHeight = S2 / 5.0;
DrawEndArcs(ctx, ox, oy, S1, S2, arcHeight);
// 3. 绘制中心线 (横向,在中间位置) - 已移除
// DrawHorizontalCenterLine(ctx, ctx.Center.Y, ox, ox + S1, needBreakLines, xBreak, lineSpacing);
// 4. Draw Break Lines if needed
if (needBreakLines)
{
DrawBreakLines(ctx, ox, oy, S1, S2);
}
// 3. Draw Section if S3 > 0
if (S3 > 0)
{
double sectionW = S3;
double sectionH = S2;
double sectionOx = ox + S1 * 2.0 / 3.0 - sectionW / 2.0; // 剖面位于右边1/3处
double sectionOy = oy;
double maxRSec = Math.Min(sectionW / 2.0, sectionH / 2.0);
double filletRSec = (filletR > maxRSec) ? maxRSec : filletR;
var sectionPoly = CreateRectPoly(sectionOx, sectionOy, sectionW, sectionH, filletRSec);
ctx.Style?.Apply(sectionPoly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(sectionPoly);
ctx.Tr.AddNewlyCreatedDBObject(sectionPoly, true);
CreateHatchForPolyline(ctx, sectionPoly);
}
// 4. Dimensions
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1) ?? S1;
var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize1);
var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1TolPlus);
var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1TolMinus);
var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize1TolPlus);
var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize1TolMinus);
var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr);
var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1Prime);
if (valPrime.HasValue && valPrime.Value > 0)
{
dimText += @"\X(" + FeatureDrivenDrawer.FormatDimNumber(valPrime.Value) + ")";
}
double dimY = oy - 25;
double dimOriginY = oy + filletR;
FeatureDrivenDrawer.AddLinearDim(ctx, new Point3d(ox, dimOriginY, 0), new Point3d(ox + S1, dimOriginY, 0), new Point3d(ctx.Center.X, dimY, 0), 0, dimText);
}
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2) ?? S2;
var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize2);
var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2TolPlus);
var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2TolMinus);
var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize2TolPlus);
var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize2TolMinus);
var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr);
var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2Prime);
if (valPrime.HasValue && valPrime.Value > 0)
{
dimText += @"\X(" + FeatureDrivenDrawer.FormatDimNumber(valPrime.Value) + ")";
}
double dimX = ox + S1 + 20;
double dimOriginX = ox + S1 - filletR;
FeatureDrivenDrawer.AddLinearDim(ctx, new Point3d(dimOriginX, oy, 0), new Point3d(dimOriginX, oy + S2, 0), new Point3d(dimX, ctx.Center.Y, 0), 90, dimText);
}
if (S3 > 0)
{
var val = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3) ?? S3;
var str = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize3);
var tolPlus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3TolPlus);
var tolMinus = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3TolMinus);
var tolPlusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize3TolPlus);
var tolMinusStr = ctx.OriginalBag?.GetString(FeatureDrivenDrawer.KeySquareShaftSize3TolMinus);
var dimText = FeatureDrivenDrawer.BuildDimensionText(FeatureDrivenDrawer.FormatDimNumber(val, str), tolPlus, tolMinus, tolPlusStr, tolMinusStr);
var valPrime = ctx.OriginalBag?.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize3Prime);
if (valPrime.HasValue && valPrime.Value > 0)
{
dimText += @"\X(" + FeatureDrivenDrawer.FormatDimNumber(valPrime.Value) + ")";
}
double dimY = oy + S2 + 20;
double sectionOx = ox + S1 * 2.0 / 3.0 - S3 / 2.0; // 标注位置对应剖面
double dimOriginY = oy + S2 - filletR;
FeatureDrivenDrawer.AddLinearDim(ctx, new Point3d(sectionOx, dimOriginY, 0), new Point3d(sectionOx + S3, dimOriginY, 0), new Point3d(ctx.Center.X, dimY, 0), 0, dimText);
}
var hardnessVal = bag.GetString(FeatureDrivenDrawer.KeyHardness);
if (!string.IsNullOrWhiteSpace(hardnessVal))
{
double xStart = (S3 > 0) ? ctx.Center.X : (ox + S1 / 2.0);
double yStart = oy;
FeatureDrivenDrawer.DrawHardnessSymbol(ctx, xStart, yStart);
}
var markingText = bag.GetString(FeatureDrivenDrawer.KeyMarkingContent);
if (!string.IsNullOrWhiteSpace(markingText))
{
double xTarget = (S3 > 0) ? ctx.Center.X : (ox + S1 / 2.0);
double yTarget = oy + S2;
FeatureDrivenDrawer.DrawSpecialHBLeaderToTop(ctx, xTarget, yTarget, markingText);
}
var s1Prime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize1Prime);
var s2Prime = bag.GetDoubleOrNull(FeatureDrivenDrawer.KeySquareShaftSize2Prime);
if (s1Prime.HasValue && s1Prime.Value > 0 && s2Prime.HasValue && s2Prime.Value > 0)
{
double pL = s1Prime.Value;
double pH = s2Prime.Value;
double pOx = ctx.Center.X - pL / 2.0;
double pOy = ctx.Center.Y - pH / 2.0;
if (needBreakLines)
{
// double xBreak = ox + S1 / 4.0; // variable is already declared in outer scope
DrawRectOutlineWithBreak(ctx, pOx, pOy, pL, pH, xBreak, lineSpacing, DrawingStyleManager.Role.PartContour);
}
else
{
DrawRectOutline(ctx, pOx, pOy, pL, pH, DrawingStyleManager.Role.PartContour);
}
}
}
/// <summary>
/// 绘制断线(使用 BreakLine 样式:白色 PHANTOM 双点划线)
/// </summary>
private static void DrawBreakLines(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double width, double height)
{
const double lineSpacing = 3.5;
const double extend = 5.0;
double xBreak = ox + width / 4.0;
double y0 = oy - extend;
double y1 = oy + height + extend;
var line1 = new Line(new Point3d(xBreak, y0, 0), new Point3d(xBreak, y1, 0));
ctx.Style?.Apply(line1, DrawingStyleManager.Role.BreakLine);
ctx.Btr.AppendEntity(line1);
ctx.Tr.AddNewlyCreatedDBObject(line1, true);
var line2 = new Line(new Point3d(xBreak + lineSpacing, y0, 0), new Point3d(xBreak + lineSpacing, y1, 0));
ctx.Style?.Apply(line2, DrawingStyleManager.Role.BreakLine);
ctx.Btr.AppendEntity(line2);
ctx.Tr.AddNewlyCreatedDBObject(line2, true);
}
/// <summary>
/// 绘制带断口的矩形轮廓(在断线位置打断上下横线)
/// </summary>
private static void DrawRectWithBreak(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double w, double h, double r, double xBreak, double breakWidth)
{
// 左边竖线
var leftLine = new Line(new Point3d(x, y, 0), new Point3d(x, y + h, 0));
ctx.Style?.Apply(leftLine, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(leftLine);
ctx.Tr.AddNewlyCreatedDBObject(leftLine, true);
// 右边竖线
var rightLine = new Line(new Point3d(x + w, y, 0), new Point3d(x + w, y + h, 0));
ctx.Style?.Apply(rightLine, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(rightLine);
ctx.Tr.AddNewlyCreatedDBObject(rightLine, true);
// 底边:断开 [xBreak, xBreak + breakWidth]
// 左段
var bottomLeft = new Line(new Point3d(x, y, 0), new Point3d(xBreak, y, 0));
ctx.Style?.Apply(bottomLeft, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(bottomLeft);
ctx.Tr.AddNewlyCreatedDBObject(bottomLeft, true);
// 右段
var bottomRight = new Line(new Point3d(xBreak + breakWidth, y, 0), new Point3d(x + w, y, 0));
ctx.Style?.Apply(bottomRight, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(bottomRight);
ctx.Tr.AddNewlyCreatedDBObject(bottomRight, true);
// 顶边:断开 [xBreak, xBreak + breakWidth]
// 左段
var topLeft = new Line(new Point3d(x, y + h, 0), new Point3d(xBreak, y + h, 0));
ctx.Style?.Apply(topLeft, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(topLeft);
ctx.Tr.AddNewlyCreatedDBObject(topLeft, true);
// 右段
var topRight = new Line(new Point3d(xBreak + breakWidth, y + h, 0), new Point3d(x + w, y + h, 0));
ctx.Style?.Apply(topRight, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(topRight);
ctx.Tr.AddNewlyCreatedDBObject(topRight, true);
}
private static void DrawRectWithFillets(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double w, double h, double r, DrawingStyleManager.Role role = DrawingStyleManager.Role.OutlineBold)
{
var poly = CreateRectPoly(x, y, w, h, r);
ctx.Style?.Apply(poly, role);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
}
private static Polyline CreateRectPoly(double x, double y, double w, double h, double r)
{
var poly = new Polyline();
if (r < 0.01)
{
poly.AddVertexAt(0, new Point2d(x, y), 0, 0, 0);
poly.AddVertexAt(1, new Point2d(x + w, y), 0, 0, 0);
poly.AddVertexAt(2, new Point2d(x + w, y + h), 0, 0, 0);
poly.AddVertexAt(3, new Point2d(x, y + h), 0, 0, 0);
}
else
{
var bulge = Math.Tan(Math.PI / 8.0);
poly.AddVertexAt(0, new Point2d(x + r, y), 0, 0, 0);
poly.AddVertexAt(1, new Point2d(x + w - r, y), bulge, 0, 0);
poly.AddVertexAt(2, new Point2d(x + w, y + r), 0, 0, 0);
poly.AddVertexAt(3, new Point2d(x + w, y + h - r), bulge, 0, 0);
poly.AddVertexAt(4, new Point2d(x + w - r, y + h), 0, 0, 0);
poly.AddVertexAt(5, new Point2d(x + r, y + h), bulge, 0, 0);
poly.AddVertexAt(6, new Point2d(x, y + h - r), 0, 0, 0);
poly.AddVertexAt(7, new Point2d(x, y + r), bulge, 0, 0);
}
poly.Closed = true;
return poly;
}
private static void DrawRectOutline(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double w, double h, DrawingStyleManager.Role role)
{
var poly = new Polyline();
poly.AddVertexAt(0, new Point2d(x, y), 0, 0, 0);
poly.AddVertexAt(1, new Point2d(x + w, y), 0, 0, 0);
poly.AddVertexAt(2, new Point2d(x + w, y + h), 0, 0, 0);
poly.AddVertexAt(3, new Point2d(x, y + h), 0, 0, 0);
poly.Closed = true;
ctx.Style?.Apply(poly, role);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
}
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
{
}
}
private static ParamBag ScaleParamBag(ParamBag original, double scaleFactor)
{
if (original == null) return null;
if (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("SquareShaftSize") || k.Contains("Radius") || k.Contains("Prime"))
{
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;
}
/// <summary>
/// 绘制左右两端的弧线(向外凸出)
/// 使用Polyline的bulge凸度值绘制确保端点精确对齐
/// </summary>
private static void DrawEndArcs(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double W, double H, double arcHeight)
{
try
{
// 弧线端点:
// 左侧弧线:从(ox, oy+H)到(ox, oy)向左凸出arcHeight
// 右侧弧线:从(ox+W, oy)到(ox+W, oy+H)向右凸出arcHeight
double chordLength = H;
double sagitta = arcHeight;
// 计算凸度bulge = 2 * 拱高 / 弦长
double bulge = (2.0 * sagitta) / chordLength;
// 左侧弧线:从(ox, oy+H)到(ox, oy),向左凸出(正凸度)
var leftArc = new Polyline();
leftArc.AddVertexAt(0, new Point2d(ox, oy + H), bulge, 0, 0);
leftArc.AddVertexAt(1, new Point2d(ox, oy), 0, 0, 0);
ctx.Style?.Apply(leftArc, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(leftArc);
ctx.Tr.AddNewlyCreatedDBObject(leftArc, true);
// 右侧弧线:从(ox+W, oy)到(ox+W, oy+H),向右凸出(正凸度)
var rightArc = new Polyline();
rightArc.AddVertexAt(0, new Point2d(ox + W, oy), bulge, 0, 0);
rightArc.AddVertexAt(1, new Point2d(ox + W, oy + H), 0, 0, 0);
ctx.Style?.Apply(rightArc, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(rightArc);
ctx.Tr.AddNewlyCreatedDBObject(rightArc, true);
}
catch
{
// ignore
}
}
/// <summary>
/// 绘制带断口的零件轮廓(在断线位置打断上下横线)
/// 支持自定义 Role (通常为 PartContour)
/// </summary>
private static void DrawRectOutlineWithBreak(FeatureDrivenDrawer.DrawingContext ctx, double x, double y, double w, double h, double xBreak, double breakWidth, DrawingStyleManager.Role role)
{
// 左边竖线
var leftLine = new Line(new Point3d(x, y, 0), new Point3d(x, y + h, 0));
ctx.Style?.Apply(leftLine, role);
ctx.Btr.AppendEntity(leftLine);
ctx.Tr.AddNewlyCreatedDBObject(leftLine, true);
// 右边竖线
var rightLine = new Line(new Point3d(x + w, y, 0), new Point3d(x + w, y + h, 0));
ctx.Style?.Apply(rightLine, role);
ctx.Btr.AppendEntity(rightLine);
ctx.Tr.AddNewlyCreatedDBObject(rightLine, true);
// 底边:断开 [xBreak, xBreak + breakWidth]
// 左段
if (xBreak > x)
{
var bottomLeft = new Line(new Point3d(x, y, 0), new Point3d(Math.Min(xBreak, x + w), y, 0));
ctx.Style?.Apply(bottomLeft, role);
ctx.Btr.AppendEntity(bottomLeft);
ctx.Tr.AddNewlyCreatedDBObject(bottomLeft, true);
}
// 右段
if (xBreak + breakWidth < x + w)
{
var bottomRight = new Line(new Point3d(Math.Max(xBreak + breakWidth, x), y, 0), new Point3d(x + w, y, 0));
ctx.Style?.Apply(bottomRight, role);
ctx.Btr.AppendEntity(bottomRight);
ctx.Tr.AddNewlyCreatedDBObject(bottomRight, true);
}
// 顶边:断开 [xBreak, xBreak + breakWidth]
// 左段
if (xBreak > x)
{
var topLeft = new Line(new Point3d(x, y + h, 0), new Point3d(Math.Min(xBreak, x + w), y + h, 0));
ctx.Style?.Apply(topLeft, role);
ctx.Btr.AppendEntity(topLeft);
ctx.Tr.AddNewlyCreatedDBObject(topLeft, true);
}
// 右段
if (xBreak + breakWidth < x + w)
{
var topRight = new Line(new Point3d(Math.Max(xBreak + breakWidth, x), y + h, 0), new Point3d(x + w, y + h, 0));
ctx.Style?.Apply(topRight, role);
ctx.Btr.AppendEntity(topRight);
ctx.Tr.AddNewlyCreatedDBObject(topRight, true);
}
}
}
}