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();