Files
AohDrllTools/RouParameterReplacer.cs

179 lines
6.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}