diff --git a/Cad/TemplateLayoutAnnotationExtractor.cs b/Cad/TemplateLayoutAnnotationExtractor.cs index c58822b..93e9b50 100644 --- a/Cad/TemplateLayoutAnnotationExtractor.cs +++ b/Cad/TemplateLayoutAnnotationExtractor.cs @@ -13,19 +13,21 @@ namespace CadParamPluging.Cad public List DeliveryStatuses { get; set; } public List ProcessMethods { get; set; } public List StructuralFeatures { get; set; } + public List SpecialConditions { get; set; } public LayoutAnnotation() { DeliveryStatuses = new List(); ProcessMethods = new List(); StructuralFeatures = new List(); + SpecialConditions = new List(); } } public static class TemplateLayoutAnnotationExtractor { private static readonly Regex FieldRegex = new Regex( - @"^\s*(交付状态|工艺方法|结构特征)\s*[::]\s*(.+?)\s*$", + @"^\s*(交付状态|工艺方法|结构特征|特殊条件)\s*[::]\s*(.+?)\s*$", RegexOptions.Compiled); private static readonly Regex MTextFormatRegex = new Regex(@"\\[A-Za-z]+[^;]*;", RegexOptions.Compiled); @@ -101,20 +103,14 @@ namespace CadParamPluging.Cad { if (ent is DBText text) { - foreach (var line in SplitLines(text.TextString)) - { - TryParseLine(line, ann); - } + ParseTextBlock(text.TextString, ann); return; } if (ent is MText mt) { var plain = SimplifyMText(mt.Contents); - foreach (var line in SplitLines(plain)) - { - TryParseLine(line, ann); - } + ParseTextBlock(plain, ann); return; } @@ -128,10 +124,7 @@ namespace CadParamPluging.Cad continue; } - foreach (var line in SplitLines(att.TextString)) - { - TryParseLine(line, ann); - } + ParseTextBlock(att.TextString, ann); } // 说明文字可能在块定义内部(非属性),需要递归扫描块内容。 @@ -159,6 +152,42 @@ namespace CadParamPluging.Cad } } + private static void ParseTextBlock(string text, LayoutAnnotation ann) + { + if (ann == null) + { + return; + } + + var lines = SplitLines(text).ToList(); + if (lines.Count == 0) + { + return; + } + + var hasAnyField = false; + foreach (var line in lines) + { + if (TryParseFieldLine(line, ann)) + { + hasAnyField = true; + } + } + + if (!hasAnyField) + { + return; + } + + foreach (var line in lines) + { + if (IsSpecialConditionValueLine(line)) + { + ann.SpecialConditions.Add(NormalizeValue(line)); + } + } + } + private static IEnumerable SplitLines(string text) { if (string.IsNullOrWhiteSpace(text)) @@ -191,24 +220,24 @@ namespace CadParamPluging.Cad return s; } - private static void TryParseLine(string line, LayoutAnnotation ann) + private static bool TryParseFieldLine(string line, LayoutAnnotation ann) { if (string.IsNullOrWhiteSpace(line)) { - return; + return false; } var m = FieldRegex.Match(line); if (!m.Success) { - return; + return false; } var key = m.Groups[1].Value; var val = (m.Groups[2].Value ?? string.Empty).Trim(); if (val.Length == 0) { - return; + return false; } val = NormalizeValue(val); @@ -224,7 +253,28 @@ namespace CadParamPluging.Cad case "结构特征": ann.StructuralFeatures.Add(val); break; + case "特殊条件": + ann.SpecialConditions.Add(val); + break; } + + return true; + } + + private static bool IsSpecialConditionValueLine(string line) + { + if (string.IsNullOrWhiteSpace(line)) + { + return false; + } + + // 特殊条件“最后一行”为不带冒号的单独值,且必须在同一文本块内已出现过字段行。 + if (FieldRegex.IsMatch(line)) + { + return false; + } + + return line.IndexOf(':') < 0 && line.IndexOf(':') < 0; } private static void Normalize(LayoutAnnotation ann) @@ -232,6 +282,7 @@ namespace CadParamPluging.Cad ann.DeliveryStatuses = NormalizeList(ann.DeliveryStatuses); ann.ProcessMethods = NormalizeList(ann.ProcessMethods); ann.StructuralFeatures = NormalizeList(ann.StructuralFeatures); + ann.SpecialConditions = NormalizeList(ann.SpecialConditions); } private static string NormalizeValue(string s) @@ -277,7 +328,8 @@ namespace CadParamPluging.Cad return ann != null && ((ann.DeliveryStatuses != null && ann.DeliveryStatuses.Count > 0) || (ann.ProcessMethods != null && ann.ProcessMethods.Count > 0) - || (ann.StructuralFeatures != null && ann.StructuralFeatures.Count > 0)); + || (ann.StructuralFeatures != null && ann.StructuralFeatures.Count > 0) + || (ann.SpecialConditions != null && ann.SpecialConditions.Count > 0)); } } } diff --git a/Cad/TemplateModelSheetExtractor.cs b/Cad/TemplateModelSheetExtractor.cs index 5093a06..2c98d56 100644 --- a/Cad/TemplateModelSheetExtractor.cs +++ b/Cad/TemplateModelSheetExtractor.cs @@ -14,6 +14,7 @@ namespace CadParamPluging.Cad public List DeliveryStatuses { get; set; } public List ProcessMethods { get; set; } public List StructuralFeatures { get; set; } + public List SpecialConditions { get; set; } public Extents3d Window { get; set; } public ModelSheetCandidate() @@ -21,13 +22,14 @@ namespace CadParamPluging.Cad DeliveryStatuses = new List(); ProcessMethods = new List(); StructuralFeatures = new List(); + SpecialConditions = new List(); } } public static class TemplateModelSheetExtractor { private static readonly Regex FieldRegex = new Regex( - @"^\s*(交付状态|工艺方法|结构特征)\s*[::]\s*(.+?)\s*$", + @"^\s*(交付状态|工艺方法|结构特征|特殊条件)\s*[::]\s*(.+?)\s*$", RegexOptions.Compiled); private static readonly Regex MTextFormatRegex = new Regex(@"\\[A-Za-z]+[^;]*;", RegexOptions.Compiled); @@ -229,23 +231,81 @@ namespace CadParamPluging.Cad private static void TryCollectText(string raw, Point3d pos, List matches) { - foreach (var line in SplitLines(raw)) + if (matches == null) { - var m = FieldRegex.Match(line); - if (!m.Success) - { - continue; - } - - var field = m.Groups[1].Value; - var value = NormalizeValue(m.Groups[2].Value); - if (value.Length == 0) - { - continue; - } - - matches.Add(new TextMatch { Field = field, Value = value, Pos = pos }); + return; } + + var lines = SplitLines(raw).ToList(); + if (lines.Count == 0) + { + return; + } + + var hasAnyField = false; + foreach (var line in lines) + { + if (TryParseFieldLine(line, out var field, out var value)) + { + hasAnyField = true; + matches.Add(new TextMatch { Field = field, Value = value, Pos = pos }); + } + } + + if (!hasAnyField) + { + return; + } + + foreach (var line in lines) + { + if (IsSpecialConditionValueLine(line)) + { + var v = NormalizeValue(line); + if (v.Length == 0) + { + continue; + } + + matches.Add(new TextMatch { Field = "特殊条件", Value = v, Pos = pos }); + } + } + } + + private static bool TryParseFieldLine(string line, out string field, out string value) + { + field = null; + value = null; + + if (string.IsNullOrWhiteSpace(line)) + { + return false; + } + + var m = FieldRegex.Match(line); + if (!m.Success) + { + return false; + } + + field = m.Groups[1].Value; + value = NormalizeValue(m.Groups[2].Value); + return !string.IsNullOrWhiteSpace(field) && !string.IsNullOrWhiteSpace(value); + } + + private static bool IsSpecialConditionValueLine(string line) + { + if (string.IsNullOrWhiteSpace(line)) + { + return false; + } + + if (FieldRegex.IsMatch(line)) + { + return false; + } + + return line.IndexOf(':') < 0 && line.IndexOf(':') < 0; } private static IEnumerable SplitLines(string text) @@ -307,6 +367,7 @@ namespace CadParamPluging.Cad var delivery = cluster.Where(m => m.Field == "交付状态").Select(m => m.Value).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); var process = cluster.Where(m => m.Field == "工艺方法").Select(m => m.Value).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); var structural = cluster.Where(m => m.Field == "结构特征").Select(m => m.Value).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); + var special = cluster.Where(m => m.Field == "特殊条件").Select(m => m.Value).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); if (delivery.Count == 0 || process.Count == 0 || structural.Count == 0) { @@ -325,6 +386,7 @@ namespace CadParamPluging.Cad DeliveryStatuses = delivery, ProcessMethods = process, StructuralFeatures = structural, + SpecialConditions = special, Window = window }); diff --git a/UI/ParamDrawingPanel.cs b/UI/ParamDrawingPanel.cs index 324fb00..1a3ac6c 100644 --- a/UI/ParamDrawingPanel.cs +++ b/UI/ParamDrawingPanel.cs @@ -200,81 +200,69 @@ namespace CadParamPluging.UI { try { - if (_selectedTemplate == null || string.IsNullOrWhiteSpace(_selectedTemplate.FilePath)) + if (_cadFilePaths == null || _cadFilePaths.Length == 0) { - AppendLog("请先选择模板文件。"); + AppendLog("请先选择路径。"); return; } - AppendLog("开始匹配图纸..."); + AppendLog("开始匹配模板..."); var tplParams = CollectTemplateParams(); - // 1) 优先按 Layout 匹配(适用于多布局模板) - var layoutCandidates = TemplateLayoutAnnotationExtractor.ExtractPerLayout(_selectedTemplate.FilePath); - var layoutMatches = layoutCandidates.Where(c => LayoutMatches(c, tplParams)).ToList(); - if (layoutMatches.Count > 0) + foreach (var cadPath in _cadFilePaths) { - LayoutAnnotation selectedLayout; - if (layoutMatches.Count == 1) + if (string.IsNullOrWhiteSpace(cadPath) || !File.Exists(cadPath)) { - selectedLayout = layoutMatches[0]; + continue; } - else + + // 1) 优先按 Layout(PaperSpace) 匹配 + var layoutCandidates = TemplateLayoutAnnotationExtractor.ExtractPerLayout(cadPath); + var layoutMatch = layoutCandidates.FirstOrDefault(c => LayoutMatches(c, tplParams)); + if (layoutMatch != null) { - if (!LayoutSelectForm.TrySelect(this, layoutMatches, out selectedLayout)) + _selectedTemplate = new TemplateInfo { - AppendLog("用户取消选择图纸。"); - return; - } + 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; } - _selectedTemplate.LayoutName = selectedLayout.LayoutName; - _selectedModelWindow = null; - _selectedSheetName = selectedLayout.LayoutName; - _lblTemplateInfo.Text = $"{_selectedTemplate.FilePath} | {selectedLayout.LayoutName}"; - AppendLog($"已匹配图纸: {selectedLayout.LayoutName}"); - return; - } - - // 2) 如果 Layout 为空或未匹配,按 ModelSpace 多张图纸模式匹配 - var modelCandidates = TemplateModelSheetExtractor.ExtractCandidates(_selectedTemplate.FilePath); - var modelMatches = modelCandidates.Where(c => ModelMatches(c, tplParams)).ToList(); - - if (modelMatches.Count == 0) - { - _selectedTemplate.LayoutName = null; - _selectedModelWindow = null; - _selectedSheetName = null; - _lblTemplateInfo.Text = _selectedTemplate.FilePath; - AppendLog("未找到匹配图纸。"); - AppendLog($"候选图纸数量: {modelCandidates.Count}"); - foreach (var c in modelCandidates.Take(10)) + // 2) Layout 未命中时,尝试按 ModelSpace 窗口候选匹配 + var modelCandidates = TemplateModelSheetExtractor.ExtractCandidates(cadPath); + var modelMatch = modelCandidates.FirstOrDefault(c => ModelMatches(c, tplParams)); + if (modelMatch != null) { - AppendLog($"候选: {c.Name} | 交付状态={Preview(c.DeliveryStatuses)} | 工艺方法={Preview(c.ProcessMethods)} | 结构特征={Preview(c.StructuralFeatures)}"); - } - return; - } + _selectedTemplate = new TemplateInfo + { + Name = Path.GetFileName(cadPath), + FilePath = cadPath + }; - ModelSheetCandidate selectedModel; - if (modelMatches.Count == 1) - { - selectedModel = modelMatches[0]; - } - else - { - if (!ModelSheetSelectForm.TrySelect(this, modelMatches, out selectedModel)) - { - AppendLog("用户取消选择图纸。"); + _selectedTemplate.LayoutName = null; + _selectedModelWindow = modelMatch.Window; + _selectedSheetName = modelMatch.Name; + + _lblTemplateInfo.Text = $"{cadPath} | {modelMatch.Name}"; + AppendLog($"匹配成功: {Path.GetFileName(cadPath)} | Model: {modelMatch.Name}"); return; } } - _selectedTemplate.LayoutName = null; - _selectedModelWindow = selectedModel.Window; - _selectedSheetName = selectedModel.Name; - _lblTemplateInfo.Text = $"{_selectedTemplate.FilePath} | {selectedModel.Name}"; - AppendLog($"已匹配图纸: {selectedModel.Name}"); + _selectedTemplate = null; + _selectedModelWindow = null; + _selectedSheetName = null; + _lblTemplateInfo.Text = "未匹配模板"; + AppendLog("未找到匹配模板。"); } catch (BusinessException bex) { @@ -310,7 +298,8 @@ namespace CadParamPluging.UI return ContainsIgnoreCase(ann.DeliveryStatuses, tplParams.ProjectType) && ContainsIgnoreCase(ann.ProcessMethods, tplParams.DrawingType) - && ContainsIgnoreCase(ann.StructuralFeatures, tplParams.SheetSize); + && ContainsIgnoreCase(ann.StructuralFeatures, tplParams.SheetSize) + && ContainsIgnoreCase(ann.SpecialConditions, tplParams.Scale); } private static bool ContainsIgnoreCase(System.Collections.Generic.IEnumerable values, string expected) @@ -361,7 +350,8 @@ namespace CadParamPluging.UI return ContainsIgnoreCase(ann.DeliveryStatuses, tplParams.ProjectType) && ContainsIgnoreCase(ann.ProcessMethods, tplParams.DrawingType) - && ContainsIgnoreCase(ann.StructuralFeatures, tplParams.SheetSize); + && ContainsIgnoreCase(ann.StructuralFeatures, tplParams.SheetSize) + && ContainsIgnoreCase(ann.SpecialConditions, tplParams.Scale); } private void OnSelectTemplate() @@ -538,7 +528,7 @@ namespace CadParamPluging.UI if (_selectedTemplate == null || string.IsNullOrWhiteSpace(_selectedTemplate.FilePath)) { - AppendLog("请先选择模板文件。"); + AppendLog("请先选择路径并匹配模板。"); return; }