C++ 绘制一个角并且在两角中间显示出具体的角度

137 篇文章 42 订阅
16 篇文章 2 订阅

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);
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wb175208

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值