diff --git a/Cad/FeatureDrivenDrawer.cs b/Cad/FeatureDrivenDrawer.cs
index 60e8acf..b1aedb6 100644
--- a/Cad/FeatureDrivenDrawer.cs
+++ b/Cad/FeatureDrivenDrawer.cs
@@ -91,14 +91,125 @@ namespace CadParamPluging.Cad
#endregion
+ #region 预期图形尺寸计算
+
+ ///
+ /// 预期图形尺寸
+ ///
+ public class ExpectedDrawingSize
+ {
+ public double Width { get; set; }
+ public double Height { get; set; }
+ public bool IsValid => Width > 0 && Height > 0;
+ }
+
+ ///
+ /// 根据参数计算预期绘制图形的尺寸(不包含标注,仅计算图形主体)
+ ///
+ public static ExpectedDrawingSize CalculateExpectedSize(ParamBag bag, string structuralFeature)
+ {
+ if (bag == null)
+ {
+ return new ExpectedDrawingSize();
+ }
+
+ if (IsRing(structuralFeature))
+ {
+ return CalculateRingSize(bag);
+ }
+ if (IsDisk(structuralFeature))
+ {
+ return CalculateDiskSize(bag);
+ }
+ if (IsShaft(structuralFeature))
+ {
+ return CalculateShaftSize(bag);
+ }
+ if (IsBlock(structuralFeature))
+ {
+ return CalculateBlockSize(bag);
+ }
+
+ return new ExpectedDrawingSize();
+ }
+
+ private static ExpectedDrawingSize CalculateRingSize(ParamBag bag)
+ {
+ var outerDia = bag.GetDoubleOrNull(KeyOuterDiameter1) ?? 0;
+ var height = bag.GetDoubleOrNull(KeyHeight1) ?? 0;
+
+ // 环形图形:宽度=高度参数(X方向),高度=外径(Y方向)
+ // 加上标注的额外空间(约40像素每侧)
+ var extraMargin = 40;
+ return new ExpectedDrawingSize
+ {
+ Width = height + extraMargin * 2,
+ Height = outerDia + extraMargin * 2
+ };
+ }
+
+ private static ExpectedDrawingSize CalculateDiskSize(ParamBag bag)
+ {
+ var diameter = bag.GetDoubleOrNull(KeyDiskDiameter) ?? 0;
+ var height = bag.GetDoubleOrNull(KeyDiskHeight) ?? 0;
+
+ var extraMargin = 40;
+ return new ExpectedDrawingSize
+ {
+ Width = diameter + extraMargin * 2,
+ Height = height + extraMargin * 2
+ };
+ }
+
+ private static ExpectedDrawingSize CalculateShaftSize(ParamBag bag)
+ {
+ var diameter = bag.GetDoubleOrNull(KeyDiameter) ?? 0;
+ var length = bag.GetDoubleOrNull(KeyLength) ?? 0;
+
+ var extraMargin = 40;
+ return new ExpectedDrawingSize
+ {
+ Width = length + extraMargin * 2,
+ Height = diameter + extraMargin * 2
+ };
+ }
+
+ private static ExpectedDrawingSize CalculateBlockSize(ParamBag bag)
+ {
+ var size1 = bag.GetDoubleOrNull(KeySize1) ?? bag.GetDoubleOrNull("Size123") ?? 0;
+ var size2 = bag.GetDoubleOrNull(KeySize2) ?? size1;
+
+ var extraMargin = 40;
+ return new ExpectedDrawingSize
+ {
+ Width = size1 + extraMargin * 2,
+ Height = size2 + extraMargin * 2
+ };
+ }
+
+ #endregion
+
#region 主入口
+ ///
+ /// 绘制图形(带缩放支持)
+ ///
+ /// CAD上下文
+ /// 参数包
+ /// 交付状态
+ /// 结构特征
+ /// 特殊条件
+ /// 绘图中心点
+ /// 缩放比例(1.0表示不缩放)
public static void Draw(CadContext ctx, ParamBag bag, string deliveryStatus, string structuralFeature,
- string specialCondition = null, Point3d? center = null)
+ string specialCondition = null, Point3d? center = null, 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 btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
@@ -106,7 +217,7 @@ namespace CadParamPluging.Cad
var context = new DrawingContext
{
Ctx = ctx,
- Bag = bag,
+ Bag = effectiveBag,
Center = center ?? Point3d.Origin,
DeliveryStatus = deliveryStatus,
StructuralFeature = structuralFeature,
@@ -759,6 +870,78 @@ namespace CadParamPluging.Cad
catch { }
}
+ ///
+ /// 对参数包中的尺寸参数应用缩放比例
+ ///
+ private static ParamBag ScaleParamBag(ParamBag original, double scaleFactor)
+ {
+ if (original == null || scaleFactor <= 0 || scaleFactor >= 1.0)
+ {
+ return original;
+ }
+
+ var scaled = new ParamBag();
+
+ // 需要缩放的尺寸参数Key列表
+ var sizeKeys = new HashSet(StringComparer.OrdinalIgnoreCase)
+ {
+ // 环形参数
+ KeyOuterDiameter1, KeyInnerDiameter2, KeyHeight1,
+ KeyOuterDiameter1Prime, KeyInnerDiameter2Prime, KeyHeight1Prime,
+ KeyMinWallThickness,
+ // 饼盘参数
+ KeyDiskDiameter, KeyDiskHeight,
+ // 轴杆参数
+ KeyDiameter, KeyLength,
+ // 方形参数
+ KeySize1, KeySize2, KeySize3, "Size123",
+ // 圆角参数
+ KeyUnspecifiedFilletRadiusMax, KeyInnerRadiusMax, KeyRoundHeadFilletRadiusMax
+ };
+
+ // 公差参数也需要缩放
+ var toleranceKeys = new HashSet(StringComparer.OrdinalIgnoreCase)
+ {
+ KeyOuterDiameter1TolPlus, KeyOuterDiameter1TolMinus,
+ KeyInnerDiameter2TolPlus, KeyInnerDiameter2TolMinus,
+ KeyHeight1TolPlus, KeyHeight1TolMinus,
+ KeyDiskDiameterTolPlus, KeyDiskDiameterTolMinus,
+ KeyDiskHeightTolPlus, KeyDiskHeightTolMinus,
+ KeyDiameterTolPlus, KeyDiameterTolMinus,
+ KeyLengthTolPlus, KeyLengthTolMinus,
+ KeySize1TolPlus, KeySize1TolMinus,
+ KeySize2TolPlus, KeySize2TolMinus,
+ KeySize3TolPlus, KeySize3TolMinus
+ };
+
+ foreach (var key in original.GetKeys())
+ {
+ var value = original.GetString(key);
+
+ if (sizeKeys.Contains(key) || toleranceKeys.Contains(key))
+ {
+ // 尝试解析为数值并缩放
+ if (double.TryParse(value, out var numValue))
+ {
+ var scaledValue = numValue * scaleFactor;
+ // 保留适当的小数位数
+ scaled.Set(key, scaledValue.ToString("F2"));
+ }
+ else
+ {
+ scaled.Set(key, value);
+ }
+ }
+ else
+ {
+ // 非尺寸参数直接复制
+ scaled.Set(key, value);
+ }
+ }
+
+ return scaled;
+ }
+
#endregion
}
}
diff --git a/Cad/HalfSectionDrawer.cs b/Cad/HalfSectionDrawer.cs
index 6be4c76..a7fb35a 100644
--- a/Cad/HalfSectionDrawer.cs
+++ b/Cad/HalfSectionDrawer.cs
@@ -20,11 +20,12 @@ namespace CadParamPluging.Cad
/// 结构特征(环形/饼盘/轴杆/方体)
/// 特殊条件(中心冲孔/有圆头等)
/// 绘图中心点
+ /// 缩放比例(1.0表示不缩放)
public static void Draw(CadContext ctx, ParamBag bag, string deliveryStatus, string structuralFeature,
- string specialCondition = null, Point3d? center = null)
+ string specialCondition = null, Point3d? center = null, double scaleFactor = 1.0)
{
// 委托给特征驱动绘图引擎
- FeatureDrivenDrawer.Draw(ctx, bag, deliveryStatus, structuralFeature, specialCondition, center);
+ FeatureDrivenDrawer.Draw(ctx, bag, deliveryStatus, structuralFeature, specialCondition, center, scaleFactor);
}
///
diff --git a/Cad/TemplateDrawingService.cs b/Cad/TemplateDrawingService.cs
index 3c20a25..cefcf60 100644
--- a/Cad/TemplateDrawingService.cs
+++ b/Cad/TemplateDrawingService.cs
@@ -1313,5 +1313,185 @@ namespace CadParamPluging.Cad
return true;
}
}
+
+ ///
+ /// 检测白色外框(图纸边界)的范围
+ /// 白色外框通常是 ColorIndex=7 的 Line 或 Polyline,构成图纸的可绘图区域
+ ///
+ public static Extents3d? ComputeWhiteFrameExtents(CadContext ctx)
+ {
+ if (ctx == null)
+ {
+ return null;
+ }
+
+ var db = ctx.Database;
+ var tr = ctx.Transaction;
+
+ var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
+ var ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
+
+ var allEntities = ms.Cast()
+ .Select(id => tr.GetObject(id, OpenMode.ForRead, false) as Entity)
+ .Where(e => e != null && !e.IsErased)
+ .ToList();
+
+ return ComputeWhiteFrameExtentsFromEntities(tr, allEntities);
+ }
+
+ private static Extents3d? ComputeWhiteFrameExtentsFromEntities(Transaction tr, IEnumerable entities)
+ {
+ Extents3d? result = null;
+
+ foreach (var ent in entities)
+ {
+ if (ent == null || ent.IsErased)
+ {
+ continue;
+ }
+
+ // 只处理 Line 或 Polyline
+ if (!(ent is Line) && !(ent is Polyline))
+ {
+ continue;
+ }
+
+ // 检查是否是白色(ColorIndex=7)
+ if (!IsWhiteColor(ent, tr))
+ {
+ continue;
+ }
+
+ try
+ {
+ var ext = ent.GeometricExtents;
+ if (result == null)
+ {
+ result = ext;
+ }
+ else
+ {
+ result = new Extents3d(
+ new Point3d(
+ Math.Min(result.Value.MinPoint.X, ext.MinPoint.X),
+ Math.Min(result.Value.MinPoint.Y, ext.MinPoint.Y),
+ Math.Min(result.Value.MinPoint.Z, ext.MinPoint.Z)),
+ new Point3d(
+ Math.Max(result.Value.MaxPoint.X, ext.MaxPoint.X),
+ Math.Max(result.Value.MaxPoint.Y, ext.MaxPoint.Y),
+ Math.Max(result.Value.MaxPoint.Z, ext.MaxPoint.Z)));
+ }
+ }
+ catch
+ {
+ // 忽略
+ }
+ }
+
+ return result;
+ }
+
+ private static bool IsWhiteColor(Entity ent, Transaction tr)
+ {
+ if (ent == null)
+ {
+ return false;
+ }
+
+ // ColorIndex=7 是白色
+ var colorIndex = ent.ColorIndex;
+ if (colorIndex == 7)
+ {
+ return true;
+ }
+
+ // ColorIndex=256 表示 ByLayer,需要检查图层颜色
+ if (colorIndex == 256 && tr != null)
+ {
+ try
+ {
+ var layer = tr.GetObject(ent.LayerId, OpenMode.ForRead) as LayerTableRecord;
+ if (layer != null && layer.Color.ColorIndex == 7)
+ {
+ return true;
+ }
+ }
+ catch
+ {
+ // 忽略
+ }
+ }
+
+ return false;
+ }
+
+ ///
+ /// 图形尺寸检查结果
+ ///
+ public sealed class DrawingSizeCheckResult
+ {
+ public bool NeedsScaling { get; set; }
+ public double ScaleFactor { get; set; } = 1.0;
+ public double DrawingWidth { get; set; }
+ public double DrawingHeight { get; set; }
+ public double AvailableWidth { get; set; }
+ public double AvailableHeight { get; set; }
+ public string Message { get; set; }
+ }
+
+ ///
+ /// 检查图形是否会超出图纸边界,如果超出则计算缩放比例
+ ///
+ /// 白色外框范围
+ /// 预期绘制图形的宽度
+ /// 预期绘制图形的高度
+ /// 边距(默认50)
+ /// 检查结果,包含是否需要缩放和缩放比例
+ public static DrawingSizeCheckResult CheckDrawingSize(Extents3d? whiteFrameExtents, double drawingWidth, double drawingHeight, double margin = 50)
+ {
+ var result = new DrawingSizeCheckResult
+ {
+ DrawingWidth = drawingWidth,
+ DrawingHeight = drawingHeight
+ };
+
+ if (!whiteFrameExtents.HasValue)
+ {
+ result.Message = "未检测到白色外框,跳过尺寸检查";
+ return result;
+ }
+
+ var frame = whiteFrameExtents.Value;
+ var availableWidth = frame.MaxPoint.X - frame.MinPoint.X - margin * 2;
+ var availableHeight = frame.MaxPoint.Y - frame.MinPoint.Y - margin * 2;
+
+ result.AvailableWidth = availableWidth;
+ result.AvailableHeight = availableHeight;
+
+ if (availableWidth <= 0 || availableHeight <= 0)
+ {
+ result.Message = "白色外框范围无效";
+ return result;
+ }
+
+ // 计算宽度和高度的缩放比例,取较小值(等比例缩放)
+ var scaleX = availableWidth / drawingWidth;
+ var scaleY = availableHeight / drawingHeight;
+
+ if (scaleX >= 1.0 && scaleY >= 1.0)
+ {
+ result.NeedsScaling = false;
+ result.ScaleFactor = 1.0;
+ result.Message = $"图形尺寸正常,无需缩放 (图形: {drawingWidth:F1}x{drawingHeight:F1}, 可用: {availableWidth:F1}x{availableHeight:F1})";
+ return result;
+ }
+
+ // 需要缩放,取较小的比例以确保两个方向都不超出
+ result.NeedsScaling = true;
+ result.ScaleFactor = Math.Min(scaleX, scaleY);
+ result.Message = $"图形超出边界,将等比例缩放至 {result.ScaleFactor:P1} (图形: {drawingWidth:F1}x{drawingHeight:F1}, 可用: {availableWidth:F1}x{availableHeight:F1})";
+
+ return result;
+ }
}
}
diff --git a/UI/ParamDrawingPanel.cs b/UI/ParamDrawingPanel.cs
index 72f13c7..a58f84a 100644
--- a/UI/ParamDrawingPanel.cs
+++ b/UI/ParamDrawingPanel.cs
@@ -616,6 +616,51 @@ namespace CadParamPluging.UI
var removeResult = TemplateDrawingService.RemoveTemplateOriginalDrawing(ctx);
AppendLog($"已删除原有图形: 红色外框={removeResult.OuterFrameErased}, CAXA图层={removeResult.CaxaLayerErased}, 标注={removeResult.DimensionLayerErased}, 保留右上角={removeResult.DimensionLayerKept}");
+ // 检测白色外框(图纸边界)范围
+ var whiteFrameExtents = TemplateDrawingService.ComputeWhiteFrameExtents(ctx);
+
+ // 计算预期图形尺寸
+ var expectedSize = FeatureDrivenDrawer.CalculateExpectedSize(bag, tplParams.SheetSize);
+
+ // 检查是否会超出图纸边界
+ double scaleFactor = 1.0;
+ if (expectedSize.IsValid && whiteFrameExtents.HasValue)
+ {
+ var sizeCheck = TemplateDrawingService.CheckDrawingSize(
+ whiteFrameExtents,
+ expectedSize.Width,
+ expectedSize.Height,
+ 50); // 边距50
+
+ AppendLog(sizeCheck.Message);
+
+ if (sizeCheck.NeedsScaling)
+ {
+ // 询问用户是否要等比例缩放
+ var confirmScale = MessageBox.Show(
+ this,
+ $"图形尺寸超出图纸边界!\n\n" +
+ $"图形尺寸: {expectedSize.Width:F1} x {expectedSize.Height:F1}\n" +
+ $"可用区域: {sizeCheck.AvailableWidth:F1} x {sizeCheck.AvailableHeight:F1}\n" +
+ $"建议缩放比例: {sizeCheck.ScaleFactor:P1}\n\n" +
+ $"是否等比例缩小图形以适应图纸?\n" +
+ $"选择【是】将自动缩放,选择【否】将按原尺寸绘制(可能超出边界)",
+ "图形尺寸超出",
+ MessageBoxButtons.YesNo,
+ MessageBoxIcon.Warning);
+
+ if (confirmScale == DialogResult.Yes)
+ {
+ scaleFactor = sizeCheck.ScaleFactor;
+ AppendLog($"将应用缩放比例: {scaleFactor:P1}");
+ }
+ else
+ {
+ AppendLog("用户选择按原尺寸绘制");
+ }
+ }
+ }
+
// 根据模板参数绘制半剖视图,居中放置于原图纸位置
// 使用特征驱动模式:根据参数存在性动态绘制对应特征
HalfSectionDrawer.Draw(
@@ -624,7 +669,8 @@ namespace CadParamPluging.UI
tplParams.ProjectType, // 交付状态
tplParams.SheetSize, // 结构特征
tplParams.Scale, // 特殊条件(中心冲孔/有圆头等)
- removeResult.OriginalCenter // 原图纸中心点
+ removeResult.OriginalCenter, // 原图纸中心点
+ scaleFactor // 缩放比例
);
ctx.Commit();