C# | GDI+图像测距辅助线的实现思路
C# | GDI+图像测距辅助线的实现思路
一、辅助线需求概述
在图像测量工具中,动态辅助线的数值标签需要满足两个核心要求:其一,标签方向需与辅助线走向保持一致;其二,无论辅助线处于何种角度,文本必须保持正面朝上显示。
二、坐标系与角度计算
2.1 笛卡尔坐标系
在屏幕坐标系中,Y轴方向与数学坐标系相反(向下为正方向)。两点间连线形成的角度范围在-π到π之间,对应屏幕空间的360度方向。
2.2 线长和角度计算方法
计算两点之间的距离:
double length = Math.Sqrt(Math.Pow(endPoint.X - startPoint.X, 2) + Math.Pow(endPoint.Y - startPoint.Y, 2));
计算线的反正切值,Math.Atan2 返回的值在 (-π, π] 之间,用于表示线的方向:
double atan = Math.Atan2(endPoint.Y - startPoint.Y, endPoint.X - startPoint.X);
2.3 文本角度矫正计算方法
调整反正切值,以确保显示的长度文本始终保持向上的方向。如果反正切值的绝对值大于 π/2,说明线的倾斜方向可能导致文本倒着显示。
此时通过 -(Math.PI - atan) 来调整反正切值,使其对应的文本方向向上。
atan = Math.Abs(atan) > Math.PI / 2 ? -(Math.PI - atan) : atan;
2.4 坐标变换实现步骤
- 平移坐标系至线段中点
- 应用旋转变换
- 垂直偏移避免覆盖线段
关键代码段:
// 计算中点位置
PointF midPoint = new PointF((startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2);
// 调整原点至两点中心
g.TranslateTransform(midPoint.X, midPoint.Y);
g.RotateTransform((float)(atan * 180 / Math.PI));
三、与if判断方式对比
使用if连环判断不但啰嗦还存在除零风险。
if (deltaX >= 0 && deltaY >= 0) // 第一象限
{
angle = Math.Atan(deltaY / deltaX);
}
else if (deltaX <= 0 && deltaY >= 0) // 第二象限
{
angle = Math.PI - Math.Atan(deltaY / -deltaX);
}
// 三、四...
四、总结
通过坐标变换矩阵验证法可检测实现效果:
- 当辅助线处于水平方向(0度)时,旋转角度为0
- 当辅助线垂直向上(-90度)时,实际应用90度旋转
- 当辅助线倾斜135度时,自动校正为-45度显示
综上,在0-360度全范围内均能保持文本正向显示,感谢阅读。