修改缩放功能

This commit is contained in:
sladro 2025-12-18 14:47:17 +08:00
parent cdd9ae1f43
commit 34028c1ac6
4 changed files with 415 additions and 5 deletions

View File

@ -91,14 +91,125 @@ namespace CadParamPluging.Cad
#endregion
#region
/// <summary>
/// 预期图形尺寸
/// </summary>
public class ExpectedDrawingSize
{
public double Width { get; set; }
public double Height { get; set; }
public bool IsValid => Width > 0 && Height > 0;
}
/// <summary>
/// 根据参数计算预期绘制图形的尺寸(不包含标注,仅计算图形主体)
/// </summary>
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
/// <summary>
/// 绘制图形(带缩放支持)
/// </summary>
/// <param name="ctx">CAD上下文</param>
/// <param name="bag">参数包</param>
/// <param name="deliveryStatus">交付状态</param>
/// <param name="structuralFeature">结构特征</param>
/// <param name="specialCondition">特殊条件</param>
/// <param name="center">绘图中心点</param>
/// <param name="scaleFactor">缩放比例1.0表示不缩放)</param>
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 { }
}
/// <summary>
/// 对参数包中的尺寸参数应用缩放比例
/// </summary>
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<string>(StringComparer.OrdinalIgnoreCase)
{
// 环形参数
KeyOuterDiameter1, KeyInnerDiameter2, KeyHeight1,
KeyOuterDiameter1Prime, KeyInnerDiameter2Prime, KeyHeight1Prime,
KeyMinWallThickness,
// 饼盘参数
KeyDiskDiameter, KeyDiskHeight,
// 轴杆参数
KeyDiameter, KeyLength,
// 方形参数
KeySize1, KeySize2, KeySize3, "Size123",
// 圆角参数
KeyUnspecifiedFilletRadiusMax, KeyInnerRadiusMax, KeyRoundHeadFilletRadiusMax
};
// 公差参数也需要缩放
var toleranceKeys = new HashSet<string>(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
}
}

View File

@ -20,11 +20,12 @@ namespace CadParamPluging.Cad
/// <param name="structuralFeature">结构特征(环形/饼盘/轴杆/方体)</param>
/// <param name="specialCondition">特殊条件(中心冲孔/有圆头等)</param>
/// <param name="center">绘图中心点</param>
/// <param name="scaleFactor">缩放比例1.0表示不缩放)</param>
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);
}
/// <summary>

View File

@ -1313,5 +1313,185 @@ namespace CadParamPluging.Cad
return true;
}
}
/// <summary>
/// 检测白色外框(图纸边界)的范围
/// 白色外框通常是 ColorIndex=7 的 Line 或 Polyline构成图纸的可绘图区域
/// </summary>
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<ObjectId>()
.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<Entity> 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;
}
/// <summary>
/// 图形尺寸检查结果
/// </summary>
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; }
}
/// <summary>
/// 检查图形是否会超出图纸边界,如果超出则计算缩放比例
/// </summary>
/// <param name="whiteFrameExtents">白色外框范围</param>
/// <param name="drawingWidth">预期绘制图形的宽度</param>
/// <param name="drawingHeight">预期绘制图形的高度</param>
/// <param name="margin">边距默认50</param>
/// <returns>检查结果,包含是否需要缩放和缩放比例</returns>
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;
}
}
}

View File

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