钻带解析顺序与格式优化,界面信息增强

本次更新聚焦于钻带文件解析顺序与格式的准确还原,提升了界面基础信息展示,并优化了相关数据结构和辅助方法。主要包括:
- 钻带孔位逐行顺序解析,完整保留原始坐标字符串格式,避免顺序错乱和格式丢失。
- 界面新增基础信息分组,自动统计并展示最小钻咀、槽刀、EA刀直径。
- 数据结构如Point2D等增加运算符重载和构造函数,便于几何计算。
- 机台码(0.499刀具)坐标行顺序提取及正则健壮性提升。
- 移除强制编码指定,提升跨平台兼容性。
- 清理冗余测试代码,更新示例/测试钻带文件内容。
- 新增《必读.md》,明确AI开发不需编写测试单元。
本次无其他功能或逻辑变动的占位diff。
This commit is contained in:
2025-12-22 16:50:42 +08:00
parent 44de1cb982
commit 0eab0f42ee
13 changed files with 30955 additions and 10232 deletions

View File

@@ -0,0 +1,7 @@
# 必读.md
针对DrillTools项目的AI编程设计原则
## 指导原则
- 完成需求后不需要AI进行功能测试编写测试单元

View File

@@ -1,142 +0,0 @@
using System;
using System.Collections.Generic;
using DrillTools;
using DrillTools.Integration;
namespace DrillTools.Tests
{
/// <summary>
/// 坐标格式保留测试类
/// 用于验证修改后的代码能正确保留原始坐标格式
/// </summary>
public class CoordinateFormatTest
{
/// <summary>
/// 测试坐标格式保留功能
/// </summary>
public static void TestCoordinateFormatPreservation()
{
Console.WriteLine("=== 坐标格式保留测试 ===");
// 测试用例:各种格式的坐标
var testCases = new[]
{
"X-265000Y013250", // 负坐标,前导零
"X-265000Y008250", // 负坐标,前导零
"X075392Y559511", // 正坐标,前导零
"X017500Y519500G85X018500Y519500", // 槽孔坐标
"X-238500Y519500G85X-237500Y519500" // 负坐标槽孔
};
// 创建测试钻带内容
string drillTapeContent = CreateTestDrillTape(testCases);
// 解析钻带
var result = DrillTapeProcessor.ProcessDrillTape(drillTapeContent);
// 验证结果
if (result.Success)
{
Console.WriteLine("钻带解析成功!");
// 检查每个工具的坐标输出
foreach (var toolResult in result.ToolResults)
{
Console.WriteLine($"\n工具 T{toolResult.ToolNumber:D2} (直径: {toolResult.Diameter:F3}mm):");
Console.WriteLine($"坐标数量: {toolResult.Locations.Count}");
// 显示前5个坐标作为示例
int displayCount = Math.Min(5, toolResult.Locations.Count);
for (int i = 0; i < displayCount; i++)
{
string original = i < testCases.Length ? testCases[i] : "N/A";
string parsed = toolResult.Locations[i];
Console.WriteLine($" 原始: {original}");
Console.WriteLine($" 解析: {parsed}");
Console.WriteLine($" 匹配: {(original == parsed ? "" : "")}");
Console.WriteLine();
}
}
}
else
{
Console.WriteLine($"钻带解析失败: {result.Message}");
}
}
/// <summary>
/// 创建测试钻带内容
/// </summary>
private static string CreateTestDrillTape(string[] coordinates)
{
var drillTape = new System.Text.StringBuilder();
// 添加头部
drillTape.AppendLine("M48");
drillTape.AppendLine("METRIC");
drillTape.AppendLine("VER,1");
drillTape.AppendLine("FMAT,2");
// 添加刀具定义
drillTape.AppendLine("T01C1.000");
drillTape.AppendLine("T02C2.000");
// 添加结束标记
drillTape.AppendLine("%");
// 添加刀具1的坐标
drillTape.AppendLine("T01");
for (int i = 0; i < Math.Min(3, coordinates.Length); i++)
{
// 只添加普通坐标不含G85
if (!coordinates[i].Contains("G85"))
{
drillTape.AppendLine(coordinates[i]);
}
}
// 添加刀具2的坐标槽孔
drillTape.AppendLine("T02");
for (int i = 3; i < coordinates.Length; i++)
{
// 添加槽孔坐标含G85
if (coordinates[i].Contains("G85"))
{
drillTape.AppendLine(coordinates[i]);
}
}
// 添加结束标记
drillTape.AppendLine("M30");
return drillTape.ToString();
}
/// <summary>
/// 测试Point2D的原始字符串保留功能
/// </summary>
public static void TestPoint2DOriginalString()
{
Console.WriteLine("\n=== Point2D原始字符串测试 ===");
// 测试用例
var testCoordinates = new[]
{
"X-265000Y013250",
"X075392Y559511",
"X000123Y000456"
};
foreach (var coord in testCoordinates)
{
var point = Point2D.ParseFromDrillString(coord);
Console.WriteLine($"原始坐标: {coord}");
Console.WriteLine($"解析后X: {point.X:F3}, Y: {point.Y:F3}");
Console.WriteLine($"原始字符串: {point.OriginalString}");
Console.WriteLine($"字符串匹配: {(coord == point.OriginalString ? "" : "")}");
Console.WriteLine();
}
}
}
}

View File

@@ -37,6 +37,9 @@ namespace DrillTools.Integration
// 检查是否是机台码 (0.499孔径)
bool isMachineCode = Math.Abs(tool.Diameter - 0.499) < 0.001;
// 获取当前刀具的孔位数据
var toolHoles = holesByTool.ContainsKey(tool.Number) ? holesByTool[tool.Number] : new List<HoleInfo>();
// 根据刀具类型设置
ToolType toolType;
if (isMachineCode)
@@ -45,17 +48,24 @@ namespace DrillTools.Integration
}
else
{
// 简化处理所有非机台码都设为Regular
// 实际应用中可以根据需要判断是否为槽孔
toolType = ToolType.Regular;
// 检查该刀具的孔位数据中是否包含G85槽孔
bool hasSlotHoles = false;
foreach (var hole in toolHoles)
{
if (hole.Type == HoleType.Slot)
{
hasSlotHoles = true;
break;
}
}
toolType = hasSlotHoles ? ToolType.Slot : ToolType.Regular;
}
// 计算刀具尾号类型和大类
var toolSuffixType = ToolItem.GetToolSuffixType(tool.Diameter);
var ToolCategory = ToolItem.GetToolCategory(toolSuffixType);
// 获取当前刀具的孔位数据
var toolHoles = holesByTool.ContainsKey(tool.Number) ? holesByTool[tool.Number] : new List<HoleInfo>();
var locations = new List<string>();
// 统计孔数并收集孔位坐标
@@ -89,6 +99,7 @@ namespace DrillTools.Integration
else
{
// 普通刀具和槽刀:正常处理
// 由于现在holes列表已经保持了原始顺序直接按顺序处理即可
foreach (var hole in toolHoles)
{
if (hole.Type == HoleType.Regular)
@@ -124,7 +135,7 @@ namespace DrillTools.Integration
// 为机台码刀具提取机台码命令和类型
string machineCodeCommand = string.Empty;
string machineCodeType = string.Empty;
if (isMachineCode)
{
// 从钻带内容中提取机台码信息
@@ -143,7 +154,7 @@ namespace DrillTools.Integration
{
machineCodeCommand = machineCodeMatch.Groups[1].Value; // M97或M98
machineCodeType = machineCodeMatch.Groups[2].Value; // A*或B*
// 添加日志验证机台码解析
System.Diagnostics.Debug.WriteLine($"[机台码解析] T{tool.Number:D2}: 命令={machineCodeCommand}, 类型={machineCodeType}");
}
@@ -230,10 +241,13 @@ namespace DrillTools.Integration
var toolPattern = $@"%.+?T{tool.Number:D2}(.*?)(?=T\d{{2}}|M30)";
var match = Regex.Match(drillTapeContent, toolPattern, RegexOptions.Singleline);
if (match.Success)
if (match.Success)//机台码
{
string holeSection = match.Groups[1].Value;
// 按行分割孔位数据,保持原始顺序
var lines = holeSection.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
// 查找机台码命令
var machineCodePattern = @"(M97|M98),(A\*|B\*),\$S \$N";
var machineCodeMatch = Regex.Match(holeSection, machineCodePattern);
@@ -246,10 +260,6 @@ namespace DrillTools.Integration
// 根据机台码类型确定孔数
int holeCount = (codeType == "A*") ? 57 : 58;
// 查找机台码坐标行
var coordinatePattern = @"X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)";
var coordinateMatches = Regex.Matches(holeSection, coordinatePattern);
// 添加机台码孔信息
for (int i = 0; i < holeCount; i++)
{
@@ -261,23 +271,33 @@ namespace DrillTools.Integration
});
}
// 这样可以确保坐标数据被正确保存到 ToolResult.Locations 中
foreach (Match coordMatch in coordinateMatches)
// 按原始顺序处理坐标行
foreach (var line in lines)
{
// 解析坐标
double x = double.Parse(coordMatch.Groups[1].Value);
double y = double.Parse(coordMatch.Groups[2].Value);
var trimmedLine = line.Trim();
if (string.IsNullOrEmpty(trimmedLine)) continue;
// 保存原始坐标字符串
string originalCoordString = coordMatch.Value;
// 检查是否是坐标行
var coordinatePattern = @"X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)";
var coordinateMatch = Regex.Match(trimmedLine, coordinatePattern);
// 添加一个特殊的孔位信息来保存实际坐标
holes.Add(new HoleInfo
if (coordinateMatch.Success)
{
ToolNumber = tool.Number,
Type = HoleType.Regular,
Position = new Point2D(x, y, originalCoordString)
});
// 解析坐标
double x = double.Parse(coordinateMatch.Groups[1].Value);
double y = double.Parse(coordinateMatch.Groups[2].Value);
// 保存原始坐标字符串
string originalCoordString = coordinateMatch.Value;
// 添加一个特殊的孔位信息来保存实际坐标
holes.Add(new HoleInfo
{
ToolNumber = tool.Number,
Type = HoleType.Regular,
Position = new Point2D(x, y, originalCoordString)
});
}
}
}
}
@@ -291,45 +311,48 @@ namespace DrillTools.Integration
if (match.Success)
{
string holeSection = match.Groups[1].Value;
// 先解析槽孔,并记录槽孔的起始坐标
var slotPattern = @"X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)G85X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)";
var slotMatches = Regex.Matches(holeSection, slotPattern);
var slotStartPositions = new System.Collections.Generic.HashSet<string>();
foreach (Match slotMatch in slotMatches)
// 按行分割孔位数据,保持原始顺序
var lines = holeSection.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var slot = SlotHoleCalculator.ParseLineSlotFromG85(slotMatch.Value, tool.Diameter);
holes.Add(new HoleInfo
{
ToolNumber = tool.Number,
Type = HoleType.Slot,
Slot = slot
});
// 记录槽孔的起始坐标,以便后续排除
string startPos = $"X{slotMatch.Groups[1].Value}Y{slotMatch.Groups[2].Value}";
slotStartPositions.Add(startPos);
}
// 解析普通圆孔(排除槽孔的起始坐标)
var regularHolePattern = @"X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)";
var regularMatches = Regex.Matches(holeSection, regularHolePattern);
foreach (Match regularMatch in regularMatches)
{
// 排除槽孔的起始坐标
if (!slotStartPositions.Contains(regularMatch.Value))
var trimmedLine = line.Trim();
if (string.IsNullOrEmpty(trimmedLine)) continue;
// 检查是否是槽孔G85指令
var slotPattern = @"X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)G85X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)";
var slotMatch = Regex.Match(trimmedLine, slotPattern);
if (slotMatch.Success)
{
// 处理槽孔
var slot = SlotHoleCalculator.ParseLineSlotFromG85(slotMatch.Value, tool.Diameter);
holes.Add(new HoleInfo
{
ToolNumber = tool.Number,
Type = HoleType.Regular,
Position = Point2D.ParseFromDrillString(regularMatch.Value)
Type = HoleType.Slot,
Slot = slot
});
}
}
else
{
// 检查是否是普通圆孔
var regularHolePattern = @"X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)";
var regularMatch = Regex.Match(trimmedLine, regularHolePattern);
// 解析槽孔(已在上面处理)
if (regularMatch.Success)
{
// 处理普通圆孔
holes.Add(new HoleInfo
{
ToolNumber = tool.Number,
Type = HoleType.Regular,
Position = Point2D.ParseFromDrillString(regularMatch.Value)
});
}
}
}
}
}
}
@@ -462,12 +485,12 @@ namespace DrillTools.Integration
public ToolType ToolType { get; set; }
public ToolSuffixType ToolSuffixType { get; set; }
public ToolCategory ToolCategory { get; set; }
/// <summary>
/// 机台码命令 (M97或M98)
/// </summary>
public string MachineCodeCommand { get; set; } = string.Empty;
/// <summary>
/// 机台码类型 (A*或B*)
/// </summary>
@@ -604,6 +627,7 @@ namespace DrillTools.Integration
result.Add($"T{tool.ToolNumber:D2}");
// 添加该刀具对应的所有坐标数据
// HoleLocations现在应该已经保持了原始顺序
if (tool.ToolType != ToolType.MachineCode && tool.HoleLocations != null && tool.HoleLocations.Count > 0)
{
foreach (var location in tool.HoleLocations)
@@ -620,6 +644,7 @@ namespace DrillTools.Integration
result.Add($"{tool.MachineCodeCommand},{tool.MachineCodeType},$S $N");
// 添加机台码的坐标数据
// HoleLocations现在应该已经保持了原始顺序
if (tool.HoleLocations != null && tool.HoleLocations.Count > 0)
{
foreach (var location in tool.HoleLocations)

View File

@@ -51,12 +51,19 @@
<!-- 主内容区域 -->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" MinWidth="400" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="120" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- 刀具列表 -->
<GroupBox Grid.Column="0" Header="刀具列表(可拖动排序)">
<GroupBox
Grid.RowSpan="2"
Grid.Column="0"
Header="刀具列表(可拖动排序)">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
@@ -142,8 +149,56 @@
</Grid>
</GroupBox>
<!-- 基础信息显示 -->
<GroupBox
Grid.Row="0"
Grid.Column="1"
Header="基础信息">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- 文件名单独一行 -->
<TextBlock
Grid.Row="0"
Text="{Binding FileNameWithoutExtension}"
VerticalAlignment="Center"
Margin="0,0,0,5"
FontWeight="Bold" />
<!-- 三个最小直径信息在同一行 -->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="最小钻咀:" VerticalAlignment="Center" />
<TextBlock Text="{Binding MinDrillDiameter, StringFormat=F3}" VerticalAlignment="Center" Margin="5,0,0,0" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<TextBlock Text="最小槽刀:" VerticalAlignment="Center" />
<TextBlock Text="{Binding MinSlotDiameter, StringFormat=F3}" VerticalAlignment="Center" Margin="5,0,0,0" />
</StackPanel>
<StackPanel Grid.Column="2" Orientation="Horizontal">
<TextBlock Text="最小EA刀" VerticalAlignment="Center" />
<TextBlock Text="{Binding MinEADiameter, StringFormat=F3}" VerticalAlignment="Center" Margin="5,0,0,0" />
</StackPanel>
</Grid>
</Grid>
</GroupBox>
<!-- 钻带内容显示 -->
<GroupBox Grid.Column="1" Header="钻带内容">
<GroupBox
Grid.Row="1"
Grid.Column="1"
Header="钻带内容">
<TextBox
Name="DrillTapeTextBox"
HorizontalScrollBarVisibility="Auto"

View File

@@ -195,16 +195,6 @@ namespace DrillTools
// 保存原始文件路径
ViewModel.OriginalFilePath = files[0];
Encoding ansiEncoding;
try
{
ansiEncoding = Encoding.GetEncoding(936); // 936是GB2312的代码页
}
catch
{
ansiEncoding = Encoding.Default; // 如果获取失败,使用系统默认编码
}
var process = new Process
{
StartInfo = new ProcessStartInfo
@@ -213,8 +203,7 @@ namespace DrillTools
Arguments = $"/c type \"{files[0]}\"",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
StandardOutputEncoding = ansiEncoding
CreateNoWindow = true
}
};

View File

@@ -26,6 +26,10 @@ namespace DrillTools
private bool _canMoveDown;
private string _originalFilePath = string.Empty;
private bool _isTopmost = true; // 默认置顶
private string _fileNameWithoutExtension = string.Empty;
private double _minDrillDiameter;
private double _minSlotDiameter;
private double _minEADiameter;
/// <summary>
/// 刀具列表
@@ -90,6 +94,16 @@ namespace DrillTools
{
// 当原始文件路径改变时,通知 HasOriginalFile 属性也已更改
OnPropertyChanged(nameof(HasOriginalFile));
// 更新文件名(不包含后缀)
if (!string.IsNullOrEmpty(value))
{
FileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(value);
}
else
{
FileNameWithoutExtension = string.Empty;
}
}
}
}
@@ -129,6 +143,42 @@ namespace DrillTools
/// </summary>
public string TopmostButtonText => IsTopmost ? "取消置顶" : "窗口置顶";
/// <summary>
/// 文件名(不包含后缀)
/// </summary>
public string FileNameWithoutExtension
{
get => _fileNameWithoutExtension;
set => SetProperty(ref _fileNameWithoutExtension, value);
}
/// <summary>
/// 最小钻咀直径
/// </summary>
public double MinDrillDiameter
{
get => _minDrillDiameter;
set => SetProperty(ref _minDrillDiameter, value);
}
/// <summary>
/// 最小槽刀直径
/// </summary>
public double MinSlotDiameter
{
get => _minSlotDiameter;
set => SetProperty(ref _minSlotDiameter, value);
}
/// <summary>
/// 最小EA刀直径
/// </summary>
public double MinEADiameter
{
get => _minEADiameter;
set => SetProperty(ref _minEADiameter, value);
}
/// <summary>
/// 从钻带内容加载刀具信息
/// </summary>
@@ -182,15 +232,26 @@ namespace DrillTools
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);
// 按行分割孔位数据,保持原始顺序
var lines = holeSection.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
toolItem.HoleLocations = new List<string>();
foreach (Match coordMatch in coordinateMatches)
// 按原始顺序处理坐标行
foreach (var line in lines)
{
toolItem.HoleLocations.Add(coordMatch.Value);
var trimmedLine = line.Trim();
if (string.IsNullOrEmpty(trimmedLine)) continue;
// 检查是否是坐标行
var coordinatePattern = @"X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)";
var coordinateMatch = System.Text.RegularExpressions.Regex.Match(trimmedLine, coordinatePattern);
if (coordinateMatch.Success)
{
toolItem.HoleLocations.Add(coordinateMatch.Value);
}
}
System.Diagnostics.Debug.WriteLine($"[机台码坐标] T{toolResult.ToolNumber:D2}: 找到{toolItem.HoleLocations.Count}个坐标");
@@ -218,6 +279,9 @@ namespace DrillTools
// 更新按钮状态
UpdateMoveButtonsState();
// 计算并更新最小直径信息
UpdateMinDiameterInfo();
// 检查并应用-sort.txt文件中的刀具排序
if (!string.IsNullOrEmpty(OriginalFilePath))
{
@@ -683,6 +747,7 @@ namespace DrillTools
result.Add($"T{tool.ToolNumber:D2}");
// 添加该刀具对应的所有坐标数据
// HoleLocations现在应该已经保持了原始顺序
if (tool.ToolType != ToolType.MachineCode && tool.HoleLocations != null && tool.HoleLocations.Count > 0)
{
foreach (var location in tool.HoleLocations)
@@ -699,6 +764,7 @@ namespace DrillTools
result.Add($"{tool.MachineCodeCommand},{tool.MachineCodeType},$S $N");
// 添加机台码的坐标数据
// HoleLocations现在应该已经保持了原始顺序
if (tool.HoleLocations != null && tool.HoleLocations.Count > 0)
{
foreach (var location in tool.HoleLocations)
@@ -866,6 +932,9 @@ namespace DrillTools
// 更新按钮状态
UpdateMoveButtonsState();
// 计算并更新最小直径信息
UpdateMinDiameterInfo();
// 加载示例钻带内容
DrillTapeContent = @"M48
@@ -1342,5 +1411,48 @@ M30";
{
IsTopmost = !IsTopmost;
}
/// <summary>
/// 更新最小直径信息
/// </summary>
private void UpdateMinDiameterInfo()
{
// 初始化为最大值,以便找到最小值
MinDrillDiameter = double.MaxValue;
MinSlotDiameter = double.MaxValue;
MinEADiameter = double.MaxValue;
foreach (var tool in Tools)
{
// 根据刀具类型分类计算最小直径
if (tool.ToolType == ToolType.Regular)
{
// 普通钻咀
if (tool.Diameter < MinDrillDiameter)
MinDrillDiameter = tool.Diameter;
}
else if (tool.ToolType == ToolType.Slot)
{
// 槽刀
if (tool.Diameter < MinSlotDiameter)
MinSlotDiameter = tool.Diameter;
// 检查是否是EA型槽刀尾号为2或6
if ((tool.ToolSuffixType == ToolSuffixType.EASlot || tool.ToolSuffixType == ToolSuffixType.EASlot2)
&& tool.Diameter < MinEADiameter)
MinEADiameter = tool.Diameter;
}
}
// 如果没有找到对应的刀具类型将值设为0
if (MinDrillDiameter == double.MaxValue)
MinDrillDiameter = 0;
if (MinSlotDiameter == double.MaxValue)
MinSlotDiameter = 0;
if (MinEADiameter == double.MaxValue)
MinEADiameter = 0;
}
}
}

View File

@@ -12,21 +12,21 @@ namespace DrillTools
public double X { get; set; }
public double Y { get; set; }
public string OriginalString { get; set; } // 存储原始坐标字符串
public Point2D(double x, double y)
{
X = x;
Y = y;
OriginalString = "";
}
public Point2D(double x, double y, string originalString)
{
X = x;
Y = y;
OriginalString = originalString;
}
/// <summary>
/// 从钻带坐标字符串创建点格式X+/-数字Y+/-数字)
/// </summary>
@@ -42,8 +42,9 @@ namespace DrillTools
}
throw new ArgumentException($"无效的钻带坐标格式: {drillString}");
}
public static Point2D operator +(Point2D p1, Point2D p2) => new Point2D(p1.X + p2.X, p1.Y + p2.Y);
public static Point2D operator -(Point2D p1, Point2D p2) => new Point2D(p1.X - p2.X, p1.Y - p2.Y);
}
@@ -55,14 +56,14 @@ namespace DrillTools
public Point2D StartPoint { get; set; }
public Point2D EndPoint { get; set; }
public double Width { get; set; } // 槽孔宽度/孔径单位mm
public LineSlot(Point2D startPoint, Point2D endPoint, double width)
{
StartPoint = startPoint;
EndPoint = endPoint;
Width = width;
}
/// <summary>
/// 获取槽孔长度
/// </summary>
@@ -79,7 +80,7 @@ namespace DrillTools
public Point2D CenterPoint { get; set; }
public double Width { get; set; } // 槽孔宽度/孔径单位mm
public bool CounterClockwise { get; set; } // 是否逆时针方向
public ArcSlot(Point2D startPoint, Point2D endPoint, Point2D centerPoint, double width, bool counterClockwise = false)
{
StartPoint = startPoint;
@@ -88,7 +89,7 @@ namespace DrillTools
Width = width;
CounterClockwise = counterClockwise;
}
/// <summary>
/// 获取弧段半径
/// </summary>
@@ -105,7 +106,7 @@ namespace DrillTools
/// 默认凸位高度值CAM350标准单位mm
/// </summary>
private const double DEFAULT_TOLERANCE = 0.0127;
/// <summary>
/// 计算线段槽孔的钻孔数量
/// </summary>
@@ -116,19 +117,19 @@ namespace DrillTools
{
// 计算孔半径
double radius = slot.Width / 2.0;
// 计算槽孔长度
double slotLength = slot.Length;
// 计算孔中心距
double holeCenterDistance = CalculateHoleCenterDistance(radius, tolerance);
// 计算孔数
int holeCount = (int)Math.Abs(Math.Floor(-slotLength / holeCenterDistance)) + 1;
return holeCount;
}
/// <summary>
/// 计算弧段槽孔的钻孔数量
/// </summary>
@@ -139,19 +140,19 @@ namespace DrillTools
{
// 计算孔半径
double radius = slot.Width / 2.0;
// 计算弧段长度
double arcLength = CalculateArcLength(slot);
// 计算孔中心距
double holeCenterDistance = CalculateHoleCenterDistance(radius, tolerance);
// 计算孔数
int holeCount = (int)Math.Abs(Math.Floor(-arcLength / holeCenterDistance)) + 1;
return holeCount;
}
/// <summary>
/// 计算线段槽孔的钻孔位置
/// </summary>
@@ -161,47 +162,47 @@ namespace DrillTools
public static List<Point2D> CalculateLineSlotHolePositions(LineSlot slot, double tolerance = DEFAULT_TOLERANCE)
{
List<Point2D> positions = new List<Point2D>();
// 计算孔半径
double radius = slot.Width / 2.0;
// 计算孔中心距
double holeCenterDistance = CalculateHoleCenterDistance(radius, tolerance);
// 计算槽孔长度
double slotLength = slot.Length;
// 计算孔数
int holeCount = CalculateLineSlotHoleCount(slot, tolerance);
// 计算方位角
double angle = CalculateAngle(slot.StartPoint, slot.EndPoint);
// 添加起点
positions.Add(slot.StartPoint);
// 计算中间点
if (holeCount > 2)
{
double avgDistance = slotLength / (holeCount - 1);
Point2D currentPoint = slot.StartPoint;
for (int i = 1; i < holeCount - 1; i++)
{
currentPoint = CalculateNextPoint(currentPoint, avgDistance, angle);
positions.Add(currentPoint);
}
}
// 添加终点
if (holeCount > 1)
{
positions.Add(slot.EndPoint);
}
return positions;
}
/// <summary>
/// 计算弧段槽孔的钻孔位置
/// </summary>
@@ -211,31 +212,31 @@ namespace DrillTools
public static List<Point2D> CalculateArcSlotHolePositions(ArcSlot slot, double tolerance = DEFAULT_TOLERANCE)
{
List<Point2D> positions = new List<Point2D>();
// 计算孔半径
double radius = slot.Width / 2.0;
// 计算孔中心距
double holeCenterDistance = CalculateHoleCenterDistance(radius, tolerance);
// 计算弧段半径
double arcRadius = slot.Radius;
// 计算弧段圆心角
double arcAngle = CalculateArcAngle(slot);
// 计算孔数
int holeCount = CalculateArcSlotHoleCount(slot, tolerance);
// 计算角度步长
double angleStep = arcAngle / (holeCount - 1);
// 计算起始角度
double startAngle = CalculateAngle(slot.CenterPoint, slot.StartPoint);
// 添加起点
positions.Add(slot.StartPoint);
// 计算中间点
if (holeCount > 2)
{
@@ -248,12 +249,12 @@ namespace DrillTools
{
currentAngle += angleStep;
}
for (int i = 1; i < holeCount - 1; i++)
{
Point2D point = CalculatePointOnArc(slot.CenterPoint, arcRadius, currentAngle);
positions.Add(point);
if (slot.CounterClockwise)
{
currentAngle -= angleStep;
@@ -264,16 +265,16 @@ namespace DrillTools
}
}
}
// 添加终点
if (holeCount > 1)
{
positions.Add(slot.EndPoint);
}
return positions;
}
/// <summary>
/// 从钻带G85命令解析线段槽孔
/// </summary>
@@ -291,7 +292,7 @@ namespace DrillTools
string startY = match.Groups[2].Value;
string endX = match.Groups[3].Value;
string endY = match.Groups[4].Value;
Point2D startPoint = new Point2D(
double.Parse(startX) / 1000.0,
double.Parse(startY) / 1000.0,
@@ -302,14 +303,14 @@ namespace DrillTools
double.Parse(endY) / 1000.0,
$"X{endX}Y{endY}"
);
return new LineSlot(startPoint, endPoint, width);
}
throw new ArgumentException($"无效的G85命令格式: {g85Command}");
}
// 辅助方法
/// <summary>
/// 计算两点间欧氏距离
/// </summary>
@@ -317,7 +318,7 @@ namespace DrillTools
{
return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
}
/// <summary>
/// 计算方位角(度数)
/// </summary>
@@ -325,14 +326,14 @@ namespace DrillTools
{
double angleRad = Math.Atan2(endPoint.Y - startPoint.Y, endPoint.X - startPoint.X);
double angleDeg = angleRad * 180.0 / Math.PI;
// 转换为0-360度范围
if (angleDeg < 0)
angleDeg += 360;
return angleDeg;
}
/// <summary>
/// 计算弧段长度
/// </summary>
@@ -343,7 +344,7 @@ namespace DrillTools
double angleRad = angleDeg * Math.PI / 180.0;
return radius * angleRad;
}
/// <summary>
/// 计算弧段圆心角(度数)
/// </summary>
@@ -351,7 +352,7 @@ namespace DrillTools
{
double startAngle = CalculateAngle(arc.CenterPoint, arc.StartPoint);
double endAngle = CalculateAngle(arc.CenterPoint, arc.EndPoint);
double angleSum;
if (arc.CounterClockwise)
{
@@ -367,10 +368,10 @@ namespace DrillTools
else
angleSum = Math.Abs(startAngle - endAngle);
}
return angleSum;
}
/// <summary>
/// 计算孔中心距
/// </summary>
@@ -378,7 +379,7 @@ namespace DrillTools
{
return Math.Sqrt(Math.Pow(radius, 2) - Math.Pow(radius - tolerance, 2)) * 2;
}
/// <summary>
/// 根据起点、距离和角度计算下一个点
/// </summary>
@@ -390,7 +391,7 @@ namespace DrillTools
startPoint.Y + distance * Math.Sin(angleRad)
);
}
/// <summary>
/// 根据圆心、半径和角度计算圆弧上的点
/// </summary>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +0,0 @@
M48
T01C3.050
T02C1.900
%
T01
X-154500Y549000
X154500Y562000
X154500Y038000
X-154500Y038000
T02
X045112Y593500
M30

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff