更改毛料态-轧制-环形的生成逻辑,圆角正确

This commit is contained in:
sladro 2026-01-21 11:42:38 +08:00
parent 707ad46315
commit d2c4be4226

View File

@ -544,12 +544,14 @@ namespace CadParamPluging.Cad
// === 特征1: 锻件外轮廓 ===
var unspecifiedFillet = bag.GetDoubleOrNull(KeyUnspecifiedFilletRadiusMax);
if (applyUnspecifiedFillet && unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
{
DrawForgingOuterContourHalf(ctx, ox, oy, visualOuterR, H, unspecifiedFillet);
}
else
// 判断是否有圆角
bool hasUnspecifiedFillet = applyUnspecifiedFillet && unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0;
if (!hasUnspecifiedFillet)
{
// 只有在非圆角模式下才绘制单独的外轮廓
// 在圆角模式下,整个实体轮廓由后面的 DrawRingSectionContourWithFillet 统一绘制
DrawForgingOuterContourHalf(ctx, ox, oy, visualOuterR, H, null);
}
@ -562,7 +564,7 @@ namespace CadParamPluging.Cad
// 传入 visualOuterR 用于画线,传入 outerDia 用于文本
DrawOuterDiameterDimensionHalf(ctx, ox, oy, visualOuterR, H, outerDia, outerTolPlus, outerTolMinus, outerDiaPrime);
// === 特征3: 内孔/内径 ===
// === 特征3: 内孔/内径 ===
double? xInnerRight = null;
if (innerDia.HasValue && innerDia.Value > 0 && innerDia.Value < outerDia)
{
@ -572,39 +574,62 @@ namespace CadParamPluging.Cad
var innerTolPlus = bag.GetDoubleOrNull(KeyInnerDiameter2TolPlus);
var innerTolMinus = bag.GetDoubleOrNull(KeyInnerDiameter2TolMinus);
DrawInnerHoleHalf(ctx, ox, xInnerRight.Value, oy, H);
// 传入 raw innerDia for text
DrawInnerDiameterDimensionHalf(ctx, ox, xInnerRight.Value, oy, H, innerDia.Value, innerTolPlus, innerTolMinus, innerDiaPrime);
// 判断是否有圆角 (hasUnspecifiedFillet already declared above)
if (hasUnspecifiedFillet)
{
// 计算圆角半径逻辑,与 DrawRingSectionContourWithFillet 保持一致
var sectionWidth = visualOuterR * 2.0; // Wait, section width is visualOuterR - visualInnerRight? No.
// Calculate visual width for section
var sWidth = (ox + visualOuterR) - (ox + visualInnerR);
var maxR = Math.Min(sWidth * 0.5, H * 0.5);
var rawR = unspecifiedFillet.Value;
var r = Math.Min(rawR, maxR);
double dimOffset = (r > 0.01) ? r : 0.0;
// === 特征4: 内径圆角 ===
var innerRadiusMax = bag.GetDoubleOrNull(KeyInnerRadiusMax);
if (innerRadiusMax.HasValue && innerRadiusMax.Value > 0 && ctx.IsCenterPunched)
{
DrawInnerFilletsHalf(ctx, xInnerRight.Value, oy, H, innerRadiusMax.Value);
}
else if (applyUnspecifiedFillet && unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
{
DrawInnerFilletsHalfInward(ctx, xInnerRight.Value, oy, H, unspecifiedFillet.Value);
}
// 新逻辑:如果启用了圆角,直接绘制一个闭合的圆角矩形作为实体轮廓
// 替代原来分散的 外轮廓 + 内孔竖线 + 圆角 的画法,解决直角残留和不平滑问题
DrawRingSectionContourWithFillet(ctx, xInnerRight.Value, ox + visualOuterR, oy, H, unspecifiedFillet.Value);
// 补充:绘制连接中轴线到实体内边缘的上下两条横线(内孔顶底面)
DrawHoleHorizontalLines(ctx, ox, xInnerRight.Value, oy, H, unspecifiedFillet.Value);
// === 特征4.1: 剖面线 ===
if (applyUnspecifiedFillet && unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
{
// 标注依然需要
// 用户反馈:下边的标注线在竖直方向上不要闭合(保持在底边水平),不要高于白色底部边框
// 所以这里恢复 offset 为 0
DrawInnerDiameterDimensionHalf(ctx, ox, xInnerRight.Value, oy, H, innerDia.Value, innerTolPlus, innerTolMinus, innerDiaPrime, 0.0);
// 剖面填充
DrawRingSectionHatchWithFillet(ctx, xInnerRight.Value, ox + visualOuterR, oy, H, unspecifiedFillet.Value);
}
else
{
// 原有逻辑:直角模式
DrawInnerHoleHalf(ctx, ox, xInnerRight.Value, oy, H);
DrawInnerDiameterDimensionHalf(ctx, ox, xInnerRight.Value, oy, H, innerDia.Value, innerTolPlus, innerTolMinus, innerDiaPrime);
DrawRingSectionHatch(ctx, xInnerRight.Value, ox + visualOuterR, oy, H);
// 剖面左侧竖线
DrawSectionInnerBoundaryBold(ctx, xInnerRight.Value, oy, H);
}
// 剖面左侧竖线
DrawSectionInnerBoundaryBold(ctx, xInnerRight.Value, oy, H);
}
// === 特征5: 高度标注 ===
var heightTolPlus = bag.GetDoubleOrNull(KeyHeight1TolPlus);
var heightTolMinus = bag.GetDoubleOrNull(KeyHeight1TolMinus);
DrawHeightDimensionHalf(ctx, ox, oy, visualOuterR, H, heightTolPlus, heightTolMinus, heightPrime);
// 计算高度标注的内缩进量(针对圆角闭合)
// 使标注界线的起点X坐标向内缩进 r从而搭在圆角的切点上而Y坐标保持不变与锻件顶底对齐
double heightDimIndentX = 0.0;
if (hasUnspecifiedFillet)
{
var sWidth = (ox + visualOuterR) - (ox + visualInnerR);
var maxR = Math.Min(sWidth * 0.5, H * 0.5);
var r = Math.Min(unspecifiedFillet.Value, maxR);
if (r > 0.01) heightDimIndentX = r;
}
DrawHeightDimensionHalf(ctx, ox, oy, visualOuterR, H, heightTolPlus, heightTolMinus, heightPrime, heightDimIndentX);
// === 特征6: 未注圆角 ===
if (unspecifiedFillet.HasValue && unspecifiedFillet.Value > 0)
@ -616,7 +641,8 @@ namespace CadParamPluging.Cad
var minWallThickness = bag.GetDoubleOrNull(KeyMinWallThickness);
if (minWallThickness.HasValue && minWallThickness.Value > 0 && xInnerRight.HasValue)
{
DrawMinWallThicknessNote(ctx, xInnerRight.Value, ox + visualOuterR, oy, minWallThickness.Value);
// 用户反馈下边标注线不要偏移恢复为0
DrawMinWallThicknessNote(ctx, xInnerRight.Value, ox + visualOuterR, oy, minWallThickness.Value, 0.0);
}
// === 特征8: 零件轮廓(车加工态,右半边) ===
@ -642,6 +668,8 @@ namespace CadParamPluging.Cad
// 高度方向没有示意图扭曲,直接使用物理高度
var scaledHeightPrime = heightPrime.Value;
// 恢复绘制零件轮廓(无论是否有圆角)
// 用户确认剖面中需要显示零件生成部分,之前的屏蔽是误判
DrawPartContourHalf(ctx, ox, oy, H, scaledOuterDiaPrime, scaledInnerDiaPrime, scaledHeightPrime);
}
@ -658,6 +686,112 @@ namespace CadParamPluging.Cad
}
/// <summary>
/// 轧制:绘制带圆角的实体闭合轮廓(圆角多段线)
/// 替代原来分散的外轮廓线和内孔边界线
/// </summary>
private static void DrawRingSectionContourWithFillet(DrawingContext ctx, double xLeft, double xRight, double yBottom, double height, double filletR)
{
var yTop = yBottom + height;
var width = xRight - xLeft;
// 限制圆角半径不超过尺寸的一半
var maxR = Math.Min(width * 0.5, height * 0.5);
var r = Math.Min(filletR, maxR);
if (r <= 0.01)
{
// 如果圆角太小,退化为矩形边框
var poly = new Polyline();
poly.AddVertexAt(0, new Point2d(xLeft, yBottom), 0, 0, 0);
poly.AddVertexAt(1, new Point2d(xRight, yBottom), 0, 0, 0);
poly.AddVertexAt(2, new Point2d(xRight, yTop), 0, 0, 0);
poly.AddVertexAt(3, new Point2d(xLeft, yTop), 0, 0, 0);
poly.Closed = true;
ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(poly);
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
return;
}
var bulge = Math.Tan(Math.PI / 8.0); // 90度圆弧的凸度
// 逆时针绘制圆角矩形
// 顺序:左下圆弧 -> 右下圆弧 -> 右上圆弧 -> 左上圆弧
// 下方边:从左下到右下
// 起点 (xLeft + r, yBottom) -> 直线 -> (xRight - r, yBottom) -> 圆弧 -> (xRight, yBottom + r)
var polyFillet = new Polyline();
// 1. 下边直线段起点
polyFillet.AddVertexAt(0, new Point2d(xLeft + r, yBottom), 0, 0, 0);
// 2. 右下角圆弧起点
polyFillet.AddVertexAt(1, new Point2d(xRight - r, yBottom), bulge, 0, 0);
// 3. 右边直线段起点 (圆弧终点)
polyFillet.AddVertexAt(2, new Point2d(xRight, yBottom + r), 0, 0, 0);
// 4. 右上角圆弧起点
polyFillet.AddVertexAt(3, new Point2d(xRight, yTop - r), bulge, 0, 0);
// 5. 上边直线段起点 (圆弧终点)
polyFillet.AddVertexAt(4, new Point2d(xRight - r, yTop), 0, 0, 0);
// 6. 左上角圆弧起点
polyFillet.AddVertexAt(5, new Point2d(xLeft + r, yTop), bulge, 0, 0);
// 7. 左边直线段起点 (圆弧终点)
polyFillet.AddVertexAt(6, new Point2d(xLeft, yTop - r), 0, 0, 0);
// 8. 左下角圆弧起点
polyFillet.AddVertexAt(7, new Point2d(xLeft, yBottom + r), bulge, 0, 0);
// 闭合回到起点
polyFillet.Closed = true;
ctx.Style?.Apply(polyFillet, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(polyFillet);
ctx.Tr.AddNewlyCreatedDBObject(polyFillet, true);
}
private static void DrawHoleHorizontalLines(DrawingContext ctx, double xAxis, double xSectionLeft, double yBottom, double height, double filletR)
{
var yTop = yBottom + height;
// 计算延伸量为了与圆角闭合横线需要延伸到圆角圆心的X坐标处
// 或者简单点,让它延伸到 (xSectionLeft + r),即圆角的结束位置
var width = 200.0; // dummy big enough width for calculation
var maxR = Math.Min(width * 0.5, height * 0.5);
var r = Math.Min(filletR, maxR);
// 如果圆角很小,就不用延伸太远,但考虑到视觉闭合,应该延伸到 xSectionLeft 就够了?
// 不, 截图显示圆角导致内孔竖直边向内缩进,所以横线必须向右延伸穿过圆角区域,连接到实体。
// 圆角起点的X坐标是 xSectionLeft圆角终点的X坐标是 xSectionLeft + r
// 实际上,横线应该连接到圆角圆弧的切点?不,横线是顶面/底面,所以应该连接到 (xSectionLeft + r)
double xTarget = xSectionLeft;
if (r > 0.01)
{
xTarget = xSectionLeft + r;
}
// Bottom line
var line1 = new Line(new Point3d(xAxis, yBottom, 0), new Point3d(xTarget, yBottom, 0));
ctx.Style?.Apply(line1, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(line1);
ctx.Tr.AddNewlyCreatedDBObject(line1, true);
// Top line
var line2 = new Line(new Point3d(xAxis, yTop, 0), new Point3d(xTarget, yTop, 0));
ctx.Style?.Apply(line2, DrawingStyleManager.Role.OutlineBold);
ctx.Btr.AppendEntity(line2);
ctx.Tr.AddNewlyCreatedDBObject(line2, true);
}
/// <summary>
/// 自由锻工艺 - 画全图
/// </summary>
@ -937,7 +1071,7 @@ namespace CadParamPluging.Cad
/// 轧制:内径标注(从对称轴到右边内孔,放到下方并与最小壁厚标注共线)
/// </summary>
private static void DrawInnerDiameterDimensionHalf(DrawingContext ctx, double oxAxis, double xInnerRight, double yBottom, double height,
double diameter, double? tolPlus, double? tolMinus, double? diameterPrime)
double diameter, double? tolPlus, double? tolMinus, double? diameterPrime, double offsetY = 0)
{
// Use OriginalBag for text display
var diameterVal = ctx.OriginalBag?.GetDoubleOrNull(KeyInnerDiameter2) ?? diameter;
@ -965,8 +1099,8 @@ namespace CadParamPluging.Cad
var dimLineY = yBottom - 10;
AddLinearDim(
ctx,
new Point3d(oxAxis, yBottom, 0),
new Point3d(xInnerRight, yBottom, 0),
new Point3d(oxAxis, yBottom, 0), // 对称轴点不需要偏移,因为它是中心线
new Point3d(xInnerRight, yBottom + offsetY, 0), // 内孔点需要偏移以避开圆角空隙
new Point3d(oxAxis + innerRadius / 2, dimLineY, 0),
0,
dimText,
@ -998,9 +1132,10 @@ namespace CadParamPluging.Cad
/// <summary>
/// 轧制:高度标注(在右侧)
/// indentX: 界线起点向内横向缩进量(配合圆角使用,使界线起于圆角切点)
/// </summary>
private static void DrawHeightDimensionHalf(DrawingContext ctx, double ox, double oy, double radius,
double height, double? tolPlus, double? tolMinus, double? heightPrime)
double height, double? tolPlus, double? tolMinus, double? heightPrime, double indentX = 0)
{
// Use OriginalBag for text display
var heightVal = ctx.OriginalBag?.GetDoubleOrNull(KeyHeight1) ?? height;
@ -1022,10 +1157,17 @@ namespace CadParamPluging.Cad
? baseText + $"\\X({FormatDimNumber(heightPrimeVal.Value)})"
: baseText;
// 界线起点:
// 下端: (ox + radius - indentX, oy)
// 上端: (ox + radius - indentX, oy + height)
// 这样保持了高度(Y)不变和白色横线对齐但X方向向内缩进搭在圆角顶点上
var xLine = ox + radius - indentX;
AddLinearDim(
ctx,
new Point3d(ox + radius, oy, 0),
new Point3d(ox + radius, oy + height, 0),
new Point3d(xLine, oy, 0),
new Point3d(xLine, oy + height, 0),
new Point3d(ox + radius + 20, oy + height / 2, 0),
90,
dimText);
@ -1250,14 +1392,14 @@ namespace CadParamPluging.Cad
}
}
private static void DrawMinWallThicknessNote(DrawingContext ctx, double xInnerRight, double xOuterRight, double yBottom, double thickness)
private static void DrawMinWallThicknessNote(DrawingContext ctx, double xInnerRight, double xOuterRight, double yBottom, double thickness, double offsetY = 0)
{
var val = ctx.OriginalBag?.GetDoubleOrNull(KeyMinWallThickness) ?? thickness;
var dimText = $"{FormatDimNumber(val)}min";
AddLinearDim(
ctx,
new Point3d(xInnerRight, yBottom, 0),
new Point3d(xOuterRight, yBottom, 0),
new Point3d(xInnerRight, yBottom + offsetY, 0),
new Point3d(xOuterRight, yBottom + offsetY, 0),
new Point3d((xInnerRight + xOuterRight) / 2, yBottom - 10, 0),
0,
dimText);