Files
AohDrllTools/SlotHoleCalculator.cs
2025-12-07 20:25:27 +08:00

406 lines
14 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.Text.RegularExpressions;
namespace DrillTools
{
/// <summary>
/// 二维点结构
/// </summary>
public struct Point2D
{
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>
public static Point2D ParseFromDrillString(string drillString)
{
var pattern = @"X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)";
var match = Regex.Match(drillString, pattern);
if (match.Success)
{
double x = double.Parse(match.Groups[1].Value) / 1000.0; // 转换为mm
double y = double.Parse(match.Groups[2].Value) / 1000.0; // 转换为mm
return new Point2D(x, y, drillString); // 保存原始字符串
}
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);
}
/// <summary>
/// 线段槽孔结构
/// </summary>
public struct LineSlot
{
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>
public double Length => Math.Sqrt(Math.Pow(StartPoint.X - EndPoint.X, 2) + Math.Pow(StartPoint.Y - EndPoint.Y, 2));
}
/// <summary>
/// 弧段槽孔结构
/// </summary>
public struct ArcSlot
{
public Point2D StartPoint { get; set; }
public Point2D EndPoint { get; set; }
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;
EndPoint = endPoint;
CenterPoint = centerPoint;
Width = width;
CounterClockwise = counterClockwise;
}
/// <summary>
/// 获取弧段半径
/// </summary>
public double Radius => Math.Sqrt(Math.Pow(StartPoint.X - CenterPoint.X, 2) + Math.Pow(StartPoint.Y - CenterPoint.Y, 2));
}
/// <summary>
/// 槽孔钻孔数量计算工具类
/// 提供与CAM350一致的槽孔孔数计算方法
/// </summary>
public static class SlotHoleCalculator
{
/// <summary>
/// 默认凸位高度值CAM350标准单位mm
/// </summary>
private const double DEFAULT_TOLERANCE = 0.0127;
/// <summary>
/// 计算线段槽孔的钻孔数量
/// </summary>
/// <param name="slot">线段槽孔参数</param>
/// <param name="tolerance">凸位高度值默认为0.0127mmCAM350标准</param>
/// <returns>需要的钻孔数量</returns>
public static int CalculateLineSlotHoleCount(LineSlot slot, double tolerance = DEFAULT_TOLERANCE)
{
// 计算孔半径
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>
/// <param name="slot">弧段槽孔参数</param>
/// <param name="tolerance">凸位高度值默认为0.0127mmCAM350标准</param>
/// <returns>需要的钻孔数量</returns>
public static int CalculateArcSlotHoleCount(ArcSlot slot, double tolerance = DEFAULT_TOLERANCE)
{
// 计算孔半径
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>
/// <param name="slot">线段槽孔参数</param>
/// <param name="tolerance">凸位高度值默认为0.0127mmCAM350标准</param>
/// <returns>钻孔位置列表</returns>
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>
/// <param name="slot">弧段槽孔参数</param>
/// <param name="tolerance">凸位高度值默认为0.0127mmCAM350标准</param>
/// <returns>钻孔位置列表</returns>
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)
{
double currentAngle = startAngle;
if (slot.CounterClockwise)
{
currentAngle -= angleStep;
}
else
{
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;
}
else
{
currentAngle += angleStep;
}
}
}
// 添加终点
if (holeCount > 1)
{
positions.Add(slot.EndPoint);
}
return positions;
}
/// <summary>
/// 从钻带G85命令解析线段槽孔
/// </summary>
/// <param name="g85Command">G85命令字符串格式XxxxYxxxG85XxxxYxxx</param>
/// <param name="width">槽孔宽度</param>
/// <returns>解析出的线段槽孔</returns>
public static LineSlot ParseLineSlotFromG85(string g85Command, double width)
{
var pattern = @"X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)G85X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)";
var match = Regex.Match(g85Command, pattern);
if (match.Success)
{
// 提取原始坐标字符串
string startX = match.Groups[1].Value;
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,
$"X{startX}Y{startY}"
);
Point2D endPoint = new Point2D(
double.Parse(endX) / 1000.0,
double.Parse(endY) / 1000.0,
$"X{endX}Y{endY}"
);
return new LineSlot(startPoint, endPoint, width);
}
throw new ArgumentException($"无效的G85命令格式: {g85Command}");
}
// 辅助方法
/// <summary>
/// 计算两点间欧氏距离
/// </summary>
private static double CalculateDistance(Point2D p1, Point2D p2)
{
return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
}
/// <summary>
/// 计算方位角(度数)
/// </summary>
private static double CalculateAngle(Point2D startPoint, Point2D endPoint)
{
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>
public static double CalculateArcLength(ArcSlot arc)
{
double radius = arc.Radius;
double angleDeg = CalculateArcAngle(arc);
double angleRad = angleDeg * Math.PI / 180.0;
return radius * angleRad;
}
/// <summary>
/// 计算弧段圆心角(度数)
/// </summary>
private static double CalculateArcAngle(ArcSlot arc)
{
double startAngle = CalculateAngle(arc.CenterPoint, arc.StartPoint);
double endAngle = CalculateAngle(arc.CenterPoint, arc.EndPoint);
double angleSum;
if (arc.CounterClockwise)
{
if (endAngle >= startAngle)
angleSum = 360 - Math.Abs(startAngle - endAngle);
else
angleSum = Math.Abs(startAngle - endAngle);
}
else
{
if (startAngle >= endAngle)
angleSum = 360 - Math.Abs(startAngle - endAngle);
else
angleSum = Math.Abs(startAngle - endAngle);
}
return angleSum;
}
/// <summary>
/// 计算孔中心距
/// </summary>
private static double CalculateHoleCenterDistance(double radius, double tolerance)
{
return Math.Sqrt(Math.Pow(radius, 2) - Math.Pow(radius - tolerance, 2)) * 2;
}
/// <summary>
/// 根据起点、距离和角度计算下一个点
/// </summary>
private static Point2D CalculateNextPoint(Point2D startPoint, double distance, double angleDeg)
{
double angleRad = angleDeg * Math.PI / 180.0;
return new Point2D(
startPoint.X + distance * Math.Cos(angleRad),
startPoint.Y + distance * Math.Sin(angleRad)
);
}
/// <summary>
/// 根据圆心、半径和角度计算圆弧上的点
/// </summary>
private static Point2D CalculatePointOnArc(Point2D centerPoint, double radius, double angleDeg)
{
double angleRad = angleDeg * Math.PI / 180.0;
return new Point2D(
centerPoint.X + radius * Math.Cos(angleRad),
centerPoint.Y + radius * Math.Sin(angleRad)
);
}
}
}