1607 lines
61 KiB
C#
1607 lines
61 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Collections.ObjectModel;
|
||
using System.ComponentModel;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Runtime.CompilerServices;
|
||
using System.Text.RegularExpressions;
|
||
using System.Windows;
|
||
using DrillTools.Integration;
|
||
|
||
namespace DrillTools
|
||
{
|
||
/// <summary>
|
||
/// 主窗口视图模型
|
||
/// </summary>
|
||
public class MainWindowViewModel : INotifyPropertyChanged
|
||
{
|
||
private ObservableCollection<ToolItem> _tools = new();
|
||
private ToolItem? _selectedTool;
|
||
private string _drillTapeContent = string.Empty;
|
||
private bool _canMoveUp;
|
||
private bool _canMoveDown;
|
||
private string _originalFilePath = string.Empty;
|
||
|
||
/// <summary>
|
||
/// 刀具列表
|
||
/// </summary>
|
||
public ObservableCollection<ToolItem> Tools
|
||
{
|
||
get => _tools;
|
||
set => SetProperty(ref _tools, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 选中的刀具
|
||
/// </summary>
|
||
public ToolItem? SelectedTool
|
||
{
|
||
get => _selectedTool;
|
||
set
|
||
{
|
||
if (SetProperty(ref _selectedTool, value))
|
||
{
|
||
UpdateMoveButtonsState();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 钻带内容
|
||
/// </summary>
|
||
public string DrillTapeContent
|
||
{
|
||
get => _drillTapeContent;
|
||
set => SetProperty(ref _drillTapeContent, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 是否可以上移
|
||
/// </summary>
|
||
public bool CanMoveUp
|
||
{
|
||
get => _canMoveUp;
|
||
set => SetProperty(ref _canMoveUp, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 是否可以下移
|
||
/// </summary>
|
||
public bool CanMoveDown
|
||
{
|
||
get => _canMoveDown;
|
||
set => SetProperty(ref _canMoveDown, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 原始文件路径
|
||
/// </summary>
|
||
public string OriginalFilePath
|
||
{
|
||
get => _originalFilePath;
|
||
set
|
||
{
|
||
if (SetProperty(ref _originalFilePath, value))
|
||
{
|
||
// 当原始文件路径改变时,通知 HasOriginalFile 属性也已更改
|
||
OnPropertyChanged(nameof(HasOriginalFile));
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 是否有原始文件
|
||
/// </summary>
|
||
public bool HasOriginalFile => !string.IsNullOrEmpty(OriginalFilePath);
|
||
|
||
/// <summary>
|
||
/// 从钻带内容加载刀具信息
|
||
/// </summary>
|
||
/// <param name="drillTapeContent">钻带内容</param>
|
||
public void LoadToolsFromDrillTape(string drillTapeContent)
|
||
{
|
||
DrillTapeContent = drillTapeContent;
|
||
Tools.Clear();
|
||
|
||
try
|
||
{
|
||
// 使用现有的 DrillTapeProcessor 处理钻带数据
|
||
var result = DrillTapeProcessor.ProcessDrillTape(drillTapeContent);
|
||
|
||
if (result.Success)
|
||
{
|
||
foreach (var toolResult in result.ToolResults)
|
||
{
|
||
var toolItem = new ToolItem
|
||
{
|
||
ToolNumber = toolResult.ToolNumber,
|
||
Diameter = toolResult.Diameter,
|
||
// 孔数相关属性已移除
|
||
// RegularHoles = toolResult.RegularHoles;
|
||
// SlotHoles = toolResult.SlotHoles;
|
||
// TotalHoles = toolResult.TotalHoles;
|
||
ToolType = toolResult.ToolType,
|
||
ToolSuffixType = toolResult.ToolSuffixType,
|
||
ToolCategory = toolResult.ToolCategory,
|
||
HoleLocations = toolResult.Locations ?? new List<string>()
|
||
};
|
||
|
||
// 如果是机台码,使用DrillTapeProcessor已经解析出的机台码信息
|
||
if (toolResult.ToolType == ToolType.MachineCode)
|
||
{
|
||
toolItem.MachineCodeCommand = toolResult.MachineCodeCommand;
|
||
toolItem.MachineCodeType = toolResult.MachineCodeType;
|
||
|
||
// 添加日志验证机台码信息传递
|
||
System.Diagnostics.Debug.WriteLine($"[机台码传递] T{toolResult.ToolNumber:D2}: 命令={toolItem.MachineCodeCommand}, 类型={toolItem.MachineCodeType}");
|
||
|
||
// 如果 toolResult.Locations 已经包含坐标数据,则使用它
|
||
// 否则从原始钻带内容中提取坐标行
|
||
if (toolItem.HoleLocations == null || toolItem.HoleLocations.Count == 0)
|
||
{
|
||
// 从钻带内容中提取机台码坐标行
|
||
var toolPattern = $@"%.+?T{toolResult.ToolNumber:D2}(.*?)(?=T\d{{2}}|M30)";
|
||
var match = System.Text.RegularExpressions.Regex.Match(DrillTapeContent, toolPattern, System.Text.RegularExpressions.RegexOptions.Singleline);
|
||
|
||
if (match.Success)
|
||
{
|
||
string holeSection = match.Groups[1].Value;
|
||
|
||
// 查找机台码坐标行
|
||
var coordinatePattern = @"X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)";
|
||
var coordinateMatches = System.Text.RegularExpressions.Regex.Matches(holeSection, coordinatePattern);
|
||
|
||
toolItem.HoleLocations = new List<string>();
|
||
foreach (Match coordMatch in coordinateMatches)
|
||
{
|
||
toolItem.HoleLocations.Add(coordMatch.Value);
|
||
}
|
||
|
||
System.Diagnostics.Debug.WriteLine($"[机台码坐标] T{toolResult.ToolNumber:D2}: 找到{toolItem.HoleLocations.Count}个坐标");
|
||
}
|
||
}
|
||
}
|
||
|
||
Tools.Add(toolItem);
|
||
}
|
||
|
||
// 更新按钮状态
|
||
UpdateMoveButtonsState();
|
||
}
|
||
else
|
||
{
|
||
System.Windows.MessageBox.Show($"解析钻带失败: {result.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Windows.MessageBox.Show($"解析钻带时发生异常: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重新排序刀具
|
||
/// </summary>
|
||
/// <param name="oldIndex">原索引</param>
|
||
/// <param name="newIndex">新索引</param>
|
||
public void ReorderTools(int oldIndex, int newIndex)
|
||
{
|
||
if (oldIndex < 0 || oldIndex >= Tools.Count || newIndex < 0 || newIndex >= Tools.Count)
|
||
return;
|
||
|
||
var tool = Tools[oldIndex];
|
||
|
||
// 检查是否是机台码刀具,如果是则不允许移动
|
||
if (tool.ToolType == ToolType.MachineCode)
|
||
{
|
||
System.Windows.MessageBox.Show("机台码刀具不允许移动位置", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||
return;
|
||
}
|
||
|
||
// 检查目标位置是否是机台码刀具
|
||
var targetTool = Tools[newIndex];
|
||
if (targetTool.ToolType == ToolType.MachineCode)
|
||
{
|
||
System.Windows.MessageBox.Show("不能移动到机台码刀具位置", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||
return;
|
||
}
|
||
|
||
Tools.RemoveAt(oldIndex);
|
||
Tools.Insert(newIndex, tool);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 上移选中的刀具
|
||
/// </summary>
|
||
public void MoveSelectedToolUp()
|
||
{
|
||
if (SelectedTool == null || !CanMoveUp)
|
||
return;
|
||
|
||
int currentIndex = Tools.IndexOf(SelectedTool);
|
||
System.Diagnostics.Debug.WriteLine($"[MoveUp] 开始上移操作,选中项索引: {currentIndex}, 刀具编号: T{SelectedTool.ToolNumber:D2}");
|
||
|
||
if (currentIndex > 0)
|
||
{
|
||
// 检查是否是机台码刀具
|
||
if (SelectedTool.ToolType == ToolType.MachineCode)
|
||
{
|
||
System.Windows.MessageBox.Show("机台码刀具不允许移动位置", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||
return;
|
||
}
|
||
|
||
// 检查目标位置是否是机台码刀具
|
||
var targetTool = Tools[currentIndex - 1];
|
||
if (targetTool.ToolType == ToolType.MachineCode)
|
||
{
|
||
System.Windows.MessageBox.Show("不能移动到机台码刀具位置", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||
return;
|
||
}
|
||
|
||
// 保存选中的刀具引用
|
||
var selectedTool = SelectedTool;
|
||
int newIndex = currentIndex - 1;
|
||
|
||
// 执行上移操作
|
||
Tools.RemoveAt(currentIndex);
|
||
Tools.Insert(newIndex, selectedTool);
|
||
|
||
System.Diagnostics.Debug.WriteLine($"[MoveUp] 上移完成,新索引: {newIndex}");
|
||
|
||
// 使用延迟方法重新选中移动后的项
|
||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"[MoveUp] 延迟设置选中项,刀具编号: T{selectedTool.ToolNumber:D2}");
|
||
SelectedTool = selectedTool;
|
||
UpdateMoveButtonsState();
|
||
}), System.Windows.Threading.DispatcherPriority.Background);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 下移选中的刀具
|
||
/// </summary>
|
||
public void MoveSelectedToolDown()
|
||
{
|
||
if (SelectedTool == null || !CanMoveDown)
|
||
return;
|
||
|
||
int currentIndex = Tools.IndexOf(SelectedTool);
|
||
System.Diagnostics.Debug.WriteLine($"[MoveDown] 开始下移操作,选中项索引: {currentIndex}, 刀具编号: T{SelectedTool.ToolNumber:D2}");
|
||
|
||
if (currentIndex >= 0 && currentIndex < Tools.Count - 1)
|
||
{
|
||
// 检查是否是机台码刀具
|
||
if (SelectedTool.ToolType == ToolType.MachineCode)
|
||
{
|
||
System.Windows.MessageBox.Show("机台码刀具不允许移动位置", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||
return;
|
||
}
|
||
|
||
// 检查目标位置是否是机台码刀具
|
||
var targetTool = Tools[currentIndex + 1];
|
||
if (targetTool.ToolType == ToolType.MachineCode)
|
||
{
|
||
System.Windows.MessageBox.Show("不能移动到机台码刀具位置", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||
return;
|
||
}
|
||
|
||
// 保存选中的刀具引用
|
||
var selectedTool = SelectedTool;
|
||
int newIndex = currentIndex + 1;
|
||
|
||
// 执行下移操作
|
||
Tools.RemoveAt(currentIndex);
|
||
Tools.Insert(newIndex, selectedTool);
|
||
|
||
System.Diagnostics.Debug.WriteLine($"[MoveDown] 下移完成,新索引: {newIndex}");
|
||
|
||
// 使用延迟方法重新选中移动后的项
|
||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"[MoveDown] 延迟设置选中项,刀具编号: T{selectedTool.ToolNumber:D2}");
|
||
SelectedTool = selectedTool;
|
||
UpdateMoveButtonsState();
|
||
}), System.Windows.Threading.DispatcherPriority.Background);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新上移/下移按钮的状态
|
||
/// </summary>
|
||
private void UpdateMoveButtonsState()
|
||
{
|
||
if (SelectedTool == null)
|
||
{
|
||
CanMoveUp = false;
|
||
CanMoveDown = false;
|
||
System.Diagnostics.Debug.WriteLine("[UpdateButtons] 没有选中项,禁用所有按钮");
|
||
return;
|
||
}
|
||
|
||
int index = Tools.IndexOf(SelectedTool);
|
||
CanMoveUp = index > 0;
|
||
CanMoveDown = index >= 0 && index < Tools.Count - 1;
|
||
|
||
System.Diagnostics.Debug.WriteLine($"[UpdateButtons] 选中项索引: {index}, CanMoveUp: {CanMoveUp}, CanMoveDown: {CanMoveDown}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存刀具顺序并应用到钻带处理
|
||
/// </summary>
|
||
/// <returns>重新排序后的钻带内容</returns>
|
||
public string ApplyToolOrderToDrillTape()
|
||
{
|
||
if (string.IsNullOrEmpty(OriginalFilePath))
|
||
{
|
||
throw new InvalidOperationException("没有原始文件路径,请先加载钻带文件");
|
||
}
|
||
|
||
if (Tools.Count == 0)
|
||
{
|
||
throw new InvalidOperationException("没有刀具数据,请先加载钻带文件");
|
||
}
|
||
|
||
try
|
||
{
|
||
// 1. 使用现有的扩展方法生成重新排序后的钻带内容
|
||
string reorderedDrillTape = DrillTapeProcessorExtensions.GenerateReorderedDrillTape(DrillTapeContent, Tools.ToList());
|
||
|
||
// 2. 改进的备份逻辑
|
||
if (File.Exists(OriginalFilePath))
|
||
{
|
||
string backupFilePath = OriginalFilePath + ".bak";
|
||
|
||
// 检查备份文件是否已存在
|
||
if (File.Exists(backupFilePath))
|
||
{
|
||
var result = System.Windows.MessageBox.Show(
|
||
"备份文件已存在,请选择处理方式:\n\n" +
|
||
"是(Y):覆盖现有备份文件\n" +
|
||
"否(N):创建带时间戳的新备份文件\n" +
|
||
"取消:中止保存操作\n\n" +
|
||
"提示:选择'否'可以保留之前的备份历史",
|
||
"备份选项",
|
||
MessageBoxButton.YesNoCancel,
|
||
MessageBoxImage.Question);
|
||
|
||
switch (result)
|
||
{
|
||
case MessageBoxResult.Yes:
|
||
// 覆盖现有备份文件
|
||
File.Copy(OriginalFilePath, backupFilePath, true);
|
||
break;
|
||
|
||
case MessageBoxResult.No:
|
||
// 创建带时间戳的新备份文件
|
||
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
|
||
string timestampBackupPath = $"{OriginalFilePath}.{timestamp}.bak";
|
||
File.Copy(OriginalFilePath, timestampBackupPath);
|
||
break;
|
||
|
||
case MessageBoxResult.Cancel:
|
||
// 用户取消操作
|
||
throw new OperationCanceledException("用户取消了保存操作");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 备份文件不存在,直接创建
|
||
File.Copy(OriginalFilePath, backupFilePath);
|
||
}
|
||
}
|
||
|
||
// 3. 将重新排序后的钻带内容写入原始文件
|
||
File.WriteAllText(OriginalFilePath, reorderedDrillTape);
|
||
|
||
// 4. 更新当前钻带内容
|
||
DrillTapeContent = reorderedDrillTape;
|
||
|
||
return reorderedDrillTape;
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
// 重新抛出取消异常,不包装
|
||
throw;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw new InvalidOperationException($"保存钻带文件失败: {ex.Message}", ex);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重排刀序并重新编号
|
||
/// </summary>
|
||
/// <returns>重排后的钻带内容</returns>
|
||
public string ReorderAndRenumberTools()
|
||
{
|
||
if (Tools.Count == 0)
|
||
{
|
||
throw new InvalidOperationException("没有可重排的刀具");
|
||
}
|
||
|
||
// 1. 创建原始刀具编号到新编号的映射
|
||
var toolNumberMapping = new Dictionary<int, int>();
|
||
var originalToNewMapping = new Dictionary<int, int>(); // 保存原始映射关系
|
||
|
||
// 2. 按当前列表顺序重新编号(T01, T02, T03...)
|
||
int newToolNumber = 1;
|
||
foreach (var tool in Tools.ToList())
|
||
{
|
||
// 机台码刀具不允许重新编号
|
||
if (tool.ToolType != ToolType.MachineCode)
|
||
{
|
||
originalToNewMapping[tool.ToolNumber] = newToolNumber;
|
||
toolNumberMapping[tool.ToolNumber] = newToolNumber;
|
||
tool.ToolNumber = newToolNumber++;
|
||
}
|
||
else
|
||
{
|
||
// 机台码刀具保持原始编号,但也要加入映射
|
||
toolNumberMapping[tool.ToolNumber] = tool.ToolNumber;
|
||
}
|
||
}
|
||
|
||
// 3. 更新钻带内容中的刀具编号和孔位数据
|
||
string updatedDrillTape = UpdateDrillTapeWithNewToolNumbers(DrillTapeContent, toolNumberMapping);
|
||
|
||
// 4. 更新钻带内容
|
||
DrillTapeContent = updatedDrillTape;
|
||
|
||
// 5. 更新界面显示
|
||
OnPropertyChanged(nameof(Tools));
|
||
|
||
return updatedDrillTape;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 使用新的刀具编号更新钻带内容
|
||
/// </summary>
|
||
/// <param name="originalDrillTape">原始钻带内容</param>
|
||
/// <param name="toolNumberMapping">刀具编号映射</param>
|
||
/// <returns>更新后的钻带内容</returns>
|
||
private string UpdateDrillTapeWithNewToolNumbers(string originalDrillTape, Dictionary<int, int> toolNumberMapping)
|
||
{
|
||
var lines = originalDrillTape.Split(new[] { '\r', '\n' }, StringSplitOptions.None);
|
||
var result = new List<string>();
|
||
|
||
// 创建新编号到刀具对象的映射,以便获取对应的坐标数据
|
||
var newNumberToToolMap = new Dictionary<int, ToolItem>();
|
||
foreach (var tool in Tools)
|
||
{
|
||
if (toolNumberMapping.ContainsValue(tool.ToolNumber))
|
||
{
|
||
newNumberToToolMap[tool.ToolNumber] = tool;
|
||
}
|
||
}
|
||
|
||
// 首先解析原始钻带中的刀具定义行,保存参数信息
|
||
var originalToolDefinitions = new Dictionary<int, string>();
|
||
var headerLines = new List<string>();
|
||
|
||
foreach (var line in lines)
|
||
{
|
||
string trimmedLine = line.Trim();
|
||
|
||
if (trimmedLine == "%")
|
||
{
|
||
//headerLines.Add(line);
|
||
break;
|
||
}
|
||
|
||
// 处理刀具定义行(如 T01C1.049H05000Z+0.000S060.00F105.0U0700.0)
|
||
if (Regex.IsMatch(trimmedLine, @"^T(\d+)C"))
|
||
{
|
||
var match = Regex.Match(trimmedLine, @"^T(\d+)C(.*)$");
|
||
if (match.Success)
|
||
{
|
||
int originalToolNumber = int.Parse(match.Groups[1].Value);
|
||
originalToolDefinitions[originalToolNumber] = match.Groups[2].Value;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (line != "")
|
||
headerLines.Add(line);
|
||
}
|
||
}
|
||
|
||
// 添加头部信息
|
||
result.AddRange(headerLines);
|
||
|
||
// 按照新的刀具编号顺序输出刀具定义部分
|
||
var sortedTools = Tools.OrderBy(t => t.ToolNumber).ToList();
|
||
foreach (var tool in sortedTools)
|
||
{
|
||
// 查找原始刀具编号
|
||
int originalToolNumber = -1;
|
||
foreach (var kvp in toolNumberMapping)
|
||
{
|
||
if (kvp.Value == tool.ToolNumber)
|
||
{
|
||
originalToolNumber = kvp.Key;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (originalToolNumber != -1 && originalToolDefinitions.ContainsKey(originalToolNumber))
|
||
{
|
||
string toolDef = $"T{tool.ToolNumber:D2}C{originalToolDefinitions[originalToolNumber]}";
|
||
result.Add(toolDef);
|
||
}
|
||
}
|
||
|
||
// 添加 % 符号
|
||
result.Add("%");
|
||
|
||
// 处理刀具切换行和坐标数据部分
|
||
// 按新刀具编号顺序输出刀具切换行和对应的坐标数据
|
||
var sortedToolsForData = Tools.OrderBy(t => t.ToolNumber).ToList();
|
||
|
||
foreach (var tool in sortedToolsForData)
|
||
{
|
||
// 添加刀具切换行
|
||
result.Add($"T{tool.ToolNumber:D2}");
|
||
|
||
// 添加该刀具对应的所有坐标数据
|
||
if (tool.ToolType != ToolType.MachineCode && tool.HoleLocations != null && tool.HoleLocations.Count > 0)
|
||
{
|
||
foreach (var location in tool.HoleLocations)
|
||
{
|
||
result.Add(location);
|
||
}
|
||
}
|
||
|
||
// 如果是机台码刀具,添加机台码命令和坐标
|
||
if (tool.ToolType == ToolType.MachineCode)
|
||
{
|
||
if (!string.IsNullOrEmpty(tool.MachineCodeCommand) && !string.IsNullOrEmpty(tool.MachineCodeType))
|
||
{
|
||
result.Add($"{tool.MachineCodeCommand},{tool.MachineCodeType},$S $N");
|
||
|
||
// 添加机台码的坐标数据
|
||
if (tool.HoleLocations != null && tool.HoleLocations.Count > 0)
|
||
{
|
||
foreach (var location in tool.HoleLocations)
|
||
{
|
||
result.Add(location);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 添加结束标记
|
||
result.Add("M30");
|
||
|
||
return string.Join("\r\n", result);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载示例数据
|
||
/// </summary>
|
||
public void LoadSampleData()
|
||
{
|
||
// 清空原始文件路径,因为这是示例数据
|
||
OriginalFilePath = string.Empty;
|
||
Tools.Clear();
|
||
|
||
// 添加示例刀具数据
|
||
Tools.Add(new ToolItem
|
||
{
|
||
ToolNumber = 1,
|
||
Diameter = 1.049, // 尾号9,特殊孔径固定为圆孔
|
||
// 孔数相关属性已移除
|
||
// RegularHoles = 7,
|
||
// SlotHoles = 0,
|
||
// TotalHoles = 7,
|
||
ToolType = ToolType.Regular,
|
||
ToolSuffixType = ToolItem.GetToolSuffixType(1.049), // 特殊孔径
|
||
ToolCategory = ToolItem.GetToolCategory(ToolItem.GetToolSuffixType(1.049)),
|
||
HoleLocations = new List<string>
|
||
{
|
||
"X-167525Y013500",
|
||
"X-167525Y018500",
|
||
"X-167525Y023500",
|
||
"X167525Y013500",
|
||
"X167525Y018500",
|
||
"X167525Y023500",
|
||
"X099366Y502000"
|
||
}
|
||
});
|
||
Tools.Add(new ToolItem
|
||
{
|
||
ToolNumber = 2,
|
||
Diameter = 1.550, // 尾号0 -> 钻针
|
||
// 孔数相关属性已移除
|
||
// RegularHoles = 5,
|
||
// SlotHoles = 0,
|
||
// TotalHoles = 5,
|
||
ToolType = ToolType.Regular,
|
||
ToolSuffixType = ToolItem.GetToolSuffixType(1.550), // 基于孔径计算
|
||
ToolCategory = ToolItem.GetToolCategory(ToolItem.GetToolSuffixType(1.550)),
|
||
HoleLocations = new List<string>
|
||
{
|
||
"X-065975Y115250",
|
||
"X-085825Y122450",
|
||
"X-085825Y124550",
|
||
"X-097425Y115250",
|
||
"X103093Y502000"
|
||
}
|
||
});
|
||
Tools.Add(new ToolItem
|
||
{
|
||
ToolNumber = 3,
|
||
Diameter = 1.156, // 尾号6 -> EA型槽刀
|
||
// 孔数相关属性已移除
|
||
// RegularHoles = 1,
|
||
// SlotHoles = 528,
|
||
// TotalHoles = 529,
|
||
ToolType = ToolType.Slot,
|
||
ToolSuffixType = ToolItem.GetToolSuffixType(1.156), // 基于孔径计算
|
||
ToolCategory = ToolItem.GetToolCategory(ToolItem.GetToolSuffixType(1.156)),
|
||
HoleLocations = new List<string>
|
||
{
|
||
"X-069659Y016450G85X-094159Y016450",
|
||
"X-181341Y195550G85X-156841Y195550",
|
||
"X-069659Y210450G85X-094159Y210450",
|
||
"X-181341Y389550G85X-156841Y389550",
|
||
"X-069659Y404450G85X-094159Y404450",
|
||
"X-181341Y583550G85X-156841Y583550",
|
||
"X162939Y596000"
|
||
}
|
||
});
|
||
Tools.Add(new ToolItem
|
||
{
|
||
ToolNumber = 4,
|
||
Diameter = 1.451, // 尾号1 -> 槽刀
|
||
// 孔数相关属性已移除
|
||
// RegularHoles = 57,
|
||
// SlotHoles = 0,
|
||
// TotalHoles = 57,
|
||
ToolType = ToolType.Regular,
|
||
ToolSuffixType = ToolItem.GetToolSuffixType(1.451), // 基于孔径计算
|
||
ToolCategory = ToolItem.GetToolCategory(ToolItem.GetToolSuffixType(1.451)),
|
||
HoleLocations = new List<string>
|
||
{
|
||
"X-065975Y115250",
|
||
"X-085825Y122450",
|
||
"X-085825Y124550",
|
||
"X-097425Y115250",
|
||
"X103093Y502000"
|
||
}
|
||
});
|
||
Tools.Add(new ToolItem
|
||
{
|
||
ToolNumber = 5,
|
||
Diameter = 1.153, // 尾号3 -> 粉尘刀
|
||
// 孔数相关属性已移除
|
||
// RegularHoles = 10,
|
||
// SlotHoles = 0,
|
||
// TotalHoles = 10,
|
||
ToolType = ToolType.Regular,
|
||
ToolSuffixType = ToolItem.GetToolSuffixType(1.153), // 基于孔径计算
|
||
ToolCategory = ToolItem.GetToolCategory(ToolItem.GetToolSuffixType(1.153)),
|
||
HoleLocations = new List<string>
|
||
{
|
||
"X-065975Y115250",
|
||
"X-085825Y122450",
|
||
"X-085825Y124550",
|
||
"X-097425Y115250",
|
||
"X103093Y502000"
|
||
}
|
||
});
|
||
Tools.Add(new ToolItem
|
||
{
|
||
ToolNumber = 6,
|
||
Diameter = 0.499, // 特殊孔径固定为圆孔(机台码)
|
||
// 孔数相关属性已移除
|
||
// RegularHoles = 57,
|
||
// SlotHoles = 0,
|
||
// TotalHoles = 57,
|
||
ToolType = ToolType.MachineCode,
|
||
MachineCodeCommand = "M97",
|
||
MachineCodeType = "A*",
|
||
ToolSuffixType = ToolItem.GetToolSuffixType(0.499), // 特殊孔径
|
||
ToolCategory = ToolItem.GetToolCategory(ToolItem.GetToolSuffixType(0.499)),
|
||
HoleLocations = new List<string> { "X-194000Y002000" } // 机台码刀具的坐标数据
|
||
});
|
||
|
||
// 更新按钮状态
|
||
UpdateMoveButtonsState();
|
||
|
||
// 加载示例钻带内容
|
||
DrillTapeContent = @"M48
|
||
;厚铜板参数-镀膜-EA-250618
|
||
T01C1.049H05000Z+0.000S060.00F105.0U0700.0
|
||
T02C1.550H01500Z+0.150S070.00F008.0U0800.0
|
||
T03C1.156H03000Z-0.200S040.00F030.0U0900.0
|
||
T04C1.451H01500Z+0.150S070.00F008.0U0800.0
|
||
T05C1.153H01500Z+0.150S070.00F008.0U0800.0
|
||
T06C0.499H01500Z+0.150S070.00F008.0U0800.0
|
||
%
|
||
T01
|
||
X-167525Y013500
|
||
X-167525Y018500
|
||
X-167525Y023500
|
||
X167525Y013500
|
||
X167525Y018500
|
||
X167525Y023500
|
||
X099366Y502000
|
||
T02
|
||
X-065975Y115250
|
||
X-085825Y122450
|
||
X-085825Y124550
|
||
X-097425Y115250
|
||
X103093Y502000
|
||
T03
|
||
X-069659Y016450G85X-094159Y016450
|
||
X-181341Y195550G85X-156841Y195550
|
||
X-069659Y210450G85X-094159Y210450
|
||
X-181341Y389550G85X-156841Y389550
|
||
X-069659Y404450G85X-094159Y404450
|
||
X-181341Y583550G85X-156841Y583550
|
||
X162939Y596000
|
||
T04
|
||
X-065975Y115250
|
||
X-085825Y122450
|
||
X-085825Y124550
|
||
X-097425Y115250
|
||
X103093Y502000
|
||
T05
|
||
X-065975Y115250
|
||
X-085825Y122450
|
||
X-085825Y124550
|
||
X-097425Y115250
|
||
X103093Y502000
|
||
T06
|
||
M97,A*,$S $N
|
||
X-194000Y002000
|
||
M30";
|
||
}
|
||
|
||
public event PropertyChangedEventHandler? PropertyChanged;
|
||
|
||
protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
|
||
{
|
||
if (EqualityComparer<T>.Default.Equals(field, value))
|
||
return false;
|
||
|
||
field = value;
|
||
OnPropertyChanged(propertyName);
|
||
return true;
|
||
}
|
||
|
||
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
||
{
|
||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试机台码孔数计算功能
|
||
/// </summary>
|
||
public void TestMachineCodeHoleCalculation()
|
||
{
|
||
Console.WriteLine("=== 机台码孔数计算测试 ===");
|
||
|
||
// 测试钻带内容
|
||
string drillTapeContent = @"M48
|
||
;厚铜板参数-镀膜-EA-250618
|
||
T01C0.799H05000Z+0.000S060.00F105.0U0700.0
|
||
T02C0.656H01500Z+0.150S070.00F008.0U0800.0
|
||
T03C1.601H03000Z-0.200S040.00F030.0U0900.0
|
||
T04C0.499
|
||
%
|
||
T01
|
||
X-167525Y013500
|
||
X-167525Y018500
|
||
X-167525Y023500
|
||
X167525Y013500
|
||
X167525Y018500
|
||
X167525Y023500
|
||
X099366Y502000
|
||
T02
|
||
X-065975Y115250
|
||
X-085825Y122450
|
||
X-085825Y124550
|
||
X-097425Y115250
|
||
X103093Y502000
|
||
T03
|
||
X-069659Y016450G85X-094159Y016450
|
||
X-181341Y195550G85X-156841Y195550
|
||
X-069659Y210450G85X-094159Y210450
|
||
X-181341Y389550G85X-156841Y389550
|
||
X-069659Y404450G85X-094159Y404450
|
||
X-181341Y583550G85X-156841Y583550
|
||
X162939Y596000
|
||
T04
|
||
M97,A*,$S $N
|
||
X-194000Y002000
|
||
M30";
|
||
|
||
// 处理钻带
|
||
var result = DrillTapeProcessor.ProcessDrillTape(drillTapeContent);
|
||
|
||
// 输出结果
|
||
Console.WriteLine($"处理状态: {(result.Success ? "成功" : "失败")}");
|
||
if (!result.Success)
|
||
{
|
||
Console.WriteLine($"错误信息: {result.Message}");
|
||
return;
|
||
}
|
||
|
||
Console.WriteLine("\n刀具统计:");
|
||
Console.WriteLine("刀具\t孔径(mm)\t类型\t\t普通孔数\t槽孔数\t总孔数\t孔位数量");
|
||
Console.WriteLine("========================================================================");
|
||
|
||
foreach (var tool in result.ToolResults)
|
||
{
|
||
string toolTypeDisplay = tool.ToolType switch
|
||
{
|
||
ToolType.Regular => "圆孔",
|
||
ToolType.Slot => "槽孔",
|
||
ToolType.MachineCode => "机台码",
|
||
_ => "未知"
|
||
};
|
||
|
||
Console.WriteLine($"T{tool.ToolNumber:D2}\t{tool.Diameter:F3}\t\t{toolTypeDisplay}\t{tool.RegularHoles}\t\t{tool.SlotHoles}\t{tool.TotalHoles}\t{tool.Locations?.Count ?? 0}");
|
||
}
|
||
|
||
Console.WriteLine($"\n总孔数: {result.TotalHoles}");
|
||
|
||
// 验证结果
|
||
Console.WriteLine("\n=== 验证结果 ===");
|
||
VerifyResults(result);
|
||
|
||
// 测试孔位数据
|
||
Console.WriteLine("\n=== 孔位数据测试 ===");
|
||
TestHoleLocations(result);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试孔位数据
|
||
/// </summary>
|
||
/// <param name="result">钻带处理结果</param>
|
||
private void TestHoleLocations(DrillTapeResult result)
|
||
{
|
||
foreach (var tool in result.ToolResults)
|
||
{
|
||
Console.WriteLine($"\nT{tool.ToolNumber:D2} 孔位数据 ({tool.Locations?.Count ?? 0} 个):");
|
||
if (tool.Locations != null && tool.Locations.Count > 0)
|
||
{
|
||
foreach (var location in tool.Locations.Take(5)) // 只显示前5个
|
||
{
|
||
Console.WriteLine($" {location}");
|
||
}
|
||
if (tool.Locations.Count > 5)
|
||
{
|
||
Console.WriteLine($" ... 还有 {tool.Locations.Count - 5} 个孔位");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine(" 无孔位数据");
|
||
}
|
||
}
|
||
}
|
||
|
||
private void VerifyResults(DrillTapeResult result)
|
||
{
|
||
// CAM350的预期结果
|
||
var expectedResults = new[]
|
||
{
|
||
new { ToolNumber = 1, Diameter = 0.799, ExpectedHoles = 7 },
|
||
new { ToolNumber = 2, Diameter = 0.656, ExpectedHoles = 5 },
|
||
new { ToolNumber = 3, Diameter = 1.601, ExpectedHoles = 529 },
|
||
new { ToolNumber = 4, Diameter = 0.499, ExpectedHoles = 57 }
|
||
};
|
||
|
||
bool allMatch = true;
|
||
|
||
foreach (var expected in expectedResults)
|
||
{
|
||
var actual = result.ToolResults.Find(t => t.ToolNumber == expected.ToolNumber);
|
||
if (actual != null)
|
||
{
|
||
bool match = Math.Abs(actual.Diameter - expected.Diameter) < 0.001 &&
|
||
actual.TotalHoles == expected.ExpectedHoles;
|
||
|
||
Console.WriteLine($"T{expected.ToolNumber:D2} ({expected.Diameter:F3}mm): " +
|
||
$"预期={expected.ExpectedHoles}, 实际={actual.TotalHoles}, " +
|
||
$"{(match ? "✓" : "✗")}");
|
||
|
||
if (!match)
|
||
allMatch = false;
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"T{expected.ToolNumber:D2}: 未找到结果 ✗");
|
||
allMatch = false;
|
||
}
|
||
}
|
||
|
||
Console.WriteLine($"\n总体结果: {(allMatch ? "✓ 所有结果与CAM350一致" : "✗ 存在不一致的结果")}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试刀具尾号类型功能
|
||
/// </summary>
|
||
public void TestToolSuffixTypeFunctionality()
|
||
{
|
||
Console.WriteLine("=== 刀具尾号类型功能测试 ===");
|
||
|
||
// 测试不同孔径的尾号类型
|
||
double[] testDiameters = { 1.049, 1.550, 1.156, 1.451, 1.153, 1.255, 1.266, 1.277, 1.288, 1.299 };
|
||
|
||
Console.WriteLine("孔径(mm)\t尾号\t尾号类型\t\t大类");
|
||
Console.WriteLine("==============================================");
|
||
|
||
foreach (double diameter in testDiameters)
|
||
{
|
||
string diameterStr = diameter.ToString("F3");
|
||
char lastChar = diameterStr[diameterStr.Length - 1];
|
||
int suffix = int.Parse(lastChar.ToString());
|
||
var suffixType = ToolItem.GetToolSuffixType(diameter);
|
||
var category = ToolItem.GetToolCategory(suffixType);
|
||
var suffixDisplay = ToolItem.GetToolSuffixTypeDisplay(suffixType);
|
||
var categoryDisplay = ToolItem.GetToolCategoryDisplay(category);
|
||
|
||
Console.WriteLine($"{diameter:F3}\t{suffix}\t{suffixDisplay}\t{categoryDisplay}");
|
||
}
|
||
|
||
Console.WriteLine();
|
||
Console.WriteLine("=== 测试钻带处理功能 ===");
|
||
|
||
// 测试钻带处理
|
||
string drillTapeContent = @"M48
|
||
T10C1.049
|
||
T11C1.550
|
||
T12C1.156
|
||
T13C1.451
|
||
T14C1.153
|
||
T15C1.255
|
||
T16C1.266
|
||
T17C1.277
|
||
%
|
||
T10
|
||
X01000Y01000
|
||
T11
|
||
X02000Y02000
|
||
T12
|
||
X03000Y03000
|
||
T13
|
||
X04000Y04000
|
||
T14
|
||
X05000Y05000
|
||
T15
|
||
X06000Y06000
|
||
T16
|
||
X07000Y07000
|
||
T17
|
||
X08000Y08000
|
||
M30";
|
||
|
||
var result = DrillTapeProcessor.ProcessDrillTape(drillTapeContent);
|
||
|
||
if (result.Success)
|
||
{
|
||
Console.WriteLine("钻带处理成功!");
|
||
Console.WriteLine();
|
||
Console.WriteLine("刀具编号\t孔径(mm)\t类型\t\t尾号类型\t大类\t\t孔数");
|
||
Console.WriteLine("================================================================");
|
||
|
||
foreach (var tool in result.ToolResults)
|
||
{
|
||
string toolTypeDisplay = tool.ToolType switch
|
||
{
|
||
ToolType.Regular => "圆孔",
|
||
ToolType.Slot => "槽孔",
|
||
ToolType.MachineCode => "机台码",
|
||
_ => "未知"
|
||
};
|
||
|
||
string suffixTypeDisplay = tool.ToolSuffixType switch
|
||
{
|
||
ToolSuffixType.Drill => "钻针",
|
||
ToolSuffixType.Slot => "槽刀",
|
||
ToolSuffixType.EASlot => "EA型槽刀",
|
||
ToolSuffixType.DustSlot => "粉尘刀",
|
||
ToolSuffixType.DeburrSlot => "去毛刺刀",
|
||
ToolSuffixType.NonStandard => "非标刀",
|
||
ToolSuffixType.EASlot2 => "EA型槽刀",
|
||
ToolSuffixType.Special => "特殊刀具",
|
||
_ => "未知"
|
||
};
|
||
|
||
string categoryDisplay = tool.ToolCategory switch
|
||
{
|
||
ToolCategory.Drill => "钻针",
|
||
ToolCategory.Slot => "槽刀",
|
||
ToolCategory.EA => "EA刀",
|
||
ToolCategory.NonStandard => "非标刀",
|
||
ToolCategory.Special => "特殊刀",
|
||
_ => "未知"
|
||
};
|
||
|
||
Console.WriteLine($"T{tool.ToolNumber:D2}\t{tool.Diameter:F3}\t\t{toolTypeDisplay}\t{suffixTypeDisplay}\t{categoryDisplay}\t{tool.TotalHoles}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"钻带处理失败: {result.Message}");
|
||
}
|
||
|
||
Console.WriteLine();
|
||
Console.WriteLine("测试完成!");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试孔位数据功能(可在应用启动时调用)
|
||
/// </summary>
|
||
public static void TestHoleLocationsFunctionality()
|
||
{
|
||
Console.WriteLine("=== 孔位数据功能测试 ===");
|
||
Console.WriteLine();
|
||
|
||
// 使用用户提供的钻带数据示例
|
||
string drillTapeContent = @"M48
|
||
T01C0.799H05000Z+0.000S060.00F105.0U0700.0
|
||
T02C1.049H05000Z+0.000S045.00F105.0U0700.0
|
||
%
|
||
T01
|
||
X-281000Y003000
|
||
X-276000Y003000
|
||
X-271000Y003000
|
||
X271000Y003000
|
||
X276000Y003000
|
||
X281000Y003000
|
||
X-281000Y702500
|
||
X-276000Y702500
|
||
X-271000Y702500
|
||
X271000Y703000
|
||
X276000Y703000
|
||
X281000Y703000
|
||
X077370Y704000
|
||
T02
|
||
X-100000Y100000
|
||
X-200000Y200000
|
||
X-300000Y300000
|
||
M30";
|
||
|
||
// 处理钻带
|
||
var result = DrillTapeProcessor.ProcessDrillTape(drillTapeContent);
|
||
|
||
// 输出结果
|
||
Console.WriteLine($"处理状态: {(result.Success ? "成功" : "失败")}");
|
||
if (!result.Success)
|
||
{
|
||
Console.WriteLine($"错误信息: {result.Message}");
|
||
return;
|
||
}
|
||
|
||
Console.WriteLine("\n刀具统计:");
|
||
Console.WriteLine("刀具\t孔径(mm)\t类型\t\t普通孔数\t槽孔数\t总孔数\t孔位数量");
|
||
Console.WriteLine("========================================================================");
|
||
|
||
foreach (var tool in result.ToolResults)
|
||
{
|
||
string toolTypeDisplay = tool.ToolType switch
|
||
{
|
||
ToolType.Regular => "圆孔",
|
||
ToolType.Slot => "槽孔",
|
||
ToolType.MachineCode => "机台码",
|
||
_ => "未知"
|
||
};
|
||
|
||
Console.WriteLine($"T{tool.ToolNumber:D2}\t{tool.Diameter:F3}\t\t{toolTypeDisplay}\t{tool.RegularHoles}\t\t{tool.SlotHoles}\t{tool.TotalHoles}\t{tool.Locations?.Count ?? 0}");
|
||
}
|
||
|
||
Console.WriteLine($"\n总孔数: {result.TotalHoles}");
|
||
|
||
// 详细显示孔位数据
|
||
Console.WriteLine("\n=== 详细孔位数据 ===");
|
||
foreach (var tool in result.ToolResults)
|
||
{
|
||
Console.WriteLine($"\nT{tool.ToolNumber:D2} 孔位数据 ({tool.Locations?.Count ?? 0} 个):");
|
||
if (tool.Locations != null && tool.Locations.Count > 0)
|
||
{
|
||
int count = 0;
|
||
foreach (var location in tool.Locations)
|
||
{
|
||
Console.WriteLine($" [{++count:D2}] {location}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine(" 无孔位数据");
|
||
}
|
||
}
|
||
|
||
// 验证T01的孔位数据是否符合预期
|
||
Console.WriteLine("\n=== 验证T01孔位数据 ===");
|
||
var t01Result = result.ToolResults.Find(t => t.ToolNumber == 1);
|
||
if (t01Result != null && t01Result.Locations != null)
|
||
{
|
||
var expectedLocations = new System.Collections.Generic.List<string>
|
||
{
|
||
"X-281000Y003000",
|
||
"X-276000Y003000",
|
||
"X-271000Y003000",
|
||
"X271000Y003000",
|
||
"X276000Y003000",
|
||
"X281000Y003000",
|
||
"X-281000Y702500",
|
||
"X-276000Y702500",
|
||
"X-271000Y702500",
|
||
"X271000Y703000",
|
||
"X276000Y703000",
|
||
"X281000Y703000",
|
||
"X077370Y704000"
|
||
};
|
||
|
||
bool allMatch = true;
|
||
if (t01Result.Locations.Count == expectedLocations.Count)
|
||
{
|
||
for (int i = 0; i < expectedLocations.Count; i++)
|
||
{
|
||
if (t01Result.Locations[i] != expectedLocations[i])
|
||
{
|
||
Console.WriteLine($" 位置 {i + 1}: 预期 {expectedLocations[i]}, 实际 {t01Result.Locations[i]} ✗");
|
||
allMatch = false;
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($" 位置 {i + 1}: {t01Result.Locations[i]} ✓");
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($" 孔位数量不匹配: 预期 {expectedLocations.Count}, 实际 {t01Result.Locations.Count} ✗");
|
||
allMatch = false;
|
||
}
|
||
|
||
Console.WriteLine($"\nT01孔位数据验证结果: {(allMatch ? "✓ 全部匹配" : "✗ 存在不匹配")}");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("未找到T01刀具数据 ✗");
|
||
}
|
||
|
||
Console.WriteLine("\n孔位数据功能测试完成!");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示刀具详情窗口
|
||
/// </summary>
|
||
/// <param name="tool">要显示详情的刀具</param>
|
||
public void ShowToolDetail(ToolItem tool)
|
||
{
|
||
if (tool == null)
|
||
return;
|
||
|
||
try
|
||
{
|
||
var detailWindow = new ToolDetailWindow(tool);
|
||
detailWindow.Owner = System.Windows.Application.Current.MainWindow;
|
||
detailWindow.ShowDialog();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Windows.MessageBox.Show($"显示刀具详情失败: {ex.Message}", "错误",
|
||
System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试重排刀序功能
|
||
/// </summary>
|
||
public void TestReorderAndRenumberTools()
|
||
{
|
||
Console.WriteLine("=== 重排刀序功能测试 ===");
|
||
|
||
// 1. 加载测试数据
|
||
LoadSampleData();
|
||
|
||
// 2. 记录原始状态
|
||
var originalOrder = Tools.Select(t => new
|
||
{
|
||
t.ToolNumber,
|
||
t.Diameter,
|
||
LocationCount = t.HoleLocations?.Count ?? 0,
|
||
FirstLocation = t.HoleLocations?.FirstOrDefault() ?? ""
|
||
}).ToList();
|
||
|
||
Console.WriteLine("原始刀具顺序:");
|
||
foreach (var tool in originalOrder)
|
||
{
|
||
Console.WriteLine($"T{tool.ToolNumber:D2}({tool.Diameter:F3}): {tool.LocationCount}个坐标, 首个坐标: {tool.FirstLocation}");
|
||
}
|
||
|
||
// 3. 执行重排操作(将T02移到第一位)
|
||
if (Tools.Count >= 2)
|
||
{
|
||
var toolToMove = Tools.FirstOrDefault(t => t.ToolNumber == 2);
|
||
if (toolToMove != null && toolToMove.ToolType != ToolType.MachineCode)
|
||
{
|
||
int oldIndex = Tools.IndexOf(toolToMove);
|
||
ReorderTools(oldIndex, 0);
|
||
}
|
||
}
|
||
|
||
// 4. 执行重新编号
|
||
string reorderedDrillTape = ReorderAndRenumberTools();
|
||
|
||
// 5. 验证结果
|
||
Console.WriteLine("\n重排后刀具顺序:");
|
||
var reorderedOrder = Tools.Select(t => new
|
||
{
|
||
t.ToolNumber,
|
||
t.Diameter,
|
||
LocationCount = t.HoleLocations?.Count ?? 0,
|
||
FirstLocation = t.HoleLocations?.FirstOrDefault() ?? ""
|
||
}).ToList();
|
||
|
||
foreach (var tool in reorderedOrder)
|
||
{
|
||
Console.WriteLine($"T{tool.ToolNumber:D2}({tool.Diameter:F3}): {tool.LocationCount}个坐标, 首个坐标: {tool.FirstLocation}");
|
||
}
|
||
|
||
// 6. 验证钻带内容
|
||
Console.WriteLine("\n重排后的钻带内容:");
|
||
Console.WriteLine(reorderedDrillTape);
|
||
|
||
// 7. 验证坐标跟随
|
||
VerifyCoordinateBinding(originalOrder.ToList<dynamic>(), reorderedOrder.ToList<dynamic>());
|
||
|
||
Console.WriteLine("\n重排刀序功能测试完成!");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证坐标绑定关系
|
||
/// </summary>
|
||
private void VerifyCoordinateBinding(List<dynamic> originalOrder, List<dynamic> reorderedOrder)
|
||
{
|
||
Console.WriteLine("\n=== 验证坐标绑定关系 ===");
|
||
|
||
// 创建直径到坐标的映射
|
||
var originalDiameterToLocation = new Dictionary<double, string>();
|
||
foreach (var tool in originalOrder)
|
||
{
|
||
originalDiameterToLocation[tool.Diameter] = tool.FirstLocation;
|
||
}
|
||
|
||
// 验证重排后的坐标绑定
|
||
bool allMatch = true;
|
||
foreach (var tool in reorderedOrder)
|
||
{
|
||
if (originalDiameterToLocation.ContainsKey(tool.Diameter))
|
||
{
|
||
string originalLocation = originalDiameterToLocation[tool.Diameter];
|
||
if (tool.FirstLocation != originalLocation)
|
||
{
|
||
Console.WriteLine($"✗ 刀具{tool.Diameter:F3}的坐标不匹配: 原始{originalLocation}, 重排后{tool.FirstLocation}");
|
||
allMatch = false;
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"✓ 刀具{tool.Diameter:F3}的坐标正确跟随: {tool.FirstLocation}");
|
||
}
|
||
}
|
||
}
|
||
|
||
Console.WriteLine($"\n坐标绑定验证结果: {(allMatch ? "✓ 全部正确" : "✗ 存在问题")}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试修正后的重排刀序功能
|
||
/// </summary>
|
||
public void TestFixedReorderFunction()
|
||
{
|
||
Console.WriteLine("=== 测试修正后的重排刀序功能 ===");
|
||
|
||
// 1. 加载测试数据
|
||
LoadSampleData();
|
||
|
||
Console.WriteLine("原始刀具顺序:");
|
||
foreach (var tool in Tools)
|
||
{
|
||
Console.WriteLine($"T{tool.ToolNumber:D2}C{tool.Diameter:F3}");
|
||
}
|
||
|
||
// 2. 模拟用户重排操作:将T02移到第一位
|
||
if (Tools.Count >= 2)
|
||
{
|
||
var toolToMove = Tools.FirstOrDefault(t => t.ToolNumber == 2);
|
||
if (toolToMove != null && toolToMove.ToolType != ToolType.MachineCode)
|
||
{
|
||
int oldIndex = Tools.IndexOf(toolToMove);
|
||
ReorderTools(oldIndex, 0);
|
||
|
||
Console.WriteLine("\n重排后刀具顺序(重新编号前):");
|
||
foreach (var tool in Tools)
|
||
{
|
||
Console.WriteLine($"T{tool.ToolNumber:D2}C{tool.Diameter:F3}");
|
||
}
|
||
|
||
// 3. 执行重新编号
|
||
string reorderedDrillTape = ReorderAndRenumberTools();
|
||
|
||
Console.WriteLine("\n重排并重新编号后的刀具顺序:");
|
||
foreach (var tool in Tools)
|
||
{
|
||
Console.WriteLine($"T{tool.ToolNumber:D2}C{tool.Diameter:F3}");
|
||
}
|
||
|
||
// 4. 验证刀具定义部分是否按顺序排列
|
||
Console.WriteLine("\n=== 验证结果 ===");
|
||
var lines = reorderedDrillTape.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||
var toolDefinitionOrder = new List<int>();
|
||
|
||
foreach (var line in lines)
|
||
{
|
||
if (line.Trim() == "%")
|
||
{
|
||
break;
|
||
}
|
||
|
||
if (Regex.IsMatch(line, @"^T(\d+)C"))
|
||
{
|
||
var match = Regex.Match(line, @"^T(\d+)C");
|
||
if (match.Success)
|
||
{
|
||
toolDefinitionOrder.Add(int.Parse(match.Groups[1].Value));
|
||
}
|
||
}
|
||
}
|
||
|
||
Console.WriteLine("刀具定义部分的顺序: " + string.Join(", ", toolDefinitionOrder.Select(t => $"T{t:D2}")));
|
||
|
||
bool isOrdered = true;
|
||
for (int i = 1; i < toolDefinitionOrder.Count; i++)
|
||
{
|
||
if (toolDefinitionOrder[i] < toolDefinitionOrder[i - 1])
|
||
{
|
||
isOrdered = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
Console.WriteLine($"刀具定义部分是否按顺序排列: {(isOrdered ? "是" : "否")}");
|
||
|
||
if (isOrdered)
|
||
{
|
||
Console.WriteLine("✓ 重排刀序功能修正成功!");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("✗ 重排刀序功能仍有问题!");
|
||
}
|
||
|
||
// 5. 显示完整的重排后钻带内容
|
||
Console.WriteLine("\n重排后的钻带内容:");
|
||
Console.WriteLine(reorderedDrillTape);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试机台码坐标数据完整性
|
||
/// </summary>
|
||
public void TestMachineCodeCoordinateIntegrity()
|
||
{
|
||
Console.WriteLine("=== 机台码坐标数据完整性测试 ===");
|
||
|
||
// 1. 加载示例数据
|
||
LoadSampleData();
|
||
|
||
// 2. 执行重排刀序操作
|
||
string reorderedDrillTape = ReorderAndRenumberTools();
|
||
|
||
// 3. 验证机台码坐标数据
|
||
Console.WriteLine("重排后的钻带内容:");
|
||
Console.WriteLine(reorderedDrillTape);
|
||
|
||
// 4. 检查机台码部分是否包含坐标数据
|
||
var lines = reorderedDrillTape.Split(new[] { '\r', '\n' }, StringSplitOptions.None);
|
||
bool foundMachineCode = false;
|
||
bool foundCoordinate = false;
|
||
int machineCodeToolNumber = -1;
|
||
|
||
for (int i = 0; i < lines.Length; i++)
|
||
{
|
||
string line = lines[i].Trim();
|
||
|
||
// 查找机台码刀具
|
||
if (Regex.IsMatch(line, @"^T(\d+)"))
|
||
{
|
||
var match = Regex.Match(line, @"^T(\d+)");
|
||
if (match.Success)
|
||
{
|
||
int toolNumber = int.Parse(match.Groups[1].Value);
|
||
var tool = Tools.FirstOrDefault(t => t.ToolNumber == toolNumber);
|
||
|
||
if (tool != null && tool.ToolType == ToolType.MachineCode)
|
||
{
|
||
foundMachineCode = true;
|
||
machineCodeToolNumber = toolNumber;
|
||
Console.WriteLine($"\n找到机台码刀具 T{toolNumber:D2}");
|
||
|
||
// 检查下一行是否是机台码命令
|
||
if (i + 1 < lines.Length)
|
||
{
|
||
string nextLine = lines[i + 1].Trim();
|
||
if (Regex.IsMatch(nextLine, @"(M97|M98),(A\*|B\*),\$S \$N"))
|
||
{
|
||
Console.WriteLine($" 机台码命令: {nextLine}");
|
||
|
||
// 检查下下行是否是坐标数据
|
||
if (i + 2 < lines.Length)
|
||
{
|
||
string coordinateLine = lines[i + 2].Trim();
|
||
if (Regex.IsMatch(coordinateLine, @"X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)"))
|
||
{
|
||
foundCoordinate = true;
|
||
Console.WriteLine($" 坐标数据: {coordinateLine}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 5. 输出测试结果
|
||
Console.WriteLine("\n=== 测试结果 ===");
|
||
Console.WriteLine($"找到机台码刀具: {(foundMachineCode ? "是" : "否")}");
|
||
Console.WriteLine($"找到坐标数据: {(foundCoordinate ? "是" : "否")}");
|
||
|
||
if (foundMachineCode && foundCoordinate)
|
||
{
|
||
Console.WriteLine("✓ 机台码坐标数据完整性测试通过!");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("✗ 机台码坐标数据完整性测试失败!");
|
||
|
||
if (!foundMachineCode)
|
||
Console.WriteLine(" 原因:未找到机台码刀具");
|
||
if (!foundCoordinate)
|
||
Console.WriteLine(" 原因:机台码刀具缺少坐标数据");
|
||
}
|
||
|
||
// 6. 验证ToolItem中的坐标数据
|
||
var machineCodeTool = Tools.FirstOrDefault(t => t.ToolType == ToolType.MachineCode);
|
||
if (machineCodeTool != null)
|
||
{
|
||
Console.WriteLine($"\nToolItem中的机台码坐标数据:");
|
||
Console.WriteLine($" 刀具编号: T{machineCodeTool.ToolNumber:D2}");
|
||
Console.WriteLine($" 机台码命令: {machineCodeTool.MachineCodeCommand}");
|
||
Console.WriteLine($" 机台码类型: {machineCodeTool.MachineCodeType}");
|
||
Console.WriteLine($" 坐标数量: {machineCodeTool.HoleLocations?.Count ?? 0}");
|
||
|
||
if (machineCodeTool.HoleLocations != null && machineCodeTool.HoleLocations.Count > 0)
|
||
{
|
||
foreach (var location in machineCodeTool.HoleLocations)
|
||
{
|
||
Console.WriteLine($" 坐标: {location}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试机台码处理修复效果
|
||
/// </summary>
|
||
public void TestMachineCodeProcessingFix()
|
||
{
|
||
Console.WriteLine("=== 测试机台码处理修复效果 ===");
|
||
|
||
// 测试钻带内容(包含机台码)
|
||
string testDrillTape = @"M48
|
||
;厚铜板参数-镀膜-EA-250618
|
||
T01C1.049H05000Z+0.000S060.00F105.0U0700.0
|
||
T02C1.550H01500Z+0.150S070.00F008.0U0800.0
|
||
T03C1.156H03000Z-0.200S040.00F030.0U0900.0
|
||
T04C0.499H01500Z+0.150S070.00F008.0U0800.0
|
||
%
|
||
T01
|
||
X-167525Y013500
|
||
X-167525Y018500
|
||
X-167525Y023500
|
||
T02
|
||
X-065975Y115250
|
||
X-085825Y122450
|
||
T03
|
||
X-069659Y016450G85X-094159Y016450
|
||
X-181341Y195550G85X-156841Y195550
|
||
T04
|
||
M97,A*,$S $N
|
||
X-194000Y002000
|
||
M30";
|
||
|
||
try
|
||
{
|
||
// 1. 使用DrillTapeProcessor处理钻带
|
||
Console.WriteLine("\n1. 使用DrillTapeProcessor处理钻带:");
|
||
var result = DrillTapeProcessor.ProcessDrillTape(testDrillTape);
|
||
|
||
if (!result.Success)
|
||
{
|
||
Console.WriteLine($"处理失败: {result.Message}");
|
||
return;
|
||
}
|
||
|
||
// 2. 检查ToolResult中的机台码信息
|
||
Console.WriteLine("\n2. 检查ToolResult中的机台码信息:");
|
||
foreach (var toolResult in result.ToolResults)
|
||
{
|
||
Console.WriteLine($"T{toolResult.ToolNumber:D2}: 类型={toolResult.ToolType}, 命令={toolResult.MachineCodeCommand}, 类型={toolResult.MachineCodeType}");
|
||
}
|
||
|
||
// 3. 使用LoadToolsFromDrillTape方法加载到ViewModel
|
||
Console.WriteLine("\n3. 加载到ViewModel并检查ToolItem中的机台码信息:");
|
||
DrillTapeContent = testDrillTape;
|
||
Tools.Clear();
|
||
LoadToolsFromDrillTape(testDrillTape);
|
||
|
||
foreach (var tool in Tools)
|
||
{
|
||
Console.WriteLine($"T{tool.ToolNumber:D2}: 类型={tool.ToolType}, 命令={tool.MachineCodeCommand}, 类型={tool.MachineCodeType}");
|
||
}
|
||
|
||
// 4. 测试GenerateReorderedDrillTape方法
|
||
Console.WriteLine("\n4. 测试GenerateReorderedDrillTape方法:");
|
||
string reorderedDrillTape = DrillTapeProcessorExtensions.GenerateReorderedDrillTape(testDrillTape, Tools.ToList());
|
||
Console.WriteLine("重排后的钻带内容:");
|
||
Console.WriteLine(reorderedDrillTape);
|
||
|
||
// 5. 验证机台码信息是否正确保留
|
||
Console.WriteLine("\n5. 验证机台码信息是否正确保留:");
|
||
bool machineCodeFound = false;
|
||
bool machineCodeCommandFound = false;
|
||
bool machineCodeTypeFound = false;
|
||
|
||
var lines = reorderedDrillTape.Split(new[] { '\r', '\n' }, StringSplitOptions.None);
|
||
foreach (var line in lines)
|
||
{
|
||
if (line.Contains("M97") || line.Contains("M98"))
|
||
{
|
||
machineCodeFound = true;
|
||
if (line.Contains("M97") || line.Contains("M98"))
|
||
{
|
||
machineCodeCommandFound = true;
|
||
}
|
||
if (line.Contains("A*") || line.Contains("B*"))
|
||
{
|
||
machineCodeTypeFound = true;
|
||
}
|
||
Console.WriteLine($"找到机台码命令行: {line}");
|
||
}
|
||
}
|
||
|
||
Console.WriteLine($"\n验证结果:");
|
||
Console.WriteLine($"机台码命令存在: {machineCodeFound}");
|
||
Console.WriteLine($"机台码命令类型正确: {machineCodeCommandFound}");
|
||
Console.WriteLine($"机台码类型正确: {machineCodeTypeFound}");
|
||
|
||
if (machineCodeFound && machineCodeCommandFound && machineCodeTypeFound)
|
||
{
|
||
Console.WriteLine("\n✓ 机台码处理修复效果验证成功!");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("\n✗ 机台码处理修复效果验证失败!");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"测试过程中发生异常: {ex.Message}");
|
||
Console.WriteLine($"堆栈跟踪: {ex.StackTrace}");
|
||
}
|
||
}
|
||
}
|
||
} |