点击匹配后可以匹配到具体的cad文件

This commit is contained in:
sladro 2025-12-15 18:34:47 +08:00
parent 2d5fe10812
commit ea9e86f1ea
3 changed files with 196 additions and 92 deletions

View File

@ -13,19 +13,21 @@ namespace CadParamPluging.Cad
public List<string> DeliveryStatuses { get; set; } public List<string> DeliveryStatuses { get; set; }
public List<string> ProcessMethods { get; set; } public List<string> ProcessMethods { get; set; }
public List<string> StructuralFeatures { get; set; } public List<string> StructuralFeatures { get; set; }
public List<string> SpecialConditions { get; set; }
public LayoutAnnotation() public LayoutAnnotation()
{ {
DeliveryStatuses = new List<string>(); DeliveryStatuses = new List<string>();
ProcessMethods = new List<string>(); ProcessMethods = new List<string>();
StructuralFeatures = new List<string>(); StructuralFeatures = new List<string>();
SpecialConditions = new List<string>();
} }
} }
public static class TemplateLayoutAnnotationExtractor public static class TemplateLayoutAnnotationExtractor
{ {
private static readonly Regex FieldRegex = new Regex( private static readonly Regex FieldRegex = new Regex(
@"^\s*(交付状态|工艺方法|结构特征)\s*[:]\s*(.+?)\s*$", @"^\s*(交付状态|工艺方法|结构特征|特殊条件)\s*[:]\s*(.+?)\s*$",
RegexOptions.Compiled); RegexOptions.Compiled);
private static readonly Regex MTextFormatRegex = new Regex(@"\\[A-Za-z]+[^;]*;", 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) if (ent is DBText text)
{ {
foreach (var line in SplitLines(text.TextString)) ParseTextBlock(text.TextString, ann);
{
TryParseLine(line, ann);
}
return; return;
} }
if (ent is MText mt) if (ent is MText mt)
{ {
var plain = SimplifyMText(mt.Contents); var plain = SimplifyMText(mt.Contents);
foreach (var line in SplitLines(plain)) ParseTextBlock(plain, ann);
{
TryParseLine(line, ann);
}
return; return;
} }
@ -128,10 +124,7 @@ namespace CadParamPluging.Cad
continue; continue;
} }
foreach (var line in SplitLines(att.TextString)) ParseTextBlock(att.TextString, ann);
{
TryParseLine(line, 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<string> SplitLines(string text) private static IEnumerable<string> SplitLines(string text)
{ {
if (string.IsNullOrWhiteSpace(text)) if (string.IsNullOrWhiteSpace(text))
@ -191,24 +220,24 @@ namespace CadParamPluging.Cad
return s; return s;
} }
private static void TryParseLine(string line, LayoutAnnotation ann) private static bool TryParseFieldLine(string line, LayoutAnnotation ann)
{ {
if (string.IsNullOrWhiteSpace(line)) if (string.IsNullOrWhiteSpace(line))
{ {
return; return false;
} }
var m = FieldRegex.Match(line); var m = FieldRegex.Match(line);
if (!m.Success) if (!m.Success)
{ {
return; return false;
} }
var key = m.Groups[1].Value; var key = m.Groups[1].Value;
var val = (m.Groups[2].Value ?? string.Empty).Trim(); var val = (m.Groups[2].Value ?? string.Empty).Trim();
if (val.Length == 0) if (val.Length == 0)
{ {
return; return false;
} }
val = NormalizeValue(val); val = NormalizeValue(val);
@ -224,7 +253,28 @@ namespace CadParamPluging.Cad
case "结构特征": case "结构特征":
ann.StructuralFeatures.Add(val); ann.StructuralFeatures.Add(val);
break; 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) private static void Normalize(LayoutAnnotation ann)
@ -232,6 +282,7 @@ namespace CadParamPluging.Cad
ann.DeliveryStatuses = NormalizeList(ann.DeliveryStatuses); ann.DeliveryStatuses = NormalizeList(ann.DeliveryStatuses);
ann.ProcessMethods = NormalizeList(ann.ProcessMethods); ann.ProcessMethods = NormalizeList(ann.ProcessMethods);
ann.StructuralFeatures = NormalizeList(ann.StructuralFeatures); ann.StructuralFeatures = NormalizeList(ann.StructuralFeatures);
ann.SpecialConditions = NormalizeList(ann.SpecialConditions);
} }
private static string NormalizeValue(string s) private static string NormalizeValue(string s)
@ -277,7 +328,8 @@ namespace CadParamPluging.Cad
return ann != null return ann != null
&& ((ann.DeliveryStatuses != null && ann.DeliveryStatuses.Count > 0) && ((ann.DeliveryStatuses != null && ann.DeliveryStatuses.Count > 0)
|| (ann.ProcessMethods != null && ann.ProcessMethods.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));
} }
} }
} }

View File

@ -14,6 +14,7 @@ namespace CadParamPluging.Cad
public List<string> DeliveryStatuses { get; set; } public List<string> DeliveryStatuses { get; set; }
public List<string> ProcessMethods { get; set; } public List<string> ProcessMethods { get; set; }
public List<string> StructuralFeatures { get; set; } public List<string> StructuralFeatures { get; set; }
public List<string> SpecialConditions { get; set; }
public Extents3d Window { get; set; } public Extents3d Window { get; set; }
public ModelSheetCandidate() public ModelSheetCandidate()
@ -21,13 +22,14 @@ namespace CadParamPluging.Cad
DeliveryStatuses = new List<string>(); DeliveryStatuses = new List<string>();
ProcessMethods = new List<string>(); ProcessMethods = new List<string>();
StructuralFeatures = new List<string>(); StructuralFeatures = new List<string>();
SpecialConditions = new List<string>();
} }
} }
public static class TemplateModelSheetExtractor public static class TemplateModelSheetExtractor
{ {
private static readonly Regex FieldRegex = new Regex( private static readonly Regex FieldRegex = new Regex(
@"^\s*(交付状态|工艺方法|结构特征)\s*[:]\s*(.+?)\s*$", @"^\s*(交付状态|工艺方法|结构特征|特殊条件)\s*[:]\s*(.+?)\s*$",
RegexOptions.Compiled); RegexOptions.Compiled);
private static readonly Regex MTextFormatRegex = new Regex(@"\\[A-Za-z]+[^;]*;", 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<TextMatch> matches) private static void TryCollectText(string raw, Point3d pos, List<TextMatch> matches)
{ {
foreach (var line in SplitLines(raw)) if (matches == null)
{ {
var m = FieldRegex.Match(line); return;
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 });
} }
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<string> SplitLines(string text) private static IEnumerable<string> 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 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 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 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) if (delivery.Count == 0 || process.Count == 0 || structural.Count == 0)
{ {
@ -325,6 +386,7 @@ namespace CadParamPluging.Cad
DeliveryStatuses = delivery, DeliveryStatuses = delivery,
ProcessMethods = process, ProcessMethods = process,
StructuralFeatures = structural, StructuralFeatures = structural,
SpecialConditions = special,
Window = window Window = window
}); });

View File

@ -200,81 +200,69 @@ namespace CadParamPluging.UI
{ {
try try
{ {
if (_selectedTemplate == null || string.IsNullOrWhiteSpace(_selectedTemplate.FilePath)) if (_cadFilePaths == null || _cadFilePaths.Length == 0)
{ {
AppendLog("请先选择模板文件。"); AppendLog("请先选择路径。");
return; return;
} }
AppendLog("开始匹配图纸..."); AppendLog("开始匹配模板...");
var tplParams = CollectTemplateParams(); 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 (string.IsNullOrWhiteSpace(cadPath) || !File.Exists(cadPath))
if (layoutMatches.Count == 1)
{ {
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("用户取消选择图纸。"); Name = Path.GetFileName(cadPath),
return; 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; // 2) Layout 未命中时,尝试按 ModelSpace 窗口候选匹配
_selectedModelWindow = null; var modelCandidates = TemplateModelSheetExtractor.ExtractCandidates(cadPath);
_selectedSheetName = selectedLayout.LayoutName; var modelMatch = modelCandidates.FirstOrDefault(c => ModelMatches(c, tplParams));
_lblTemplateInfo.Text = $"{_selectedTemplate.FilePath} | {selectedLayout.LayoutName}"; if (modelMatch != null)
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))
{ {
AppendLog($"候选: {c.Name} | 交付状态={Preview(c.DeliveryStatuses)} | 工艺方法={Preview(c.ProcessMethods)} | 结构特征={Preview(c.StructuralFeatures)}"); _selectedTemplate = new TemplateInfo
} {
return; Name = Path.GetFileName(cadPath),
} FilePath = cadPath
};
ModelSheetCandidate selectedModel; _selectedTemplate.LayoutName = null;
if (modelMatches.Count == 1) _selectedModelWindow = modelMatch.Window;
{ _selectedSheetName = modelMatch.Name;
selectedModel = modelMatches[0];
} _lblTemplateInfo.Text = $"{cadPath} | {modelMatch.Name}";
else AppendLog($"匹配成功: {Path.GetFileName(cadPath)} | Model: {modelMatch.Name}");
{
if (!ModelSheetSelectForm.TrySelect(this, modelMatches, out selectedModel))
{
AppendLog("用户取消选择图纸。");
return; return;
} }
} }
_selectedTemplate.LayoutName = null; _selectedTemplate = null;
_selectedModelWindow = selectedModel.Window; _selectedModelWindow = null;
_selectedSheetName = selectedModel.Name; _selectedSheetName = null;
_lblTemplateInfo.Text = $"{_selectedTemplate.FilePath} | {selectedModel.Name}"; _lblTemplateInfo.Text = "未匹配模板";
AppendLog($"已匹配图纸: {selectedModel.Name}"); AppendLog("未找到匹配模板。");
} }
catch (BusinessException bex) catch (BusinessException bex)
{ {
@ -310,7 +298,8 @@ namespace CadParamPluging.UI
return ContainsIgnoreCase(ann.DeliveryStatuses, tplParams.ProjectType) return ContainsIgnoreCase(ann.DeliveryStatuses, tplParams.ProjectType)
&& ContainsIgnoreCase(ann.ProcessMethods, tplParams.DrawingType) && 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<string> values, string expected) private static bool ContainsIgnoreCase(System.Collections.Generic.IEnumerable<string> values, string expected)
@ -361,7 +350,8 @@ namespace CadParamPluging.UI
return ContainsIgnoreCase(ann.DeliveryStatuses, tplParams.ProjectType) return ContainsIgnoreCase(ann.DeliveryStatuses, tplParams.ProjectType)
&& ContainsIgnoreCase(ann.ProcessMethods, tplParams.DrawingType) && ContainsIgnoreCase(ann.ProcessMethods, tplParams.DrawingType)
&& ContainsIgnoreCase(ann.StructuralFeatures, tplParams.SheetSize); && ContainsIgnoreCase(ann.StructuralFeatures, tplParams.SheetSize)
&& ContainsIgnoreCase(ann.SpecialConditions, tplParams.Scale);
} }
private void OnSelectTemplate() private void OnSelectTemplate()
@ -538,7 +528,7 @@ namespace CadParamPluging.UI
if (_selectedTemplate == null || string.IsNullOrWhiteSpace(_selectedTemplate.FilePath)) if (_selectedTemplate == null || string.IsNullOrWhiteSpace(_selectedTemplate.FilePath))
{ {
AppendLog("请先选择模板文件。"); AppendLog("请先选择路径并匹配模板。");
return; return;
} }