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 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 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 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 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()) .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 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( ctx, bag, tplParams.ProjectType, // 交付状态 tplParams.SheetSize, // 结构特征 tplParams.Scale, // 特殊条件(中心冲孔/有圆头等) 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("未找到标题栏中的'比例'文字,无法更新比例"); } ctx.Commit(); } 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 items) { var cb = new ComboBox { DropDownStyle = ComboBoxStyle.DropDownList, Width = 160 }; var arr = (items ?? Enumerable.Empty()).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 items) { if (cb == null) { return; } var previous = cb.Text; var arr = (items ?? Enumerable.Empty()).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}"); } } }