feat: 新增 BlockRawFreeForgeRoundHeadDrawer 类,实现自由锻圆头毛坯的参数化绘图功能。
This commit is contained in:
parent
ad9968f622
commit
ad76f1bb32
@ -135,34 +135,40 @@ namespace CadParamPluging.Cad
|
||||
// 使用 sectionFilletR
|
||||
DrawBoxSectionContourWithFillet(ctx, xSectionLeft, xSectionRight, oy, H, sectionFilletR);
|
||||
|
||||
// Calculate effective head fillet R (clamped by side frame width) to ensure Outline matches SideFrame
|
||||
// Calculate effective head fillet R (clamped by side frame width)
|
||||
double sideFrameWidth = xSectionLeft - xInnerLeft;
|
||||
double maxR = Math.Min(sideFrameWidth * 0.5, H * 0.5);
|
||||
double effectiveHeadR = Math.Min(headFilletR, maxR);
|
||||
|
||||
// 绘制左侧框线(连接左端圆弧和中间剖面框)
|
||||
// 左端: xInnerLeft (需处理左上下角的圆角 - 使用 headFilletR)
|
||||
// 右端: xSectionLeft (连接到中间框的直边)
|
||||
// Note: Extend horizontally by sectionFilletR to achieve "Horizontal Closure" with the section fillet
|
||||
DrawBoxSideFrame(ctx, xInnerLeft, xSectionLeft + sectionFilletR, oy, H, headFilletR, isLeft: true);
|
||||
double Rm = (H * H) / (8.0 * arcHeight) + arcHeight / 2.0;
|
||||
double D_tangent = (Rm >= effectiveHeadR) ? Math.Sqrt(Math.Max(0, (Rm - effectiveHeadR) * (Rm - effectiveHeadR) - (H / 2.0 - effectiveHeadR) * (H / 2.0 - effectiveHeadR))) : (Rm - arcHeight);
|
||||
|
||||
double xf_left = effectiveHeadR > 0 ? (xInnerLeft + Rm - arcHeight) - D_tangent : xInnerLeft;
|
||||
double xf_right = effectiveHeadR > 0 ? (xInnerRight - Rm + arcHeight) + D_tangent : xInnerRight;
|
||||
|
||||
// 绘制右侧框线
|
||||
// 左端: xSectionRight (连接到中间框的直边)
|
||||
// 右端: xInnerRight (需处理右上下角的圆角 - 使用 headFilletR)
|
||||
// Note: Extend horizontally inwards by sectionFilletR
|
||||
DrawBoxSideFrame(ctx, xSectionRight - sectionFilletR, xInnerRight, oy, H, headFilletR, isLeft: false);
|
||||
double xc_left = xInnerLeft + Rm - arcHeight;
|
||||
double fx_L_tang = effectiveHeadR > 0 ? xc_left + (Rm / (Rm - effectiveHeadR)) * (xf_left - xc_left) : xInnerLeft;
|
||||
double fy_L_tangBot = effectiveHeadR > 0 ? (oy + H / 2.0) + (Rm / (Rm - effectiveHeadR)) * ((oy + effectiveHeadR) - (oy + H / 2.0)) : oy;
|
||||
|
||||
// 1. 绘制完整锻件外轮廓(方体有圆头 - 白色,大圆弧)
|
||||
// 修正:圆弧弦线需向内缩进 effectiveHeadR (Clamped),以与锻件外侧圆角起点对齐
|
||||
// This ensures the Big Arc starts curving exactly where the Side Frame vertical edge ends.
|
||||
DrawBlockRoundHeadOutline(ctx, ox, oy, visualTotalW, H, arcHeight, effectiveHeadR);
|
||||
double xc_right = xInnerRight - Rm + arcHeight;
|
||||
double fx_R_tang = effectiveHeadR > 0 ? xc_right + (Rm / (Rm - effectiveHeadR)) * (xf_right - xc_right) : xInnerRight;
|
||||
double fy_R_tangBot = effectiveHeadR > 0 ? (oy + H / 2.0) + (Rm / (Rm - effectiveHeadR)) * ((oy + effectiveHeadR) - (oy + H / 2.0)) : oy;
|
||||
|
||||
// 绘制左侧框线(只画横向连接线)
|
||||
DrawBoxSideFrame(ctx, xf_left, xSectionLeft + sectionFilletR, oy, H, 0, isLeft: true);
|
||||
|
||||
// 绘制右侧框线(只画横向连接线)
|
||||
DrawBoxSideFrame(ctx, xSectionRight - sectionFilletR, xf_right, oy, H, 0, isLeft: false);
|
||||
|
||||
// 1. 绘制完整锻件外轮廓(方体有圆头 - 白色,大圆弧及外侧平滑过渡圆角)
|
||||
DrawBlockRoundHeadOutline(ctx, ox, oy, visualTotalW, H, arcHeight, effectiveHeadR, xf_left, xf_right);
|
||||
|
||||
// 绘制圆角的斜向标注(如果存在圆角):4-R<=*
|
||||
if (effectiveHeadR > 0)
|
||||
{
|
||||
// 左上角
|
||||
double yTop = oy + H;
|
||||
double cxLeft = xInnerLeft + effectiveHeadR;
|
||||
double cxLeft = xf_left;
|
||||
double cyLeft = yTop - effectiveHeadR;
|
||||
DrawHeadFilletRadiusLeader(ctx, cxLeft, cyLeft, effectiveHeadR, true);
|
||||
|
||||
@ -228,13 +234,12 @@ namespace CadParamPluging.Cad
|
||||
// 修正:标注需涵盖内框宽度 (矩形部分)
|
||||
|
||||
// 修正:引线起点改为内框边界 (xInnerLeft/Right) 和高度底部上移圆角半径,确保闭合到白色线框
|
||||
// 使用 headFilletR 作为 Offset,因为这是侧边框的倒角
|
||||
double dimOriginY = oy + headFilletR;
|
||||
// 修正:引线起点严格匹配倒角与圆弧相切处的极限点坐标 (fx_L_tang, fy_L_tangBot)
|
||||
AddLinearDim(
|
||||
ctx,
|
||||
new Point3d(xInnerLeft, dimOriginY, 0),
|
||||
new Point3d(xInnerRight, dimOriginY, 0),
|
||||
new Point3d((xInnerLeft + xInnerRight) / 2, oy - 25, 0),
|
||||
new Point3d(fx_L_tang, fy_L_tangBot, 0),
|
||||
new Point3d(fx_R_tang, fy_R_tangBot, 0),
|
||||
new Point3d((fx_L_tang + fx_R_tang) / 2, oy - 25, 0),
|
||||
0,
|
||||
dimText);
|
||||
}
|
||||
@ -327,55 +332,146 @@ namespace CadParamPluging.Cad
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawBlockRoundHeadOutline(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double totalWidth, double height, double arcHeight, double innerFilletR)
|
||||
private static void DrawBlockRoundHeadOutline(FeatureDrivenDrawer.DrawingContext ctx, double ox, double oy, double totalWidth, double height, double arcHeight, double innerFilletR, double xf_left, double xf_right)
|
||||
{
|
||||
try
|
||||
{
|
||||
double H = height;
|
||||
double r = innerFilletR;
|
||||
|
||||
// Calculate geometric bounds
|
||||
double xInnerLeft = ox + arcHeight;
|
||||
double xInnerRight = ox + totalWidth - arcHeight;
|
||||
|
||||
// 修正:为了确保视觉上与圆角完全闭合,稍微向圆角区域延伸一点 (0.8 * r)
|
||||
// 用户的需求是“再高一点和低一点”,这意味着需要一定的重叠量来消除缝隙
|
||||
double overlapFactor = 0.8;
|
||||
double yBottomStraight = oy + r * overlapFactor;
|
||||
double yTopStraight = oy + H - r * overlapFactor;
|
||||
|
||||
double chordLength = yTopStraight - yBottomStraight;
|
||||
if (chordLength < 0.1) return; // Should not happen for reasonable params
|
||||
double w = arcHeight;
|
||||
if (w < 0.1) return;
|
||||
|
||||
double sagitta = arcHeight;
|
||||
|
||||
// Bulge calculation: bulge = 2 * sagitta / chord
|
||||
// For a CCW arc, bulge is positive.
|
||||
double bulge = (2.0 * sagitta) / chordLength;
|
||||
double Rm = (H * H) / (8.0 * w) + w / 2.0;
|
||||
|
||||
// Left side
|
||||
double xInnerLeft = ox + w;
|
||||
double xc_left = xInnerLeft + Rm - w;
|
||||
|
||||
Point2d C_m_L = new Point2d(xc_left, oy + H / 2.0);
|
||||
Point2d C_fTop_L = new Point2d(xf_left, oy + H - r);
|
||||
Point2d C_fBot_L = new Point2d(xf_left, oy + r);
|
||||
|
||||
double fx_L_tangTop = r > 0 ? C_m_L.X + (Rm / (Rm - r)) * (C_fTop_L.X - C_m_L.X) : xInnerLeft;
|
||||
double fy_L_tangTop = r > 0 ? C_m_L.Y + (Rm / (Rm - r)) * (C_fTop_L.Y - C_m_L.Y) : oy + H;
|
||||
|
||||
double fx_L_tangBot = r > 0 ? C_m_L.X + (Rm / (Rm - r)) * (C_fBot_L.X - C_m_L.X) : xInnerLeft;
|
||||
double fy_L_tangBot = r > 0 ? C_m_L.Y + (Rm / (Rm - r)) * (C_fBot_L.Y - C_m_L.Y) : oy;
|
||||
|
||||
// Left Arc: From Top to Bottom, bulging Left (CCW)
|
||||
// Start: (xInnerLeft, yTopStraight)
|
||||
// End: (xInnerLeft, yBottomStraight)
|
||||
// Path: 12 o'clock -> 9 o'clock -> 6 o'clock direction is CCW.
|
||||
var leftPoly = new Polyline();
|
||||
leftPoly.AddVertexAt(0, new Point2d(xInnerLeft, yTopStraight), bulge, 0, 0);
|
||||
leftPoly.AddVertexAt(1, new Point2d(xInnerLeft, yBottomStraight), 0, 0, 0);
|
||||
|
||||
if (r > 0.01)
|
||||
{
|
||||
double angTop1 = Math.PI / 2.0;
|
||||
double angTop2 = Math.Atan2(fy_L_tangTop - C_fTop_L.Y, fx_L_tangTop - C_fTop_L.X);
|
||||
double diffTop = angTop2 - angTop1;
|
||||
while (diffTop < 0) diffTop += Math.PI * 2;
|
||||
while (diffTop >= Math.PI * 2) diffTop -= Math.PI * 2;
|
||||
double bulgeTop = Math.Tan(diffTop / 4.0);
|
||||
|
||||
double angM1 = Math.Atan2(fy_L_tangTop - C_m_L.Y, fx_L_tangTop - C_m_L.X);
|
||||
double angM2 = Math.Atan2(fy_L_tangBot - C_m_L.Y, fx_L_tangBot - C_m_L.X);
|
||||
double diffM = angM2 - angM1;
|
||||
while (diffM < 0) diffM += Math.PI * 2;
|
||||
while (diffM >= Math.PI * 2) diffM -= Math.PI * 2;
|
||||
double bulgeM = Math.Tan(diffM / 4.0);
|
||||
|
||||
double angBot1 = Math.Atan2(fy_L_tangBot - C_fBot_L.Y, fx_L_tangBot - C_fBot_L.X);
|
||||
double angBot2 = -Math.PI / 2.0;
|
||||
double diffBot = angBot2 - angBot1;
|
||||
while (diffBot < 0) diffBot += Math.PI * 2;
|
||||
while (diffBot >= Math.PI * 2) diffBot -= Math.PI * 2;
|
||||
double bulgeBot = Math.Tan(diffBot / 4.0);
|
||||
|
||||
leftPoly.AddVertexAt(0, new Point2d(xf_left, oy + H), bulgeTop, 0, 0);
|
||||
leftPoly.AddVertexAt(1, new Point2d(fx_L_tangTop, fy_L_tangTop), bulgeM, 0, 0);
|
||||
leftPoly.AddVertexAt(2, new Point2d(fx_L_tangBot, fy_L_tangBot), bulgeBot, 0, 0);
|
||||
leftPoly.AddVertexAt(3, new Point2d(xf_left, oy), 0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
double angM1 = Math.Atan2(oy + H - C_m_L.Y, xInnerLeft - C_m_L.X);
|
||||
double angM2 = Math.Atan2(oy - C_m_L.Y, xInnerLeft - C_m_L.X);
|
||||
double diffM = angM2 - angM1;
|
||||
while (diffM < 0) diffM += Math.PI * 2;
|
||||
while (diffM >= Math.PI * 2) diffM -= Math.PI * 2;
|
||||
double bulgeM = Math.Tan(diffM / 4.0);
|
||||
|
||||
leftPoly.AddVertexAt(0, new Point2d(xInnerLeft, oy + H), bulgeM, 0, 0);
|
||||
leftPoly.AddVertexAt(1, new Point2d(xInnerLeft, oy), 0, 0, 0);
|
||||
}
|
||||
|
||||
ctx.Style?.Apply(leftPoly, DrawingStyleManager.Role.OutlineBold);
|
||||
ctx.Btr.AppendEntity(leftPoly);
|
||||
ctx.Tr.AddNewlyCreatedDBObject(leftPoly, true);
|
||||
|
||||
// Right Arc: From Bottom to Top, bulging Right (CCW)
|
||||
// Start: (xInnerRight, yBottomStraight)
|
||||
// End: (xInnerRight, yTopStraight)
|
||||
// Path: 6 o'clock -> 3 o'clock -> 12 o'clock direction is CCW.
|
||||
var leftClosureLine = new Line(new Point3d(fx_L_tangTop, fy_L_tangTop, 0), new Point3d(fx_L_tangBot, fy_L_tangBot, 0));
|
||||
ctx.Style?.Apply(leftClosureLine, DrawingStyleManager.Role.OutlineBold);
|
||||
ctx.Btr.AppendEntity(leftClosureLine);
|
||||
ctx.Tr.AddNewlyCreatedDBObject(leftClosureLine, true);
|
||||
|
||||
// Right side
|
||||
double xInnerRight = ox + totalWidth - w;
|
||||
double xc_right = xInnerRight - Rm + w;
|
||||
|
||||
Point2d C_m_R = new Point2d(xc_right, oy + H / 2.0);
|
||||
Point2d C_fTop_R = new Point2d(xf_right, oy + H - r);
|
||||
Point2d C_fBot_R = new Point2d(xf_right, oy + r);
|
||||
|
||||
double fx_R_tangTop = r > 0 ? C_m_R.X + (Rm / (Rm - r)) * (C_fTop_R.X - C_m_R.X) : xInnerRight;
|
||||
double fy_R_tangTop = r > 0 ? C_m_R.Y + (Rm / (Rm - r)) * (C_fTop_R.Y - C_m_R.Y) : oy + H;
|
||||
|
||||
double fx_R_tangBot = r > 0 ? C_m_R.X + (Rm / (Rm - r)) * (C_fBot_R.X - C_m_R.X) : xInnerRight;
|
||||
double fy_R_tangBot = r > 0 ? C_m_R.Y + (Rm / (Rm - r)) * (C_fBot_R.Y - C_m_R.Y) : oy;
|
||||
|
||||
var rightPoly = new Polyline();
|
||||
rightPoly.AddVertexAt(0, new Point2d(xInnerRight, yBottomStraight), bulge, 0, 0);
|
||||
rightPoly.AddVertexAt(1, new Point2d(xInnerRight, yTopStraight), 0, 0, 0);
|
||||
if (r > 0.01)
|
||||
{
|
||||
double angBot1 = -Math.PI / 2.0;
|
||||
double angBot2 = Math.Atan2(fy_R_tangBot - C_fBot_R.Y, fx_R_tangBot - C_fBot_R.X);
|
||||
double diffBot = angBot2 - angBot1;
|
||||
while (diffBot < 0) diffBot += Math.PI * 2;
|
||||
while (diffBot >= Math.PI * 2) diffBot -= Math.PI * 2;
|
||||
double bulgeBot = Math.Tan(diffBot / 4.0);
|
||||
|
||||
double angM1 = Math.Atan2(fy_R_tangBot - C_m_R.Y, fx_R_tangBot - C_m_R.X);
|
||||
double angM2 = Math.Atan2(fy_R_tangTop - C_m_R.Y, fx_R_tangTop - C_m_R.X);
|
||||
double diffM = angM2 - angM1;
|
||||
while (diffM < 0) diffM += Math.PI * 2;
|
||||
while (diffM >= Math.PI * 2) diffM -= Math.PI * 2;
|
||||
double bulgeM = Math.Tan(diffM / 4.0);
|
||||
|
||||
double angTop1 = Math.Atan2(fy_R_tangTop - C_fTop_R.Y, fx_R_tangTop - C_fTop_R.X);
|
||||
double angTop2 = Math.PI / 2.0;
|
||||
double diffTop = angTop2 - angTop1;
|
||||
while (diffTop < 0) diffTop += Math.PI * 2;
|
||||
while (diffTop >= Math.PI * 2) diffTop -= Math.PI * 2;
|
||||
double bulgeTop = Math.Tan(diffTop / 4.0);
|
||||
|
||||
rightPoly.AddVertexAt(0, new Point2d(xf_right, oy), bulgeBot, 0, 0);
|
||||
rightPoly.AddVertexAt(1, new Point2d(fx_R_tangBot, fy_R_tangBot), bulgeM, 0, 0);
|
||||
rightPoly.AddVertexAt(2, new Point2d(fx_R_tangTop, fy_R_tangTop), bulgeTop, 0, 0);
|
||||
rightPoly.AddVertexAt(3, new Point2d(xf_right, oy + H), 0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
double angM1 = Math.Atan2(oy - C_m_R.Y, xInnerRight - C_m_R.X);
|
||||
double angM2 = Math.Atan2(oy + H - C_m_R.Y, xInnerRight - C_m_R.X);
|
||||
double diffM = angM2 - angM1;
|
||||
while (diffM < 0) diffM += Math.PI * 2;
|
||||
while (diffM >= Math.PI * 2) diffM -= Math.PI * 2;
|
||||
double bulgeM = Math.Tan(diffM / 4.0);
|
||||
|
||||
rightPoly.AddVertexAt(0, new Point2d(xInnerRight, oy), bulgeM, 0, 0);
|
||||
rightPoly.AddVertexAt(1, new Point2d(xInnerRight, oy + H), 0, 0, 0);
|
||||
}
|
||||
|
||||
ctx.Style?.Apply(rightPoly, DrawingStyleManager.Role.OutlineBold);
|
||||
ctx.Btr.AppendEntity(rightPoly);
|
||||
ctx.Tr.AddNewlyCreatedDBObject(rightPoly, true);
|
||||
|
||||
var rightClosureLine = new Line(new Point3d(fx_R_tangTop, fy_R_tangTop, 0), new Point3d(fx_R_tangBot, fy_R_tangBot, 0));
|
||||
ctx.Style?.Apply(rightClosureLine, DrawingStyleManager.Role.OutlineBold);
|
||||
ctx.Btr.AppendEntity(rightClosureLine);
|
||||
ctx.Tr.AddNewlyCreatedDBObject(rightClosureLine, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
@ -429,50 +525,21 @@ namespace CadParamPluging.Cad
|
||||
var width = Math.Abs(xEnd - xStart);
|
||||
if (width < 0.1) return;
|
||||
|
||||
var maxR = Math.Min(width * 0.5, height * 0.5);
|
||||
var r = Math.Min(filletR, maxR);
|
||||
var bulge = -Math.Tan(Math.PI / 8.0);
|
||||
|
||||
var poly = new Polyline();
|
||||
var topPoly = new Polyline();
|
||||
topPoly.AddVertexAt(0, new Point2d(xStart, yTop), 0, 0, 0);
|
||||
topPoly.AddVertexAt(1, new Point2d(xEnd, yTop), 0, 0, 0);
|
||||
|
||||
if (isLeft)
|
||||
{
|
||||
poly.AddVertexAt(0, new Point2d(xEnd, yBottom), 0, 0, 0);
|
||||
|
||||
if (r > 0.01)
|
||||
{
|
||||
poly.AddVertexAt(1, new Point2d(xStart + r, yBottom), bulge, 0, 0);
|
||||
poly.AddVertexAt(2, new Point2d(xStart, yBottom + r), 0, 0, 0);
|
||||
poly.AddVertexAt(3, new Point2d(xStart, yTop - r), bulge, 0, 0);
|
||||
poly.AddVertexAt(4, new Point2d(xStart + r, yTop), 0, 0, 0);
|
||||
poly.AddVertexAt(5, new Point2d(xEnd, yTop), 0, 0, 0);
|
||||
}
|
||||
poly.Closed = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
poly.AddVertexAt(0, new Point2d(xStart, yTop), 0, 0, 0);
|
||||
|
||||
if (r > 0.01)
|
||||
{
|
||||
poly.AddVertexAt(1, new Point2d(xEnd - r, yTop), bulge, 0, 0);
|
||||
poly.AddVertexAt(2, new Point2d(xEnd, yTop - r), 0, 0, 0);
|
||||
poly.AddVertexAt(3, new Point2d(xEnd, yBottom + r), bulge, 0, 0);
|
||||
poly.AddVertexAt(4, new Point2d(xEnd - r, yBottom), 0, 0, 0);
|
||||
poly.AddVertexAt(5, new Point2d(xStart, yBottom), 0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
poly.AddVertexAt(1, new Point2d(xEnd, yTop), 0, 0, 0);
|
||||
poly.AddVertexAt(2, new Point2d(xEnd, yBottom), 0, 0, 0);
|
||||
poly.AddVertexAt(3, new Point2d(xStart, yBottom), 0, 0, 0);
|
||||
}
|
||||
poly.Closed = false;
|
||||
}
|
||||
ctx.Style?.Apply(topPoly, DrawingStyleManager.Role.OutlineBold);
|
||||
ctx.Btr.AppendEntity(topPoly);
|
||||
ctx.Tr.AddNewlyCreatedDBObject(topPoly, true);
|
||||
|
||||
ctx.Style?.Apply(poly, DrawingStyleManager.Role.OutlineBold);
|
||||
ctx.Btr.AppendEntity(poly);
|
||||
ctx.Tr.AddNewlyCreatedDBObject(poly, true);
|
||||
var botPoly = new Polyline();
|
||||
botPoly.AddVertexAt(0, new Point2d(xStart, yBottom), 0, 0, 0);
|
||||
botPoly.AddVertexAt(1, new Point2d(xEnd, yBottom), 0, 0, 0);
|
||||
|
||||
ctx.Style?.Apply(botPoly, DrawingStyleManager.Role.OutlineBold);
|
||||
ctx.Btr.AppendEntity(botPoly);
|
||||
ctx.Tr.AddNewlyCreatedDBObject(botPoly, true);
|
||||
}
|
||||
|
||||
private static void DrawRingSectionHatchWithFillet(FeatureDrivenDrawer.DrawingContext ctx, double xInnerRight, double xOuterRight, double yBottom, double height, double filletR)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user