Qt中辅助actTo()来绘制圆弧的辅助函数

一 问题描述:

由于Qt所支持的绘制圆弧的函数如下所示:



所需要的输入值是:圆弧所在的矩形(左上角点,宽度,高度)、入射点的初始角度、入射点与出射点之间的发散角度。且其中角度逆时针为正,顺时针为负。

而我们绘制圆弧时候所调用的值只有坐标点的五个属性值,故需要根据两点的属性值,设计一个算法以实现圆弧线段的绘制。

二 算法说明

下图是相关参数点和计算公式的说明:


入射点(x1,y1);出射点(x2,y2);圆心(x,y)

初始夹角startAngle;发散角spanAngle

顺时针弧为z=1,逆时针狐为z=2

入射点与出射点连线的中点(a,b)。

//用于生成绘制圆弧所需的参数,输入为(点1,点2,圆心,插补类型)
void Widget::arcDrawing(double x1, double y1, double x2, double y2, double x, double y, double z)

2.1 矩形推导

//确定圆弧所在矩形
    double r=sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2));
    rect.setRect(x-r,y-r,2*r,2*r);//因为坐标系是相反的,所以是y-r。!!矩形高和宽是2*r


2.2 转换为真实坐标进行计算

由于我容器中的数据是根据界面坐标设定的,故需转化为真实坐标进行计算

//转换为真实坐标进行角度计算
    double y1_real=ui->graphicsView->height()-y1;
    double y2_real=ui->graphicsView->height()-y2;
    double y_real=ui->graphicsView->height()-y;


2.3 初始夹角的推导

//确定startAngle
    //点1在上方
    if(y1_real>=y_real){
        if(x1<x)      startAngle=180-180*qAtan((y_real-y1_real)/(x1-x))/PI;
        else if(x1==x) startAngle=90;
        else if(x1>x) startAngle=180*qAtan((y1_real-y_real)/(x1-x))/PI;
    }
    //点1在下方
    else{
        if(x1<x)      startAngle=180*qAtan((y1_real-y_real)/(x1-x))/PI-180;
        else if(x1==x) startAngle=-90;
        else if(x1>x) startAngle=180*qAtan((y1_real-y_real)/(x1-x))/PI;
    }


2.4 发散角的推导

//确定spanAngle
    //中心计算
    double a=(x1+x2)/2;
    double b=(y1_real+y2_real)/2;
    //入射点x1与圆心位于同一垂线,斜率不存在
    if(x1==x){
        //点1在圆心下面
        if(y1_real<y_real){
            //若为逆时针插补
            if(z==2){
                if(x2>x1)spanAngle=2*180*qAtan(sqrt((a-x2)*(a-x2)+(b-y2_real)*(b-y2_real))/sqrt((a-x)*(a-x)+(b-y_real)*(b-y_real)))/PI;
                if(x2==x1)spanAngle=180;
                if(x2<x1)spanAngle=360-2*180*qAtan(sqrt((a-x2)*(a-x2)+(b-y2_real)*(b-y2_real))/sqrt((a-x)*(a-x)+(b-y_real)*(b-y_real)))/PI;
            }
            //若为顺时针插补
            if(z==1){
                if(x2>x1)spanAngle=360-2*180*qAtan(sqrt((a-x2)*(a-x2)+(b-y2_real)*(b-y2_real))/sqrt((a-x)*(a-x)+(b-y_real)*(b-y_real)))/PI;
                if(x2==x1)spanAngle=-180;
                if(x2<x1)spanAngle=-2*180*qAtan(sqrt((a-x2)*(a-x2)+(b-y2_real)*(b-y2_real))/sqrt((a-x)*(a-x)+(b-y_real)*(b-y_real)))/PI;
            }
        }
        //点1在圆心上面
        else{
            //若为逆时针插补
            if(z==2){
                if(x2<x1)spanAngle=360-2*180*qAtan(sqrt((a-x2)*(a-x2)+(b-y2_real)*(b-y2_real))/sqrt((a-x)*(a-x)+(b-y_real)*(b-y_real)))/PI;
                if(x2==x1)spanAngle=180;
                if(x2>x1)spanAngle=2*180*qAtan(sqrt((a-x2)*(a-x2)+(b-y2_real)*(b-y2_real))/sqrt((a-x)*(a-x)+(b-y_real)*(b-y_real)))/PI;
            }
            //若为顺时针插补
            if(z==1){
                if(x2<x1)spanAngle=-2*180*qAtan(sqrt((a-x2)*(a-x2)+(b-y2_real)*(b-y2_real))/sqrt((a-x)*(a-x)+(b-y_real)*(b-y_real)))/PI;
                if(x2==x1)spanAngle=-180;
                if(x2>x1)spanAngle=360-2*180*qAtan(sqrt((a-x2)*(a-x2)+(b-y2_real)*(b-y2_real))/sqrt((a-x)*(a-x)+(b-y_real)*(b-y_real)))/PI;
 
            }
        }
else{
        double D=y2-(y1_real-y_real)*(x2-x)/(x1-x)-y_real;
        qDebug()<<D;
        //若为逆时针插补
        if(z==2){
            if(D>0)spanAngle=2*180*qAtan(sqrt((a-x2)*(a-x2)+(b-y2_real)*(b-y2_real))/sqrt((a-x)*(a-x)+(b-y_real)*(b-y_real)))/PI;
            if(D==0)spanAngle=180;
            if(D<0)spanAngle=360-2*180*qAtan(sqrt((a-x2)*(a-x2)+(b-y2_real)*(b-y2_real))/sqrt((a-x)*(a-x)+(b-y_real)*(b-y_real)))/PI;
        }
        //若为顺时针插补
        else if(z==1){
            if(D>0)spanAngle=-2*180*qAtan(sqrt((a-x2)*(a-x2)+(b-y2_real)*(b-y2_real))/sqrt((a-x)*(a-x)+(b-y_real)*(b-y_real)))/PI;
            if(D==0)spanAngle=-180;
            if(D<0)spanAngle=2*180*qAtan(sqrt((a-x2)*(a-x2)+(b-y2_real)*(b-y2_real))/sqrt((a-x)*(a-x)+(b-y_real)*(b-y_real)))/PI-360;
        }
     }



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值