feat: ROU成型参数替换功能 — 支持 .rou/.rou1/.rou2/.roux 文件从参数 txt 自动补充 S/F/R/Z/H
This commit is contained in:
72
App.xaml.cs
72
App.xaml.cs
@@ -51,6 +51,7 @@ namespace DrillTools
|
|||||||
bool canGeneratePpDrillTape = viewModel.CanGeneratePpDrillTape;
|
bool canGeneratePpDrillTape = viewModel.CanGeneratePpDrillTape;
|
||||||
string extension = Path.GetExtension(filePath).ToLowerInvariant();
|
string extension = Path.GetExtension(filePath).ToLowerInvariant();
|
||||||
bool canScaleDrillTape = extension == ".dr2" || extension == ".dpin";
|
bool canScaleDrillTape = extension == ".dr2" || extension == ".dpin";
|
||||||
|
bool isRouFile = extension == ".rou" || extension == ".rou1" || extension == ".rou2" || extension == ".roux";
|
||||||
double minDrill = viewModel.MinDrillDiameter;
|
double minDrill = viewModel.MinDrillDiameter;
|
||||||
double minSlot = viewModel.MinSlotDiameter;
|
double minSlot = viewModel.MinSlotDiameter;
|
||||||
double minEA = viewModel.MinEADiameter;
|
double minEA = viewModel.MinEADiameter;
|
||||||
@@ -82,7 +83,8 @@ namespace DrillTools
|
|||||||
selectionViewModel,
|
selectionViewModel,
|
||||||
canClearParameters,
|
canClearParameters,
|
||||||
canGeneratePpDrillTape,
|
canGeneratePpDrillTape,
|
||||||
canScaleDrillTape);
|
canScaleDrillTape,
|
||||||
|
canReplaceRouParameters: isRouFile);
|
||||||
selectionWindow.ShowDialog();
|
selectionWindow.ShowDialog();
|
||||||
|
|
||||||
switch (selectionWindow.SelectedAction)
|
switch (selectionWindow.SelectedAction)
|
||||||
@@ -107,6 +109,10 @@ namespace DrillTools
|
|||||||
PerformDrillScaling(filePath);
|
PerformDrillScaling(filePath);
|
||||||
Shutdown();
|
Shutdown();
|
||||||
break;
|
break;
|
||||||
|
case StartupAction.ReplaceRouParameters:
|
||||||
|
PerformRouParameterReplace(filePath);
|
||||||
|
Shutdown();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Shutdown();
|
Shutdown();
|
||||||
break;
|
break;
|
||||||
@@ -222,12 +228,14 @@ namespace DrillTools
|
|||||||
string content = CommandTypeFileReader.ReadAllText(filePath);
|
string content = CommandTypeFileReader.ReadAllText(filePath);
|
||||||
string scaledContent = Integration.ExcellonScaler.Scale(content, result.Kx, result.Ky);
|
string scaledContent = Integration.ExcellonScaler.Scale(content, result.Kx, result.Ky);
|
||||||
|
|
||||||
// 备份原文件
|
// 在源文件所在目录下新建子文件夹 dr2 x{InputX} y{InputY}
|
||||||
string backupFilePath = filePath + ".bak";
|
string sourceDir = Path.GetDirectoryName(filePath)!;
|
||||||
File.Copy(filePath, backupFilePath, true);
|
string outputDir = Path.Combine(sourceDir, $"dr2 x{result.InputX} y{result.InputY}");
|
||||||
|
Directory.CreateDirectory(outputDir);
|
||||||
|
|
||||||
// 写入缩放后的内容
|
// 将涨缩后的钻带写入子文件夹,文件名不变
|
||||||
using var writer = new StreamWriter(filePath, false, Encoding.GetEncoding(936));
|
string outputFilePath = Path.Combine(outputDir, Path.GetFileName(filePath));
|
||||||
|
using var writer = new StreamWriter(outputFilePath, false, Encoding.GetEncoding(936));
|
||||||
writer.Write(scaledContent);
|
writer.Write(scaledContent);
|
||||||
|
|
||||||
// 系数记忆:紧跟钻带写回立即落盘,不滞后到完成提示之后。
|
// 系数记忆:紧跟钻带写回立即落盘,不滞后到完成提示之后。
|
||||||
@@ -242,7 +250,7 @@ namespace DrillTools
|
|||||||
memoryWarning = $"\n(系数记忆保存失败:{ex.Message})";
|
memoryWarning = $"\n(系数记忆保存失败:{ex.Message})";
|
||||||
}
|
}
|
||||||
|
|
||||||
string completionMessage = $"涨缩完成,原文件已备份为:\n{Path.GetFileName(filePath)}.bak";
|
string completionMessage = $"涨缩完成,输出至:\n{outputFilePath}";
|
||||||
if (memoryWarning != null)
|
if (memoryWarning != null)
|
||||||
completionMessage += memoryWarning;
|
completionMessage += memoryWarning;
|
||||||
|
|
||||||
@@ -264,7 +272,7 @@ namespace DrillTools
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
string exePath = Process.GetCurrentProcess().MainModule!.FileName!;
|
string exePath = Process.GetCurrentProcess().MainModule!.FileName!;
|
||||||
string[] extensions = { ".drl", ".dr2", ".dr3", ".trg", ".dpin", ".txt" };
|
string[] extensions = { ".drl", ".dr2", ".dr3", ".trg", ".dpin", ".txt", ".rou", ".rou1", ".rou2", ".roux" };
|
||||||
string menuText = "用DrillTools打开";
|
string menuText = "用DrillTools打开";
|
||||||
|
|
||||||
foreach (string ext in extensions)
|
foreach (string ext in extensions)
|
||||||
@@ -295,11 +303,57 @@ namespace DrillTools
|
|||||||
|
|
||||||
// 检查文件扩展名是否为支持的钻带文件格式
|
// 检查文件扩展名是否为支持的钻带文件格式
|
||||||
string extension = Path.GetExtension(filePath).ToLowerInvariant();
|
string extension = Path.GetExtension(filePath).ToLowerInvariant();
|
||||||
string[] supportedExtensions = { ".txt", ".drl", ".dr2", ".dr3", ".trg", ".dpin" };
|
string[] supportedExtensions = { ".txt", ".drl", ".dr2", ".dr3", ".trg", ".dpin", ".rou", ".rou1", ".rou2", ".roux" };
|
||||||
|
|
||||||
return supportedExtensions.Contains(extension);
|
return supportedExtensions.Contains(extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void PerformRouParameterReplace(string filePath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
string paramDir = @"C:\Users\14244\source\repos\Aoh\DrillTools\ROU-canshu\";
|
||||||
|
#else
|
||||||
|
string paramDir = @"\\aht-file-1\AHT-workdatatemp\泰国澳弘的相关说明资料及作业指引\钻锣带\成型\";
|
||||||
|
#endif
|
||||||
|
if (!Directory.Exists(paramDir))
|
||||||
|
{
|
||||||
|
System.Windows.MessageBox.Show(
|
||||||
|
$"参数文件目录不存在:\n{paramDir}",
|
||||||
|
"错误",
|
||||||
|
MessageBoxButton.OK,
|
||||||
|
MessageBoxImage.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectionWindow = new ParameterFileSelectionWindow(paramDir);
|
||||||
|
selectionWindow.ShowDialog();
|
||||||
|
|
||||||
|
if (selectionWindow.SelectedFilePath == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RouParameterReplacer.ReplaceParameters(filePath, selectionWindow.SelectedFilePath);
|
||||||
|
|
||||||
|
System.Windows.MessageBox.Show(
|
||||||
|
$"参数替换完成:\n{filePath}\n原文件已备份为 .bak",
|
||||||
|
"替换完成",
|
||||||
|
MessageBoxButton.OK,
|
||||||
|
MessageBoxImage.Information);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Windows.MessageBox.Show(
|
||||||
|
$"参数替换失败:\n{ex.Message}",
|
||||||
|
"错误",
|
||||||
|
MessageBoxButton.OK,
|
||||||
|
MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从 MainWindowViewModel.Tools 独立遍历计算叠板用最小刀径。
|
/// 从 MainWindowViewModel.Tools 独立遍历计算叠板用最小刀径。
|
||||||
/// 分类逻辑与 UpdateMinDiameterInfo 一致(按尾号使用标准),不排除 0.749mm;
|
/// 分类逻辑与 UpdateMinDiameterInfo 一致(按尾号使用标准),不排除 0.749mm;
|
||||||
|
|||||||
57
DrillTapeLineParser.cs
Normal file
57
DrillTapeLineParser.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace DrillTools
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 钻带文本行结构,保留原始文本和行尾换行符。
|
||||||
|
/// </summary>
|
||||||
|
internal readonly record struct DrillTapeLine(string Text, string LineEnding);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 钻带行解析器,将钻带文本按行拆分,保留原始换行符。
|
||||||
|
/// </summary>
|
||||||
|
internal static class DrillTapeLineParser
|
||||||
|
{
|
||||||
|
private static readonly char[] LineEndChars = { '\r', '\n' };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将文本内容按行拆分,保留每行的换行符。
|
||||||
|
/// </summary>
|
||||||
|
public static List<DrillTapeLine> SplitLines(string content)
|
||||||
|
{
|
||||||
|
var lines = new List<DrillTapeLine>();
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
while (index < content.Length)
|
||||||
|
{
|
||||||
|
int lineEndIndex = content.IndexOfAny(LineEndChars, index);
|
||||||
|
if (lineEndIndex < 0)
|
||||||
|
{
|
||||||
|
lines.Add(new DrillTapeLine(content[index..], string.Empty));
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
string text = content[index..lineEndIndex];
|
||||||
|
string lineEnding;
|
||||||
|
if (content[lineEndIndex] == '\r' && lineEndIndex + 1 < content.Length && content[lineEndIndex + 1] == '\n')
|
||||||
|
{
|
||||||
|
lineEnding = "\r\n";
|
||||||
|
index = lineEndIndex + 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lineEnding = content[lineEndIndex].ToString();
|
||||||
|
index = lineEndIndex + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.Add(new DrillTapeLine(text, lineEnding));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (content.Length == 0)
|
||||||
|
lines.Add(new DrillTapeLine(string.Empty, string.Empty));
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,6 @@ namespace DrillTools
|
|||||||
internal static class DrillTapeParameterCleaner
|
internal static class DrillTapeParameterCleaner
|
||||||
{
|
{
|
||||||
private const int Gb2312CodePage = 936;
|
private const int Gb2312CodePage = 936;
|
||||||
private static readonly char[] LineEndChars = { '\r', '\n' };
|
|
||||||
private static readonly Regex HeaderToolDefinitionStartPattern = new(
|
private static readonly Regex HeaderToolDefinitionStartPattern = new(
|
||||||
@"^T\d+C",
|
@"^T\d+C",
|
||||||
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
@@ -19,7 +18,7 @@ namespace DrillTools
|
|||||||
|
|
||||||
public static bool CanClearParameters(string drillTapeContent)
|
public static bool CanClearParameters(string drillTapeContent)
|
||||||
{
|
{
|
||||||
var lines = SplitLines(drillTapeContent);
|
var lines = DrillTapeLineParser.SplitLines(drillTapeContent);
|
||||||
if (lines.Count < 2)
|
if (lines.Count < 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -45,7 +44,7 @@ namespace DrillTools
|
|||||||
if (!CanClearParameters(drillTapeContent))
|
if (!CanClearParameters(drillTapeContent))
|
||||||
throw new InvalidOperationException("钻带文件不符合清空参数条件");
|
throw new InvalidOperationException("钻带文件不符合清空参数条件");
|
||||||
|
|
||||||
var lines = SplitLines(drillTapeContent);
|
var lines = DrillTapeLineParser.SplitLines(drillTapeContent);
|
||||||
var builder = new StringBuilder(drillTapeContent.Length);
|
var builder = new StringBuilder(drillTapeContent.Length);
|
||||||
|
|
||||||
for (int i = 0; i < lines.Count; i++)
|
for (int i = 0; i < lines.Count; i++)
|
||||||
@@ -81,42 +80,6 @@ namespace DrillTools
|
|||||||
writer.Write(cleanedContent);
|
writer.Write(cleanedContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<DrillTapeLine> SplitLines(string content)
|
|
||||||
{
|
|
||||||
var lines = new List<DrillTapeLine>();
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
while (index < content.Length)
|
|
||||||
{
|
|
||||||
int lineEndIndex = content.IndexOfAny(LineEndChars, index);
|
|
||||||
if (lineEndIndex < 0)
|
|
||||||
{
|
|
||||||
lines.Add(new DrillTapeLine(content[index..], string.Empty));
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
string text = content[index..lineEndIndex];
|
|
||||||
string lineEnding;
|
|
||||||
if (content[lineEndIndex] == '\r' && lineEndIndex + 1 < content.Length && content[lineEndIndex + 1] == '\n')
|
|
||||||
{
|
|
||||||
lineEnding = "\r\n";
|
|
||||||
index = lineEndIndex + 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineEnding = content[lineEndIndex].ToString();
|
|
||||||
index = lineEndIndex + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
lines.Add(new DrillTapeLine(text, lineEnding));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content.Length == 0)
|
|
||||||
lines.Add(new DrillTapeLine(string.Empty, string.Empty));
|
|
||||||
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<DrillTapeLine> GetHeaderToolDefinitionLines(IReadOnlyList<DrillTapeLine> lines)
|
private static List<DrillTapeLine> GetHeaderToolDefinitionLines(IReadOnlyList<DrillTapeLine> lines)
|
||||||
{
|
{
|
||||||
var toolDefinitionLines = new List<DrillTapeLine>();
|
var toolDefinitionLines = new List<DrillTapeLine>();
|
||||||
@@ -150,6 +113,5 @@ namespace DrillTools
|
|||||||
return Encoding.GetEncoding(Gb2312CodePage);
|
return Encoding.GetEncoding(Gb2312CodePage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly record struct DrillTapeLine(string Text, string LineEnding);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
32
ParameterFileSelectionWindow.xaml
Normal file
32
ParameterFileSelectionWindow.xaml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<Window x:Class="DrillTools.ParameterFileSelectionWindow"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
Title="选择参数文件"
|
||||||
|
Width="420"
|
||||||
|
SizeToContent="Height"
|
||||||
|
ResizeMode="NoResize"
|
||||||
|
Topmost="True"
|
||||||
|
WindowStartupLocation="CenterScreen">
|
||||||
|
<Grid Margin="15">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="0" Text="请选择要使用的参数文件:" Margin="0,0,0,10" />
|
||||||
|
|
||||||
|
<ListBox Grid.Row="1"
|
||||||
|
Name="FileListBox"
|
||||||
|
Height="200"
|
||||||
|
Margin="0,0,0,15"
|
||||||
|
DisplayMemberPath="Name" />
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="2" HorizontalAlignment="Center" Orientation="Horizontal">
|
||||||
|
<Button Name="OkButton" Width="80" Height="28" Content="确定" Margin="0,0,15,0"
|
||||||
|
Click="OkButton_Click" IsDefault="True" />
|
||||||
|
<Button Name="CancelButton" Width="80" Height="28" Content="取消"
|
||||||
|
Click="CancelButton_Click" IsCancel="True" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
66
ParameterFileSelectionWindow.xaml.cs
Normal file
66
ParameterFileSelectionWindow.xaml.cs
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace DrillTools
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 参数文件选择窗口,列出指定目录下所有 .txt 文件供用户选择。
|
||||||
|
/// </summary>
|
||||||
|
public partial class ParameterFileSelectionWindow : Window
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 用户选中的文件完整路径;若取消则为 null。
|
||||||
|
/// </summary>
|
||||||
|
public string? SelectedFilePath { get; private set; }
|
||||||
|
|
||||||
|
public ParameterFileSelectionWindow(string paramDirectory)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
if (Directory.Exists(paramDirectory))
|
||||||
|
{
|
||||||
|
var files = Directory.GetFiles(paramDirectory, "*.txt")
|
||||||
|
.Select(f => new FileInfo(f))
|
||||||
|
.OrderBy(f => f.Name)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
FileListBox.ItemsSource = files;
|
||||||
|
}
|
||||||
|
|
||||||
|
OkButton.IsEnabled = false;
|
||||||
|
FileListBox.SelectionChanged += (_, _) =>
|
||||||
|
{
|
||||||
|
OkButton.IsEnabled = FileListBox.SelectedItem != null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 双击直接确认
|
||||||
|
FileListBox.MouseDoubleClick += (_, _) =>
|
||||||
|
{
|
||||||
|
if (FileListBox.SelectedItem is FileInfo file)
|
||||||
|
{
|
||||||
|
SelectedFilePath = file.FullName;
|
||||||
|
DialogResult = true;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OkButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (FileListBox.SelectedItem is FileInfo file)
|
||||||
|
{
|
||||||
|
SelectedFilePath = file.FullName;
|
||||||
|
DialogResult = true;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CancelButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
DialogResult = false;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
178
RouParameterReplacer.cs
Normal file
178
RouParameterReplacer.cs
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace DrillTools
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ROU 成型参数替换:将参数文件中的 S/F/R/Z/H 参数追加到 .rou 文件的刀径定义行。
|
||||||
|
/// </summary>
|
||||||
|
internal static class RouParameterReplacer
|
||||||
|
{
|
||||||
|
private const int Gb2312CodePage = 936;
|
||||||
|
private const double DiameterTolerance = 0.001;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 匹配参数行:T00C<直径>S<参数...>
|
||||||
|
/// 例:T00C1.800S55.0F5.0R25Z0H600
|
||||||
|
/// </summary>
|
||||||
|
private static readonly Regex ParamLinePattern = new(
|
||||||
|
@"^T00C(?<diameter>\d+(?:\.\d+)?)(?<params>S.+?)\s*$",
|
||||||
|
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 匹配 .rou 刀径定义行:T<刀号>C<直径>
|
||||||
|
/// 例:T01C1.8
|
||||||
|
/// </summary>
|
||||||
|
private static readonly Regex ToolLinePattern = new(
|
||||||
|
@"^T\d+C(?<diameter>\d+(?:\.\d+)?)",
|
||||||
|
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行参数替换。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rouFilePath">.rou 文件完整路径</param>
|
||||||
|
/// <param name="paramFilePath">参数 .txt 文件完整路径</param>
|
||||||
|
public static void ReplaceParameters(string rouFilePath, string paramFilePath)
|
||||||
|
{
|
||||||
|
// 1. 读取参数文件,构建直径→参数字符串映射
|
||||||
|
var paramDict = LoadParameterDictionary(paramFilePath);
|
||||||
|
|
||||||
|
if (paramDict.Count == 0)
|
||||||
|
throw new InvalidOperationException("参数文件中未找到有效的参数行(格式:T00C<直径>S...)");
|
||||||
|
|
||||||
|
// 2. 读取 .rou 文件
|
||||||
|
string rouContent = CommandTypeFileReader.ReadAllText(rouFilePath);
|
||||||
|
|
||||||
|
// 3. 执行替换
|
||||||
|
string replacedContent = ReplaceParametersInContent(rouContent, paramDict);
|
||||||
|
|
||||||
|
// 4. 备份原文件
|
||||||
|
string backupFilePath = rouFilePath + ".bak";
|
||||||
|
File.Copy(rouFilePath, backupFilePath, true);
|
||||||
|
|
||||||
|
// 5. 写回文件
|
||||||
|
using var writer = new StreamWriter(rouFilePath, false, Encoding.GetEncoding(Gb2312CodePage));
|
||||||
|
writer.Write(replacedContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从参数文件加载直径→参数字符串(从 S 开始到行尾)的映射。
|
||||||
|
/// </summary>
|
||||||
|
private static Dictionary<double, string> LoadParameterDictionary(string paramFilePath)
|
||||||
|
{
|
||||||
|
var dict = new Dictionary<double, string>();
|
||||||
|
|
||||||
|
string content = CommandTypeFileReader.ReadAllText(paramFilePath);
|
||||||
|
var lines = DrillTapeLineParser.SplitLines(content);
|
||||||
|
|
||||||
|
foreach (var line in lines)
|
||||||
|
{
|
||||||
|
string trimmed = line.Text.Trim();
|
||||||
|
var match = ParamLinePattern.Match(trimmed);
|
||||||
|
if (!match.Success)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!double.TryParse(match.Groups["diameter"].Value,
|
||||||
|
NumberStyles.Float, CultureInfo.InvariantCulture, out double diameter))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string paramString = match.Groups["params"].Value;
|
||||||
|
|
||||||
|
// 如果同一直径出现多次,后面的覆盖前面的
|
||||||
|
dict[diameter] = paramString;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 在 .rou 文件内容中,将 M48~% 区域内的刀径行末尾追加参数。
|
||||||
|
/// </summary>
|
||||||
|
private static string ReplaceParametersInContent(string rouContent, Dictionary<double, string> paramDict)
|
||||||
|
{
|
||||||
|
var lines = DrillTapeLineParser.SplitLines(rouContent);
|
||||||
|
var builder = new StringBuilder(rouContent.Length + 1024);
|
||||||
|
|
||||||
|
bool inHeader = false;
|
||||||
|
|
||||||
|
foreach (var line in lines)
|
||||||
|
{
|
||||||
|
string trimmed = line.Text.Trim();
|
||||||
|
|
||||||
|
// 检测 M48 头部开始
|
||||||
|
if (!inHeader && trimmed == "M48")
|
||||||
|
{
|
||||||
|
inHeader = true;
|
||||||
|
builder.Append(line.Text);
|
||||||
|
builder.Append(line.LineEnding);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检测 % 头部结束
|
||||||
|
if (inHeader && trimmed == "%")
|
||||||
|
{
|
||||||
|
inHeader = false;
|
||||||
|
builder.Append(line.Text);
|
||||||
|
builder.Append(line.LineEnding);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在头部区域内匹配刀径定义行
|
||||||
|
if (inHeader)
|
||||||
|
{
|
||||||
|
var match = ToolLinePattern.Match(trimmed);
|
||||||
|
if (match.Success &&
|
||||||
|
double.TryParse(match.Groups["diameter"].Value,
|
||||||
|
NumberStyles.Float, CultureInfo.InvariantCulture, out double diameter))
|
||||||
|
{
|
||||||
|
// 按直径数值匹配参数(允许浮点误差)
|
||||||
|
string? paramString = FindMatchingParameter(diameter, paramDict);
|
||||||
|
if (paramString != null)
|
||||||
|
{
|
||||||
|
// 保留原始行尾空白
|
||||||
|
string textWithoutTrailing = line.Text.TrimEnd();
|
||||||
|
int trailingLength = line.Text.Length - textWithoutTrailing.Length;
|
||||||
|
string trailing = trailingLength > 0 ? line.Text[^trailingLength..] : string.Empty;
|
||||||
|
|
||||||
|
builder.Append(textWithoutTrailing);
|
||||||
|
builder.Append(paramString);
|
||||||
|
builder.Append(trailing);
|
||||||
|
builder.Append(line.LineEnding);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他行原样保留
|
||||||
|
builder.Append(line.Text);
|
||||||
|
builder.Append(line.LineEnding);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按直径查找匹配的参数字符串,允许 0.001 的浮点误差。
|
||||||
|
/// 返回 null 表示未找到匹配。
|
||||||
|
/// </summary>
|
||||||
|
private static string? FindMatchingParameter(double diameter, Dictionary<double, string> paramDict)
|
||||||
|
{
|
||||||
|
// 精确匹配优先
|
||||||
|
if (paramDict.TryGetValue(diameter, out string? paramString))
|
||||||
|
return paramString;
|
||||||
|
|
||||||
|
// 浮点容差匹配
|
||||||
|
foreach (var kvp in paramDict)
|
||||||
|
{
|
||||||
|
if (Math.Abs(kvp.Key - diameter) < DiameterTolerance)
|
||||||
|
return kvp.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -137,6 +137,7 @@
|
|||||||
<Button Width="120" Height="30" Content="调整刀序" Margin="0,0,15,0" Click="AdjustToolOrder_Click"/>
|
<Button Width="120" Height="30" Content="调整刀序" Margin="0,0,15,0" Click="AdjustToolOrder_Click"/>
|
||||||
<Button Width="120" Height="30" Content="导出孔数" Margin="0,0,15,0" Click="ExportHoleCount_Click"/>
|
<Button Width="120" Height="30" Content="导出孔数" Margin="0,0,15,0" Click="ExportHoleCount_Click"/>
|
||||||
<Button Name="ClearParametersButton" Width="120" Height="30" Content="清空参数" Margin="0,0,15,0" Click="ClearParameters_Click"/>
|
<Button Name="ClearParametersButton" Width="120" Height="30" Content="清空参数" Margin="0,0,15,0" Click="ClearParameters_Click"/>
|
||||||
|
<Button Name="ReplaceRouParametersButton" Width="120" Height="30" Content="更改参数" Margin="0,0,15,0" Click="ReplaceRouParameters_Click" Visibility="Collapsed"/>
|
||||||
<Button Name="GeneratePpDrillTapeButton" Width="120" Height="30" Content="生成PP钻带" Margin="0,0,15,0" Click="GeneratePpDrillTape_Click"/>
|
<Button Name="GeneratePpDrillTapeButton" Width="120" Height="30" Content="生成PP钻带" Margin="0,0,15,0" Click="GeneratePpDrillTape_Click"/>
|
||||||
<Button Name="ScaleDrillTapeButton" Width="120" Height="30" Content="二钻涨缩" Click="ScaleDrillTape_Click"/>
|
<Button Name="ScaleDrillTapeButton" Width="120" Height="30" Content="二钻涨缩" Click="ScaleDrillTape_Click"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ namespace DrillTools
|
|||||||
ExportHoleCount,
|
ExportHoleCount,
|
||||||
ClearParameters,
|
ClearParameters,
|
||||||
GeneratePpDrillTape,
|
GeneratePpDrillTape,
|
||||||
ScaleDrillTape
|
ScaleDrillTape,
|
||||||
|
ReplaceRouParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class StartupSelectionWindow : Window
|
public partial class StartupSelectionWindow : Window
|
||||||
@@ -18,13 +19,14 @@ namespace DrillTools
|
|||||||
|
|
||||||
public StartupSelectionWindow(StartupSelectionViewModel viewModel,
|
public StartupSelectionWindow(StartupSelectionViewModel viewModel,
|
||||||
bool canClearParameters = false, bool canGeneratePpDrillTape = false,
|
bool canClearParameters = false, bool canGeneratePpDrillTape = false,
|
||||||
bool canScaleDrillTape = false)
|
bool canScaleDrillTape = false, bool canReplaceRouParameters = false)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
ClearParametersButton.Visibility = canClearParameters ? Visibility.Visible : Visibility.Collapsed;
|
ClearParametersButton.Visibility = canClearParameters ? Visibility.Visible : Visibility.Collapsed;
|
||||||
GeneratePpDrillTapeButton.Visibility = canGeneratePpDrillTape ? Visibility.Visible : Visibility.Collapsed;
|
GeneratePpDrillTapeButton.Visibility = canGeneratePpDrillTape ? Visibility.Visible : Visibility.Collapsed;
|
||||||
ScaleDrillTapeButton.Visibility = canScaleDrillTape ? Visibility.Visible : Visibility.Collapsed;
|
ScaleDrillTapeButton.Visibility = canScaleDrillTape ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
ReplaceRouParametersButton.Visibility = canReplaceRouParameters ? Visibility.Visible : Visibility.Collapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AdjustToolOrder_Click(object sender, RoutedEventArgs e)
|
private void AdjustToolOrder_Click(object sender, RoutedEventArgs e)
|
||||||
@@ -56,5 +58,11 @@ namespace DrillTools
|
|||||||
SelectedAction = StartupAction.ScaleDrillTape;
|
SelectedAction = StartupAction.ScaleDrillTape;
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ReplaceRouParameters_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
SelectedAction = StartupAction.ReplaceRouParameters;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user