feat: 增加钻带涨缩功能,支持倍率/PPM模式缩放坐标

- 新增 ExcellonScaler 引擎:普通孔缩放坐标,G85槽孔保护槽长,刀具定义行原样保留
- 新增 DrillScalingWindow 参数设置窗口:倍率/PPM模式切换,X/Y独立输入
- 集成到启动功能菜单:.dr2/.dpin 文件显示"涨缩"按钮
- 输出覆盖原文件 + .bak 备份,GB2312 编码
This commit is contained in:
2026-06-05 22:17:15 +08:00
parent f050a606ef
commit cacbbe6c33
7 changed files with 505 additions and 2 deletions

154
ExcellonScaler.cs Normal file
View File

@@ -0,0 +1,154 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace DrillTools.Integration
{
/// <summary>
/// Excellon 钻带涨缩引擎
/// 对钻孔坐标进行 X/Y 方向独立缩放,保持槽孔长度不变
/// </summary>
internal static class ExcellonScaler
{
// 坐标模式X 后跟可选符号的数字可能含小数点Y 同理
private static readonly Regex CoordinatePattern = new(
@"^X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)$",
RegexOptions.Compiled);
// G85 槽孔模式X...Y...G85X...Y...
private static readonly Regex SlotPattern = new(
@"^(X[+-]?\d+\.?\d*Y[+-]?\d+\.?\d*)G85(X[+-]?\d+\.?\d*Y[+-]?\d+\.?\d*)$",
RegexOptions.Compiled);
// 解析 X 或 Y 坐标值的子模式
private static readonly Regex XValuePattern = new(
@"X([+-]?\d+\.?\d*)", RegexOptions.Compiled);
private static readonly Regex YValuePattern = new(
@"Y([+-]?\d+\.?\d*)", RegexOptions.Compiled);
// 刀具定义行模式(在头部,如 T01C0.799H05000Z+0.000S060.00
private static readonly Regex ToolDefinitionPattern = new(
@"^T\d+C", RegexOptions.Compiled | RegexOptions.IgnoreCase);
/// <summary>
/// 对钻带内容执行涨缩
/// </summary>
/// <param name="content">原始钻带内容</param>
/// <param name="kx">X 方向缩放倍率</param>
/// <param name="ky">Y 方向缩放倍率</param>
/// <returns>缩放后的钻带内容</returns>
public static string Scale(string content, double kx, double ky)
{
if (content == null)
throw new ArgumentNullException(nameof(content));
var lines = content.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
var result = new List<string>(lines.Length);
foreach (var line in lines)
{
string trimmed = line.Trim();
// 空行直接保留
if (string.IsNullOrEmpty(trimmed))
{
result.Add(line);
continue;
}
// 刀具定义行TxxC...):严格原样保留
if (ToolDefinitionPattern.IsMatch(trimmed))
{
result.Add(line);
continue;
}
// G85 槽孔行:缩放中心点,保持槽长不变
var slotMatch = SlotPattern.Match(trimmed);
if (slotMatch.Success)
{
result.Add(ScaleSlotLine(trimmed, kx, ky));
continue;
}
// 普通坐标行X...Y...
var coordMatch = CoordinatePattern.Match(trimmed);
if (coordMatch.Success)
{
result.Add(ScaleCoordinateLine(trimmed, kx, ky));
continue;
}
// 其余行原样保留M48, %, Txx, M30 等)
result.Add(line);
}
return string.Join("\r\n", result);
}
/// <summary>
/// 缩放普通坐标行
/// </summary>
private static string ScaleCoordinateLine(string line, double kx, double ky)
{
var xMatch = XValuePattern.Match(line);
var yMatch = YValuePattern.Match(line);
if (!xMatch.Success || !yMatch.Success)
return line;
double xOrig = double.Parse(xMatch.Groups[1].Value);
double yOrig = double.Parse(yMatch.Groups[1].Value);
long xNew = (long)Math.Round(xOrig * kx);
long yNew = (long)Math.Round(yOrig * ky);
return $"X{xNew}Y{yNew}";
}
/// <summary>
/// 缩放 G85 槽孔行
/// 缩放中心点,保持原始矢量恢复起止点(槽长不变)
/// </summary>
private static string ScaleSlotLine(string line, double kx, double ky)
{
var slotMatch = SlotPattern.Match(line);
if (!slotMatch.Success)
return line;
// 解析起点坐标
var startPart = slotMatch.Groups[1].Value;
var xStartMatch = XValuePattern.Match(startPart);
var yStartMatch = YValuePattern.Match(startPart);
double xStart = double.Parse(xStartMatch.Groups[1].Value);
double yStart = double.Parse(yStartMatch.Groups[1].Value);
// 解析终点坐标
var endPart = slotMatch.Groups[2].Value;
var xEndMatch = XValuePattern.Match(endPart);
var yEndMatch = YValuePattern.Match(endPart);
double xEnd = double.Parse(xEndMatch.Groups[1].Value);
double yEnd = double.Parse(yEndMatch.Groups[1].Value);
// 计算中心点
double cx = (xStart + xEnd) / 2.0;
double cy = (yStart + yEnd) / 2.0;
// 缩放中心点
long cxNew = (long)Math.Round(cx * kx);
long cyNew = (long)Math.Round(cy * ky);
// 保持原始矢量(槽长不变)
long dx = (long)Math.Round((xEnd - xStart) / 2.0);
long dy = (long)Math.Round((yEnd - yStart) / 2.0);
// 恢复起止点
long newStartX = cxNew - dx;
long newStartY = cyNew - dy;
long newEndX = cxNew + dx;
long newEndY = cyNew + dy;
return $"X{newStartX}Y{newStartY}G85X{newEndX}Y{newEndY}";
}
}
}