CadParamPluging/UI/ParamDrawingPanel.cs

942 lines
36 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using CadParamPluging.Cad;
using CadParamPluging.Common;
using CadParamPluging.Domain;
using CadParamPluging.Domain.Models;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace CadParamPluging.UI
{
public class ParamDrawingPanel : UserControl
{
private readonly ComboBox _cbProjectType;
private readonly ComboBox _cbDrawingType;
private readonly ComboBox _cbSheetSize;
private readonly ComboBox _cbScale;
private Label _lblTemplateInfo;
private TextBox _txtLog;
private TextBox _txtTemplatePath;
private string _selectedFolderPath;
private string[] _cadFilePaths = new string[0];
private TemplateInfo _selectedTemplate;
private Extents3d? _selectedModelWindow;
private string _selectedSheetName;
public ParamDrawingPanel()
{
Dock = DockStyle.Fill;
var dropdownOptions = DropdownOptionsStore.Load();
var layout = new TableLayoutPanel
{
Dock = DockStyle.Fill,
ColumnCount = 1,
RowCount = 4,
AutoSize = true,
AutoSizeMode = AutoSizeMode.GrowAndShrink,
Padding = new Padding(8)
};
_cbProjectType = CreateComboBox(dropdownOptions.DeliveryStatuses);
_cbDrawingType = CreateComboBox(dropdownOptions.ProcessMethods);
_cbSheetSize = CreateComboBox(dropdownOptions.StructuralFeatures);
_cbScale = CreateComboBox(dropdownOptions.SpecialConditions);
var templateGroup = BuildTemplateGroup();
var drawingGroup = BuildDrawingGroup();
var actionPanel = BuildActionPanel();
var logGroup = BuildLogGroup();
layout.Controls.Add(templateGroup, 0, 0);
layout.Controls.Add(drawingGroup, 0, 1);
layout.Controls.Add(actionPanel, 0, 2);
layout.Controls.Add(logGroup, 0, 3);
Controls.Add(layout);
}
private GroupBox BuildTemplateGroup()
{
var group = new GroupBox
{
Text = "模板参数",
Dock = DockStyle.Top,
AutoSize = true,
AutoSizeMode = AutoSizeMode.GrowAndShrink
};
var grid = new TableLayoutPanel
{
Dock = DockStyle.Fill,
ColumnCount = 2,
RowCount = 6,
AutoSize = true
};
grid.Controls.Add(new Label { Text = "交付状态", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, 0);
grid.Controls.Add(_cbProjectType, 1, 0);
grid.Controls.Add(new Label { Text = "工艺方法", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, 1);
grid.Controls.Add(_cbDrawingType, 1, 1);
grid.Controls.Add(new Label { Text = "结构特征", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, 2);
grid.Controls.Add(_cbSheetSize, 1, 2);
grid.Controls.Add(new Label { Text = "特殊条件", AutoSize = true, TextAlign = ContentAlignment.MiddleLeft }, 0, 3);
grid.Controls.Add(_cbScale, 1, 3);
var btnSelect = new Button { Text = "选择路径", AutoSize = true };
btnSelect.Click += (_, __) => OnSelectTemplate();
_txtTemplatePath = new TextBox { Width = 160, ReadOnly = true };
grid.Controls.Add(btnSelect, 0, 4);
grid.Controls.Add(_txtTemplatePath, 1, 4);
var btnMatch = new Button { Text = "匹配模板", AutoSize = true };
btnMatch.Click += (_, __) => OnMatchTemplate();
_lblTemplateInfo = new Label
{
Text = "未匹配模板",
AutoSize = true,
ForeColor = Color.DarkBlue,
TextAlign = ContentAlignment.MiddleLeft
};
grid.Controls.Add(btnMatch, 0, 5);
grid.Controls.Add(_lblTemplateInfo, 1, 5);
group.Controls.Add(grid);
return group;
}
private GroupBox BuildDrawingGroup()
{
var group = new GroupBox
{
Text = "出图参数",
Dock = DockStyle.Top,
AutoSize = true,
AutoSizeMode = AutoSizeMode.GrowAndShrink
};
var label = new Label
{
AutoSize = true,
Padding = new Padding(8),
Text = "出图参数较多,请点击【生成图纸】后在弹窗中填写。"
};
group.Controls.Add(label);
return group;
}
private FlowLayoutPanel BuildActionPanel()
{
var panel = new FlowLayoutPanel
{
Dock = DockStyle.Top,
AutoSize = true
};
var btnGenerate = new Button { Text = "生成图纸", AutoSize = true };
btnGenerate.Click += (_, __) => OnGenerateDrawing();
var btnSaveAs = new Button { Text = "保存当前图纸", AutoSize = true };
btnSaveAs.Click += (_, __) => OnSaveDrawing();
var btnSettings = new Button { Text = "设置", AutoSize = true };
btnSettings.Click += (_, __) => OnOpenSettings();
var btnTestDraw = new Button { Text = "测试绘制", AutoSize = true };
btnTestDraw.Click += (_, __) => OnTestDraw();
panel.Controls.Add(btnGenerate);
panel.Controls.Add(btnSaveAs);
panel.Controls.Add(btnSettings);
// panel.Controls.Add(btnTestDraw); // 暂时屏蔽测试绘制按钮
return panel;
}
private GroupBox BuildLogGroup()
{
var group = new GroupBox
{
Text = "日志",
Dock = DockStyle.Fill
};
_txtLog = new TextBox
{
Multiline = true,
ScrollBars = ScrollBars.Vertical,
Dock = DockStyle.Fill,
Height = 140
};
group.Controls.Add(_txtLog);
return group;
}
private void OnMatchTemplate()
{
try
{
if (_cadFilePaths == null || _cadFilePaths.Length == 0)
{
AppendLog("请先选择路径。");
return;
}
AppendLog("开始匹配模板...");
var tplParams = CollectTemplateParams();
foreach (var cadPath in _cadFilePaths)
{
if (string.IsNullOrWhiteSpace(cadPath) || !File.Exists(cadPath))
{
continue;
}
// 1) 优先按 Layout(PaperSpace) 匹配
var layoutCandidates = TemplateLayoutAnnotationExtractor.ExtractPerLayout(cadPath);
var layoutMatch = layoutCandidates.FirstOrDefault(c => LayoutMatches(c, tplParams));
if (layoutMatch != null)
{
_selectedTemplate = new TemplateInfo
{
Name = Path.GetFileName(cadPath),
FilePath = cadPath
};
_selectedTemplate.LayoutName = layoutMatch.LayoutName;
_selectedModelWindow = null;
_selectedSheetName = layoutMatch.LayoutName;
_lblTemplateInfo.Text = $"{cadPath} | {layoutMatch.LayoutName}";
AppendLog($"匹配成功: {Path.GetFileName(cadPath)} | Layout: {layoutMatch.LayoutName}");
return;
}
// 2) Layout 未命中时,尝试按 ModelSpace 窗口候选匹配
var modelCandidates = TemplateModelSheetExtractor.ExtractCandidates(cadPath);
var modelMatch = modelCandidates.FirstOrDefault(c => ModelMatches(c, tplParams));
if (modelMatch != null)
{
_selectedTemplate = new TemplateInfo
{
Name = Path.GetFileName(cadPath),
FilePath = cadPath
};
_selectedTemplate.LayoutName = null;
_selectedModelWindow = modelMatch.Window;
_selectedSheetName = modelMatch.Name;
_lblTemplateInfo.Text = $"{cadPath} | {modelMatch.Name}";
AppendLog($"匹配成功: {Path.GetFileName(cadPath)} | Model: {modelMatch.Name}");
return;
}
}
_selectedTemplate = null;
_selectedModelWindow = null;
_selectedSheetName = null;
_lblTemplateInfo.Text = "未匹配模板";
AppendLog("未找到匹配模板。");
}
catch (BusinessException bex)
{
if (_selectedTemplate != null)
{
_selectedTemplate.LayoutName = null;
}
_selectedModelWindow = null;
_selectedSheetName = null;
_lblTemplateInfo.Text = _selectedTemplate?.FilePath ?? "未匹配图纸";
AppendLog($"图纸匹配错误: {bex.Message}");
}
catch (Exception ex)
{
if (_selectedTemplate != null)
{
_selectedTemplate.LayoutName = null;
}
_selectedModelWindow = null;
_selectedSheetName = null;
_lblTemplateInfo.Text = _selectedTemplate?.FilePath ?? "未匹配图纸";
AppendLog($"匹配失败: {ex.Message}");
Logger.Error("MatchLayout", ex);
}
}
private static bool LayoutMatches(LayoutAnnotation ann, TemplateParams tplParams)
{
if (ann == null || tplParams == null)
{
return false;
}
return ContainsIgnoreCase(ann.DeliveryStatuses, tplParams.ProjectType)
&& ContainsIgnoreCase(ann.ProcessMethods, tplParams.DrawingType)
&& ContainsIgnoreCase(ann.StructuralFeatures, tplParams.SheetSize)
&& ContainsIgnoreCase(ann.SpecialConditions, tplParams.Scale);
}
private static bool ContainsIgnoreCase(System.Collections.Generic.IEnumerable<string> values, string expected)
{
if (string.IsNullOrWhiteSpace(expected))
{
return true;
}
if (values == null)
{
return false;
}
var exp = NormalizeValue(expected);
return values.Any(v => string.Equals(NormalizeValue(v), exp, StringComparison.OrdinalIgnoreCase));
}
private static string NormalizeValue(string s)
{
if (string.IsNullOrWhiteSpace(s))
{
return string.Empty;
}
var trimmed = s.Trim();
var chars = trimmed.Where(c => !char.IsWhiteSpace(c)).ToArray();
return new string(chars);
}
private static string Preview(System.Collections.Generic.IEnumerable<string> values)
{
if (values == null)
{
return "(无)";
}
var arr = values.Where(v => !string.IsNullOrWhiteSpace(v)).Select(v => v.Trim()).ToArray();
return arr.Length == 0 ? "(无)" : string.Join("/", arr);
}
private static bool ModelMatches(ModelSheetCandidate ann, TemplateParams tplParams)
{
if (ann == null || tplParams == null)
{
return false;
}
return ContainsIgnoreCase(ann.DeliveryStatuses, tplParams.ProjectType)
&& ContainsIgnoreCase(ann.ProcessMethods, tplParams.DrawingType)
&& ContainsIgnoreCase(ann.StructuralFeatures, tplParams.SheetSize)
&& ContainsIgnoreCase(ann.SpecialConditions, tplParams.Scale);
}
private void OnSelectTemplate()
{
try
{
using (var dialog = new FolderBrowserDialog())
{
dialog.Description = "选择包含 CAD 文件的文件夹";
if (!string.IsNullOrWhiteSpace(_selectedFolderPath) && Directory.Exists(_selectedFolderPath))
{
dialog.SelectedPath = _selectedFolderPath;
}
if (dialog.ShowDialog(this) == DialogResult.OK)
{
var folderPath = dialog.SelectedPath;
if (string.IsNullOrWhiteSpace(folderPath) || !Directory.Exists(folderPath))
{
AppendLog("选择路径无效。");
return;
}
_selectedFolderPath = folderPath;
_txtTemplatePath.Text = folderPath;
_cadFilePaths = LoadCadFilesFromFolder(folderPath);
AppendLog($"已选择路径: {folderPath}");
AppendLog($"检测到 CAD 文件数量: {_cadFilePaths.Length}");
foreach (var p in _cadFilePaths.Take(10))
{
AppendLog($"- {Path.GetFileName(p)}");
}
if (_cadFilePaths.Length > 10)
{
AppendLog($"... 还有 {_cadFilePaths.Length - 10} 个文件");
}
}
}
}
catch (Exception ex)
{
AppendLog($"选择路径失败: {ex.Message}");
Logger.Error("SelectCadFolder", ex);
}
}
private static string[] LoadCadFilesFromFolder(string folderPath)
{
if (string.IsNullOrWhiteSpace(folderPath) || !Directory.Exists(folderPath))
{
return new string[0];
}
var patterns = new[] { "*.dwg", "*.dwt", "*.dxf" };
return patterns
.SelectMany(p => Directory.EnumerateFiles(folderPath, p, SearchOption.TopDirectoryOnly))
.Distinct(StringComparer.OrdinalIgnoreCase)
.OrderBy(p => p, StringComparer.OrdinalIgnoreCase)
.ToArray();
}
private void TryReplaceDropdownOptionsFromTemplate(string templatePath)
{
try
{
var result = TemplateAnnotationOptionsExtractor.Extract(templatePath);
var options = result?.Options;
if (options == null || !HasAnyOptions(options))
{
AppendLog("未从模板标注解析到参数,下拉列表不变。");
return;
}
AppendLog("已从模板标注解析到参数,询问是否替换下拉设置。");
var preview = BuildOptionsPreview(options, 5);
var confirm = MessageBox.Show(
this,
$"检测到模板参数(去重后):\n\n{preview}\n\n是否用模板参数替换当前下拉列表并保存\n特殊条件不从模板解析将保持当前设置",
"模板参数",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (confirm != DialogResult.Yes)
{
AppendLog("用户取消替换下拉设置。");
return;
}
var current = DropdownOptionsStore.Load();
var updated = (current ?? DropdownOptions.CreateDefault()).Clone();
if (options.DeliveryStatuses != null && options.DeliveryStatuses.Count > 0)
{
updated.DeliveryStatuses = options.DeliveryStatuses.ToList();
}
if (options.ProcessMethods != null && options.ProcessMethods.Count > 0)
{
updated.ProcessMethods = options.ProcessMethods.ToList();
}
if (options.StructuralFeatures != null && options.StructuralFeatures.Count > 0)
{
updated.StructuralFeatures = options.StructuralFeatures.ToList();
}
updated.Normalize();
DropdownOptionsStore.Save(updated);
ReloadDropdownOptions(updated);
AppendLog("已从模板替换下拉设置并保存。");
}
catch (Exception ex)
{
AppendLog($"模板解析/替换失败: {ex.Message}");
Logger.Error("TemplateDropdownOptions", ex);
}
}
private static bool HasAnyOptions(DropdownOptions options)
{
return options != null
&& ((options.DeliveryStatuses != null && options.DeliveryStatuses.Count > 0)
|| (options.ProcessMethods != null && options.ProcessMethods.Count > 0)
|| (options.StructuralFeatures != null && options.StructuralFeatures.Count > 0));
}
private static string BuildOptionsPreview(DropdownOptions options, int maxPerField)
{
return string.Join(
Environment.NewLine,
new[]
{
$"交付状态: {PreviewValues(options?.DeliveryStatuses, maxPerField)}",
$"工艺方法: {PreviewValues(options?.ProcessMethods, maxPerField)}",
$"结构特征: {PreviewValues(options?.StructuralFeatures, maxPerField)}"
});
}
private static string PreviewValues(System.Collections.Generic.IEnumerable<string> values, int max)
{
if (values == null)
{
return "(无)";
}
var arr = values.Where(v => !string.IsNullOrWhiteSpace(v)).Select(v => v.Trim()).ToArray();
if (arr.Length == 0)
{
return "(无)";
}
if (arr.Length <= max)
{
return string.Join(", ", arr);
}
return string.Join(", ", arr.Take(max)) + $" ... (共 {arr.Length} 项)";
}
private static double ParseScaleFactor(string raw)
{
if (string.IsNullOrWhiteSpace(raw))
{
throw new BusinessException("请填写:出图比例 (DrawingScale)");
}
var s = (raw ?? string.Empty).Trim();
s = s.Replace(" ", "").Replace("\u3000", "").Replace("", ":");
var parts = s.Split(':');
if (parts.Length != 2 || !string.Equals(parts[0], "1", StringComparison.OrdinalIgnoreCase))
{
throw new BusinessException("出图比例格式错误,应为 1:n例如 1:5");
}
if (!TryParseDouble(parts[1], out var denom) || denom < 1e-9)
{
throw new BusinessException("出图比例格式错误,应为 1:n例如 1:5");
}
if (denom < 1.0)
{
throw new BusinessException("出图比例不支持放大n 必须 >= 1");
}
return 1.0 / denom;
}
private static bool TryParseDouble(string s, out double value)
{
value = 0;
if (string.IsNullOrWhiteSpace(s))
{
return false;
}
return double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out value)
|| double.TryParse(s, NumberStyles.Float, CultureInfo.CurrentCulture, out value);
}
private void OnGenerateDrawing()
{
try
{
var tplParams = CollectTemplateParams();
if (_selectedTemplate == null || string.IsNullOrWhiteSpace(_selectedTemplate.FilePath))
{
AppendLog("请先选择路径并匹配模板。");
return;
}
if (string.IsNullOrWhiteSpace(_selectedTemplate.LayoutName) && !_selectedModelWindow.HasValue)
{
AppendLog("未匹配图纸,尝试自动匹配...");
OnMatchTemplate();
if (_selectedTemplate == null || (string.IsNullOrWhiteSpace(_selectedTemplate.LayoutName) && !_selectedModelWindow.HasValue))
{
return;
}
}
var templateKey = TemplateKeyBuilder.Build(tplParams);
if (string.IsNullOrWhiteSpace(templateKey))
{
AppendLog("模板参数不完整,无法生成 TemplateKey。");
return;
}
var schemas = TemplateSchemaStore.Load();
var schema = (schemas?.Items ?? Enumerable.Empty<TemplateSchemaDefinition>())
.FirstOrDefault(s => string.Equals(s.TemplateKey, templateKey, StringComparison.OrdinalIgnoreCase));
if (schema == null)
{
AppendLog($"未找到该模板的参数绑定配置TemplateKey={templateKey})。请到【设置→模板参数绑定】中新增/配置。");
return;
}
var catalog = ParamCatalogStore.Load();
CadParamPluging.Common.ParamBag bag;
using (var f = new DrawingParamsForm(catalog, schema))
{
var r = f.ShowDialog(this);
if (r != DialogResult.OK)
{
AppendLog("用户取消填写参数。");
return;
}
bag = f.Result;
}
// Current demo generator uses a rectangle. Size defaults are handled inside DomainFacade.DrawByParams.
// Real templates will use their own generator/parameters.
var drawingParams = new DrawingParams();
DomainFacade.ValidateParameters(tplParams, drawingParams);
var doc = TemplateDrawingService.CreateDocumentFromTemplate(_selectedTemplate);
if (_selectedModelWindow.HasValue)
{
TemplateDrawingService.KeepOnlyModelWindow(doc, _selectedModelWindow.Value);
}
else
{
TemplateDrawingService.KeepOnlyLayout(doc, _selectedTemplate.LayoutName);
}
AppendLog($"已生成图纸窗口,并仅保留图纸: {_selectedSheetName ?? _selectedTemplate.LayoutName}");
using (doc.LockDocument())
using (var ctx = new CadContext(doc))
{
var removed = TemplateDrawingService.RemoveMatchParameterAnnotations(
ctx,
_selectedTemplate.LayoutName,
_selectedModelWindow.HasValue);
if (removed > 0)
{
AppendLog($"已移除模板匹配参数标注文本: {removed} 处");
}
var noteResult = TemplateDrawingService.ApplyNoteTemplate(
ctx,
_selectedTemplate.LayoutName,
_selectedModelWindow.HasValue,
schema,
bag);
if (noteResult != null)
{
if (noteResult.Applied)
{
AppendLog($"附注替换成功(目标={noteResult.TargetKind}, 占位符={noteResult.PlaceholderCountInDwg}");
}
else if (!string.IsNullOrWhiteSpace(noteResult.Message))
{
AppendLog($"附注替换跳过: {noteResult.Message}");
}
}
// 删除模板中原有的图纸图形CAXA图层和尺寸标注保留右上角
var removeResult = TemplateDrawingService.RemoveTemplateOriginalDrawing(ctx);
AppendLog($"已删除原有图形: 红色外框={removeResult.OuterFrameErased}, CAXA图层={removeResult.CaxaLayerErased}, 标注={removeResult.DimensionLayerErased}, 保留右上角={removeResult.DimensionLayerKept}");
// 删除白色线框内“上半部分”的所有内容(保留右上角与下半部分附注/表格)
var upperRemoved = TemplateDrawingService.RemoveWhiteFrameUpperContent(
ctx,
keepBottomRatio: 0.50,
topRightThreshold: 0.70);
if (upperRemoved > 0)
{
AppendLog($"已清理白框上半部内容: {upperRemoved} 处");
}
var scaleFactor = ParseScaleFactor(bag.GetString("DrawingScale"));
// 根据模板参数绘制半剖视图,居中放置于原图纸位置
// 使用特征驱动模式:根据参数存在性动态绘制对应特征
HalfSectionDrawer.Draw(
ctx,
bag,
tplParams.ProjectType, // 交付状态
tplParams.SheetSize, // 结构特征
tplParams.Scale, // 特殊条件(中心冲孔/有圆头等)
tplParams.DrawingType, // 工艺方法(轧制/自由锻)
removeResult.OriginalCenter, // 原图纸中心点
scaleFactor // 缩放比例
);
// 更新标题栏中的比例属性
var scaleUpdated = TemplateDrawingService.UpdateScaleAttribute(
ctx,
_selectedTemplate.LayoutName,
_selectedModelWindow.HasValue,
scaleFactor
);
if (scaleUpdated)
{
AppendLog($"已更新标题栏比例: {(scaleFactor >= 0.9999 ? "1:1" : $"1:{(1/scaleFactor):F1}")}");
}
else
{
AppendLog("未找到标题栏中的'比例'文字,无法更新比例");
}
// 更新标题栏中的检验类别
var inspectionCategory = bag.GetString("InspectionCategory");
if (!string.IsNullOrWhiteSpace(inspectionCategory))
{
var categoryUpdated = TemplateDrawingService.UpdateInspectionCategoryAttribute(
ctx,
_selectedTemplate.LayoutName,
_selectedModelWindow.HasValue,
inspectionCategory
);
if (categoryUpdated)
{
AppendLog($"已更新标题栏检验类别: {inspectionCategory}");
}
else
{
AppendLog("未找到标题栏中的'检验类别'文字,无法更新检验类别");
}
}
ctx.Commit();
try { doc.Editor.Regen(); } catch { }
}
AppendLog("图纸生成完成。");
}
catch (BusinessException bex)
{
AppendLog($"参数错误: {bex.Message}");
}
catch (Exception ex)
{
AppendLog($"生成失败: {ex.Message}");
Logger.Error("GenerateDrawing", ex);
}
}
private void OnSaveDrawing()
{
try
{
var doc = AcadApp.DocumentManager.MdiActiveDocument;
if (doc == null)
{
AppendLog("未找到活动图纸,无法保存。");
return;
}
using (var dialog = new SaveFileDialog
{
Filter = "AutoCAD Drawing (*.dwg)|*.dwg",
FileName = "新图纸.dwg"
})
{
if (dialog.ShowDialog() == DialogResult.OK)
{
doc.Database.SaveAs(dialog.FileName, true, DwgVersion.Current, doc.Database.SecurityParameters);
AppendLog($"图纸已保存到: {dialog.FileName}");
}
}
}
catch (Exception ex)
{
AppendLog($"保存失败: {ex.Message}");
Logger.Error("SaveDrawing", ex);
}
}
private void OnOpenSettings()
{
try
{
var current = DropdownOptionsStore.Load();
using (var form = new SettingsForm(current))
{
if (form.ShowDialog() == DialogResult.OK)
{
DropdownOptionsStore.Save(form.Result);
ReloadDropdownOptions(form.Result);
AppendLog("设置已保存");
}
}
}
catch (Exception ex)
{
AppendLog($"打开设置失败: {ex.Message}");
Logger.Error("OpenSettings", ex);
}
}
private void ReloadDropdownOptions(DropdownOptions options)
{
if (options == null)
{
return;
}
ResetComboBoxItems(_cbProjectType, options.DeliveryStatuses);
ResetComboBoxItems(_cbDrawingType, options.ProcessMethods);
ResetComboBoxItems(_cbSheetSize, options.StructuralFeatures);
ResetComboBoxItems(_cbScale, options.SpecialConditions);
}
private TemplateParams CollectTemplateParams()
{
var specialCondition = _cbScale.Text?.Trim();
if (string.Equals(specialCondition, "无", StringComparison.OrdinalIgnoreCase))
{
specialCondition = null;
}
return new TemplateParams
{
ProjectType = _cbProjectType.Text?.Trim(),
DrawingType = _cbDrawingType.Text?.Trim(),
SheetSize = _cbSheetSize.Text?.Trim(),
Scale = specialCondition
};
}
private static ComboBox CreateComboBox(System.Collections.Generic.IEnumerable<string> items)
{
var cb = new ComboBox
{
DropDownStyle = ComboBoxStyle.DropDownList,
Width = 160
};
var arr = (items ?? Enumerable.Empty<string>()).Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim()).ToArray();
if (arr.Length > 0)
{
cb.Items.AddRange(arr);
}
if (cb.Items.Count > 0)
{
cb.SelectedIndex = 0;
}
return cb;
}
private static void ResetComboBoxItems(ComboBox cb, System.Collections.Generic.IEnumerable<string> items)
{
if (cb == null)
{
return;
}
var previous = cb.Text;
var arr = (items ?? Enumerable.Empty<string>()).Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim()).ToArray();
cb.BeginUpdate();
try
{
cb.Items.Clear();
if (arr.Length > 0)
{
cb.Items.AddRange(arr);
var idx = Array.FindIndex(arr, v => string.Equals(v, previous, StringComparison.OrdinalIgnoreCase));
cb.SelectedIndex = idx >= 0 ? idx : 0;
}
}
finally
{
cb.EndUpdate();
}
}
private void OnTestDraw()
{
try
{
// ==========================================
// 测试参数构造 - 演示特征驱动模式
// ==========================================
var bag = new ParamBag();
// 锻件参数 (调整为细长型,符合参考图比例)
bag.Set("OuterDiameter1", "160");
bag.Set("OuterDiameter1TolPlus", "2");
bag.Set("OuterDiameter1TolMinus", "-2");
bag.Set("InnerDiameter2", "100");
bag.Set("InnerDiameter2TolPlus", "3");
bag.Set("InnerDiameter2TolMinus", "-3");
bag.Set("Height1", "400");
bag.Set("Height1TolPlus", "5");
bag.Set("Height1TolMinus", "-5");
// 零件参数 (车加工)
bag.Set("OuterDiameter1Prime", "150");
bag.Set("InnerDiameter2Prime", "110");
bag.Set("Height1Prime", "380");
// 可选特征参数 - 根据模板绑定动态显示
bag.Set("UnspecifiedFilletRadiusMax", "6"); // 未注圆角半径R≤6
bag.Set("MinWallThickness", "25"); // 最小壁厚T
// bag.Set("InnerRadiusMax", "8"); // 内径半径R≤8中心冲孔时用
var doc = AcadApp.DocumentManager.MdiActiveDocument;
if (doc == null)
{
AppendLog("未找到活动图纸。");
return;
}
using (doc.LockDocument())
using (var ctx = new CadContext(doc))
{
// 调用特征驱动绘图引擎
// 会根据bag中存在的参数自动绘制对应特征
HalfSectionDrawer.Draw(
ctx,
bag,
"车加工", // 交付状态
"环形", // 结构特征
null // 特殊条件(可选:中心冲孔/有圆头等)
);
ctx.Commit();
AppendLog($"测试绘制完成 (特征驱动模式)");
AppendLog($"已绘制特征: 外轮廓、内孔(虚线)、公差标注、未注圆角、壁厚、零件(填充)");
}
// Zoom Extents
doc.SendStringToExecute("._ZOOM _E ", true, false, false);
}
catch (Exception ex)
{
AppendLog($"测试绘制失败: {ex.Message}");
Logger.Error("TestDraw", ex);
}
}
private void AppendLog(string message)
{
var time = DateTime.Now.ToString("HH:mm:ss");
_txtLog.AppendText($"[{time}] {message}{Environment.NewLine}");
}
}
}