From cb27e8917ad22f00cb0222ab8bba2086c96c614b Mon Sep 17 00:00:00 2001 From: "Mr.Xia" <1424473282@qq.com> Date: Sat, 23 May 2026 16:04:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20PP=E9=92=BB=E5=B8=A6=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E6=98=BE=E7=A4=BAX/Y=E9=97=B4=E8=B7=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 检测PP钻带(文件名-pp结尾、4孔、直径4.000),计算上下孔X间距和左右孔Y间距 (欧氏距离),在MainWindow和StartupSelectionWindow的基础信息中显示。 Co-Authored-By: Claude Opus 4.7 --- App.xaml.cs | 29 +++++++- MainWindow.xaml | 12 +++- MainWindowViewModel.cs | 126 +++++++++++++++++++++++++++++++++ StartupSelectionWindow.xaml | 12 +++- StartupSelectionWindow.xaml.cs | 8 ++- demo_drl/m80033599b0-a2-pp.drl | 10 +++ 6 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 demo_drl/m80033599b0-a2-pp.drl diff --git a/App.xaml.cs b/App.xaml.cs index 6822a27..43e6379 100644 --- a/App.xaml.cs +++ b/App.xaml.cs @@ -37,7 +37,8 @@ namespace DrillTools bool canClearParameters = CanClearDrillTapeParameters(filePath); bool canGeneratePpDrillTape = CanGeneratePpDrillTape(filePath); GetMinDiameters(filePath, out double minDrill, out double minSlot, out double minEA); - var selectionWindow = new StartupSelectionWindow(filePath, canClearParameters, canGeneratePpDrillTape, minDrill, minSlot, minEA); + GetPpSpacing(filePath, out bool isPpDrillTape, out double ppXSpacing, out double ppYSpacing); + var selectionWindow = new StartupSelectionWindow(filePath, canClearParameters, canGeneratePpDrillTape, minDrill, minSlot, minEA, isPpDrillTape, ppXSpacing, ppYSpacing); selectionWindow.ShowDialog(); switch (selectionWindow.SelectedAction) @@ -173,6 +174,32 @@ namespace DrillTools } } + private static void GetPpSpacing(string filePath, out bool isPpDrillTape, out double ppXSpacing, out double ppYSpacing) + { + isPpDrillTape = false; + ppXSpacing = 0; + ppYSpacing = 0; + + try + { + var viewModel = new MainWindowViewModel + { + OriginalFilePath = filePath, + ShouldCheckSortFileOnLoad = false + }; + + string content = CommandTypeFileReader.ReadAllText(filePath); + viewModel.LoadToolsFromDrillTape(content); + + isPpDrillTape = viewModel.IsPpDrillTape; + ppXSpacing = viewModel.PpXSpacing; + ppYSpacing = viewModel.PpYSpacing; + } + catch + { + } + } + private static void PerformPpDrillTapeGeneration(string filePath) { try diff --git a/MainWindow.xaml b/MainWindow.xaml index b84b094..7c655a8 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -211,10 +211,20 @@ + + diff --git a/MainWindowViewModel.cs b/MainWindowViewModel.cs index 768a25e..854b802 100644 --- a/MainWindowViewModel.cs +++ b/MainWindowViewModel.cs @@ -33,6 +33,9 @@ namespace DrillTools private bool _isStartupDrillTapeFile; private bool _canGeneratePpDrillTape; private bool _shouldCheckSortFileOnLoad = true; + private bool _isPpDrillTape; + private double _ppXSpacing; + private double _ppYSpacing; private const int SwRestore = 9; private const int SvsiSelect = 0x1; @@ -209,6 +212,33 @@ namespace DrillTools set => SetProperty(ref _minEADiameter, value); } + /// + /// 是否为PP钻带 + /// + public bool IsPpDrillTape + { + get => _isPpDrillTape; + set => SetProperty(ref _isPpDrillTape, value); + } + + /// + /// PP钻带X间距(左右孔距离,单位mm) + /// + public double PpXSpacing + { + get => _ppXSpacing; + set => SetProperty(ref _ppXSpacing, value); + } + + /// + /// PP钻带Y间距(上下孔距离,单位mm) + /// + public double PpYSpacing + { + get => _ppYSpacing; + set => SetProperty(ref _ppYSpacing, value); + } + /// /// 从钻带内容加载刀具信息 /// @@ -316,6 +346,9 @@ namespace DrillTools // 计算并更新最小直径信息 UpdateMinDiameterInfo(); + // 计算PP钻带间距 + UpdatePpSpacingInfo(); + // 启动菜单的预检查和非调整刀序动作会关闭此开关,避免排序提示抢在菜单前弹出。 if (ShouldCheckSortFileOnLoad && !string.IsNullOrEmpty(OriginalFilePath)) { @@ -1709,6 +1742,99 @@ M30"; System.Diagnostics.Debug.WriteLine($"=== 计算完成 ==="); } + /// + /// 更新PP钻带间距信息 + /// + private void UpdatePpSpacingInfo() + { + IsPpDrillTape = false; + PpXSpacing = 0; + PpYSpacing = 0; + + // 检测条件:文件名以-pp结尾,恰好1个刀具,4个孔,直径4.000 + if (string.IsNullOrEmpty(OriginalFilePath)) + return; + + var fileName = System.IO.Path.GetFileNameWithoutExtension(OriginalFilePath); + if (!fileName.EndsWith("-pp", StringComparison.OrdinalIgnoreCase)) + return; + + if (Tools.Count != 1) + return; + + var tool = Tools[0]; + if (tool.TotalHoles != 4 || Math.Abs(tool.Diameter - 4.000) > 0.001) + return; + + // 解析孔位坐标 + var points = new List<(double X, double Y)>(); + + foreach (var location in tool.HoleLocations) + { + var match = System.Text.RegularExpressions.Regex.Match(location, @"X([+-]?\d+)Y([+-]?\d+)"); + if (match.Success) + { + double x = double.Parse(match.Groups[1].Value) / 1000.0; + double y = double.Parse(match.Groups[2].Value) / 1000.0; + points.Add((x, y)); + } + } + + if (points.Count != 4) + return; + + IsPpDrillTape = true; + + // 将4个点配对为矩形的两组对边,取X跨度+Y跨度最大的方案 + int[][][] combos = { new[] { new[] { 0, 1 }, new[] { 2, 3 } }, new[] { new[] { 0, 2 }, new[] { 1, 3 } }, new[] { new[] { 0, 3 }, new[] { 1, 2 } } }; + + double bestRange = -1; + int bestIdx = 0; + + for (int i = 0; i < combos.Length; i++) + { + var a = points[combos[i][0][0]]; + var b = points[combos[i][0][1]]; + var c = points[combos[i][1][0]]; + var d = points[combos[i][1][1]]; + + double xRange = Math.Max(Math.Abs(a.X - b.X), Math.Abs(c.X - d.X)); + double yRange = Math.Max(Math.Abs(a.Y - b.Y), Math.Abs(c.Y - d.Y)); + double totalRange = xRange + yRange; + + if (totalRange > bestRange) + { + bestRange = totalRange; + bestIdx = i; + } + } + + var p1 = points[combos[bestIdx][0][0]]; + var p2 = points[combos[bestIdx][0][1]]; + var p3 = points[combos[bestIdx][1][0]]; + var p4 = points[combos[bestIdx][1][1]]; + + double dist1 = Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y)); + double dist2 = Math.Sqrt((p3.X - p4.X) * (p3.X - p4.X) + (p3.Y - p4.Y) * (p3.Y - p4.Y)); + + // 跨度更大的为X间距(上下孔),另一组为Y间距(左右孔) + double xSpan1 = Math.Abs(p1.X - p2.X); + double xSpan2 = Math.Abs(p3.X - p4.X); + + if (xSpan1 >= xSpan2) + { + PpXSpacing = Math.Round(dist1, 3, MidpointRounding.AwayFromZero); + PpYSpacing = Math.Round(dist2, 3, MidpointRounding.AwayFromZero); + } + else + { + PpXSpacing = Math.Round(dist2, 3, MidpointRounding.AwayFromZero); + PpYSpacing = Math.Round(dist1, 3, MidpointRounding.AwayFromZero); + } + + System.Diagnostics.Debug.WriteLine($"[PP钻带] X间距={PpXSpacing:F3}, Y间距={PpYSpacing:F3}"); + } + /// /// 测试使用参考钻带重排功能 /// diff --git a/StartupSelectionWindow.xaml b/StartupSelectionWindow.xaml index 63c5022..7f3fc68 100644 --- a/StartupSelectionWindow.xaml +++ b/StartupSelectionWindow.xaml @@ -24,10 +24,20 @@ + + diff --git a/StartupSelectionWindow.xaml.cs b/StartupSelectionWindow.xaml.cs index 0458fb8..90adf1b 100644 --- a/StartupSelectionWindow.xaml.cs +++ b/StartupSelectionWindow.xaml.cs @@ -17,7 +17,8 @@ namespace DrillTools public StartupAction SelectedAction { get; private set; } = StartupAction.None; public StartupSelectionWindow(string filePath, bool canClearParameters = false, bool canGeneratePpDrillTape = false, - double minDrillDiameter = 0, double minSlotDiameter = 0, double minEADiameter = 0) + double minDrillDiameter = 0, double minSlotDiameter = 0, double minEADiameter = 0, + bool isPpDrillTape = false, double ppXSpacing = 0, double ppYSpacing = 0) { InitializeComponent(); DataContext = new @@ -25,7 +26,10 @@ namespace DrillTools FileName = Path.GetFileNameWithoutExtension(filePath), MinDrillDiameter = minDrillDiameter, MinSlotDiameter = minSlotDiameter, - MinEADiameter = minEADiameter + MinEADiameter = minEADiameter, + IsPpDrillTape = isPpDrillTape, + PpXSpacing = ppXSpacing, + PpYSpacing = ppYSpacing }; ClearParametersButton.Visibility = canClearParameters ? Visibility.Visible : Visibility.Collapsed; GeneratePpDrillTapeButton.Visibility = canGeneratePpDrillTape ? Visibility.Visible : Visibility.Collapsed; diff --git a/demo_drl/m80033599b0-a2-pp.drl b/demo_drl/m80033599b0-a2-pp.drl new file mode 100644 index 0000000..ad291cb --- /dev/null +++ b/demo_drl/m80033599b0-a2-pp.drl @@ -0,0 +1,10 @@ +M48 +;厚铜板参数-镀膜-EA-260417 +T01C4.000H00400Z-0.305S020.00F030.0U0700.0 +% +T01 +X245000Y297500 +X023000Y595000 +X-245000Y297500 +X030000Y000000 +M30