1.先看一个效果:
2.理论基础
有两条直线l1(OM)和l2(ON)构成一个夹角∠MON,大小为α,顶点为O,以O为圆心r为半径做圆,交l1和l2分别为C点和D点。做∠α的角平分线与圆O交与点A,在圆O的3点钟方向做一条直线l4,过点A做l4的垂线,垂足为B。则矩形AEFG是圆O的内接矩形。A点位置就是要打印显示具体度数的位置。
1. 圆弧的所在圆的直径取线段OM和ON中较短的一个线段的一半。
2. 求出∠α的度数。根据以下函数计算出两条直线的角度。
3. 计算出∠AOB的度数,为下面求出其正余弦值做准备。
∠AOB=∠COB-∠α/2
4. 计算出线段AB和线段OB的长度。
5. 在内接矩形的长为2*OB=a,宽度为2*AB=b
6. 内接矩形左上角的坐标为:x = 圆心的横坐标 - a/2 ; y = 圆心的纵坐标 - b/2
7. 在具体的角度显示的位置:内接矩形的右上角也就是A的位置
3.函数说明
计算两条射线的角度:
#define PI 3.141592653589793
struct Vertex {
double x;
double y;
double z;
Vertex() {
x = 0.0;
y = 0.0;
z = 0.0;
}
};
// 以pt1为M点 pt2为N点 c为O点
double angleOfTwoVector(Vertex&pt1, Vertex&pt2, Vertex&c) {
double theta = atan2(pt1.x - c.x, pt1.y - c.y) - atan2(pt2.x - c.x, pt2.y - c.y);
if (theta > PI) {
theta -= 2 * PI;
}
if (theta < -PI) {
theta += 2 * PI;
}
theta = theta * 180.0 / PI;
return theta;
}
绘制角度:
//绘制角度
/*
void QPainter::drawArc(int x, int y, int width, int height, int startAngle, int spanAngle)
(1)以坐标(x,y)为起点,沿x轴正方向延伸w个 单位,沿y轴的正方向延伸h个单位,得到一个矩形,此虚拟矩形内切绘制一个椭圆(如果w和h相 等,则为圆)。
(2)以矩形的中心为圆心,以时钟3点的方向为0°,逆时针为正方向,从0°正方向旋转startAngle 度,和椭圆相交得到一条直线和一个交点。
(3)从这条直线开始,正方向旋转arcAngle度,得到另一条直线和交点,这样就得到了一个两交点之间的 圆弧。
*/
void MeasureAngle::drawAngle(QPainter*painter, QPoint screenStart, QPoint screenCenter, QPoint screenEnd) {
//计算两线之间的夹角
double angle = Utility::angleOfTwoVector(ptStart, ptEnd, ptCenter);
if (angle <= 0) {
angle = -angle;
} else {
double a = 180 - angle;
angle = 180 + a;
}
//计算弧线的起始角度
Vertex end;
end.x = ptCenter.x + 100;
end.y = ptCenter.y;
double startAngle = Utility::angleOfTwoVector(ptStart, end, ptCenter);
if (startAngle <= 0) {
startAngle = -startAngle;
} else {
double a = 180 - startAngle;
startAngle = 180 + a;
}
double firstLen = Utility::lenthOfTwoPoint(screenStart, screenCenter);
double secondLen = Utility::lenthOfTwoPoint(screenEnd, screenCenter);
double len = firstLen > secondLen ? secondLen : firstLen;
//绘制弧线
int x = screenCenter.x() - len / 2;
int y = screenCenter.y() - len / 2;
int w = len;
int h = len;
painter->drawArc(x, y, w, h, startAngle * 16, -angle * 16);
//显示坐标值
painter->setFont(font);
QString str = QString::number(angle, 10, 2);
str += QStringLiteral("°");
double centerAX = startAngle - angle / 2;//两条直线夹角的一般
double exrendLenX = cos(PI / 180 * centerAX)*(len/2);
double exrendLenY = sin(PI / 180 * centerAX)*(len/2);
//绘制外接矩形
#if 0
painter->drawRect(x, y, w, h);
#endif
int x0 = screenCenter.x() - exrendLenX;
int y0 = screenCenter.y() - exrendLenY;
int w0 = exrendLenX * 2;
int h0 = exrendLenY * 2;
#if 0//绘制内接矩形
painter->drawRect(x0, y0, w0, h0);
#endif
painter->drawText(x0 + w0 + 5, y0 -5, str);
}