0.圆相关公式
在笛卡尔坐标系上,一个标准的圆是这样的:
已知圆心坐标 (x0,y0),半径 R,角度 a,则圆边上点(x',y')的坐标为:
C 的三角函数参数为弧度,转换如下:
角度转弧度:
弧度转角度:
但我们知道,Qt 绘图是屏幕坐标系,起点在左上角,以右下角为正方向:
(可以把计算后的 y 取反来得到想要的效果)
1 void MainWindow::paintEvent(QPaintEvent *event) 2 { 3 event->accept(); 4 5 QPainter painter(this); 6 painter.setPen(QPen(Qt::red,2)); 7 //移动坐标中心点到窗口中心,默认左上角为起点,往右下为正方向 8 painter.translate(width()/2,height()/2); 9 //画一个圆,圆心为起点(上一步移动到的正中),半径100px 10 const int R=100; 11 painter.drawEllipse(QPoint(0,0),R,R); 12 //计算45度角圆边上的点,角度需要转换为弧度 13 const double a=qDegreesToRadians((double)45); 14 const int x=0+R*cos(a); 15 const int y=0+R*sin(a); 16 //因为屏幕坐标系y轴正方向和笛卡尔坐标系相反,所以y取反就是我们要的结果了 17 painter.drawLine(QPoint(0,0),QPoint(x,-y)); //y取反 18 }
运行结果:
1.椭圆相关公式
在笛卡尔坐标系上,一个标准的椭圆是这样的:
已知圆心坐标 (x0,y0),横轴 A(长半轴),竖轴 B(短半轴),角度 a,则圆边上点(x',y')的坐标为:
椭圆半径:
(可以发现,与普通圆相比,不考虑椭圆角度的话只是半径变化了,其他部分是一样的)
1 void MainWindow::paintEvent(QPaintEvent *event) 2 { 3 event->accept(); 4 5 QPainter painter(this); 6 painter.setPen(QPen(Qt::red,2)); 7 //移动坐标中心点到窗口中心,默认左上角为起点,往右下为正方向 8 painter.translate(width()/2,height()/2); 9 //画一个圆,圆心为起点(上一步移动到的正中),半径100px 10 const int A=150; //横轴 11 const int B=100; //竖轴 12 painter.drawEllipse(QPoint(0,0),A,B); 13 //计算45度角圆边上的点,角度需要转换为弧度 14 const double a=qDegreesToRadians((double)45); 15 const int R=A*B/sqrt(pow(A*sin(a),2)+pow(B*cos(a),2)); //计算对应角度的半径 16 const int x=0+R*cos(a); 17 const int y=0+R*sin(a); 18 //因为屏幕坐标系y轴正方向和笛卡尔坐标系相反,所以y取反就是我们要的结果了 19 painter.drawLine(QPoint(0,0),QPoint(x,-y)); //y取反 20 }
运行结果:
2.旋转矩阵
上面的角度都是从右侧开始,椭圆也是标准椭圆,如果我们想旋转一定角度来绘制,就需要用到我们的旋转矩阵了。
(本节主要来自参考博客)
已知 A(x,y) ,求旋转 a 角度后的 B(x’,y’) 坐标:
公式推导:
根据矩阵乘法计算规则,可以推出:
操作流程:
- 把图形的各点平移,令旋转中心平移至原点;
- 乘以旋转矩阵;
- 再平移至原来的旋转中心。
我们将上面椭圆的代码改一下,逆时针旋转 45 度:
1 2 void MainWindow::paintEvent(QPaintEvent *event) 3 { 4 event->accept(); 5 6 QPainter painter(this); 7 painter.setPen(QPen(Qt::red,2)); 8 //移动坐标中心点到窗口中心,默认左上角为起点,往右下为正方向 9 painter.translate(width()/2,height()/2); 10 //画一个圆,圆心为起点(上一步移动到的正中),半径100px 11 const int A=150; //横轴 12 const int B=100; //竖轴 13 painter.rotate(-45); //在屏幕坐标系,qpainter是顺时针转的 14 painter.drawEllipse(QPoint(0,0),A,B); 15 painter.rotate(45); 16 17 //计算45度角圆边上的点,角度需要转换为弧度 18 const double a=qDegreesToRadians((double)45); 19 const int R=A*B/sqrt(pow(A*sin(a),2)+pow(B*cos(a),2)); //计算对应角度的半径 20 const int x=0+R*cos(a); 21 const int y=0+R*sin(a); 22 //根据旋转矩阵计算 23 const double a2=qDegreesToRadians((double)45); 24 const int x2=x*cos(a2)-y*sin(a2); 25 const int y2=x*sin(a2)+y*cos(a2); 26 //因为屏幕坐标系y轴正方向和笛卡尔坐标系相反,所以y取反就是我们要的结果了 27 painter.drawLine(QPoint(0,0),QPoint(x2,-y2)); //y取反 28 }
运行结果:
(第一次计算的角度坐标是计算标准椭圆下的位置,第二次是根据椭圆的旋转角度做旋转得到的坐标)
(本来就有 45 度,从右侧逆时针旋转,再旋转 45 度就成了垂直向上了)
(虽然线可以直接 QPainter 旋转的方式绘制,但是这样文本也旋转了)
标签:求圆,椭圆,const,Qt,int,45,旋转,QPoint,painter From: https://www.cnblogs.com/ybqjymy/p/18111115