当前位置: 首页 > news >正文

计算圆弧的起始角度、终止角度和矩形信息并使用drawArc绘制圆弧

Qt中常用绘制圆弧的库函数:

//函数原型
void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)

Qt规定1°约占16个像素,比如一个完整的圆等于360度,对应的像素角度就是 5760度(16 * 360)。

正值的角度表示逆时针方向,而负值的角度表示顺时针方向。因此,如果你指定正值的 startAngle 和 spanAngle,那么绘制的弧形将是逆时针方向的;如果是负值,那么绘制的弧形将是顺时针方向的。0度位于时钟的 3 点钟位置。这意味着,如果 startAngle 为零,弧形的起始点将位于圆的最右侧,然后按照逆时针方向绘制。

例如:

QRectF rectangle(10.0, 20.0, 80.0, 60.0);
int startAngle = 30 * 16;
int spanAngle = 120 * 16;QPainter painter(this);
painter.drawArc(rectangle, startAngle, spanAngle);

计算drawArc函数所需的startAngle,spanAngle和rectangle

自定义复数类,用于计算参数信息的时候使用
//ComplexNum.h
class ComplexNum
{
public:ComplexNum();ComplexNum(double a, double b);public://复数的四则运算ComplexNum operator +(const ComplexNum& num);ComplexNum operator -(const ComplexNum& num);ComplexNum operator *(const ComplexNum& num);ComplexNum operator /(const ComplexNum& num);//其他函数,设置和取模void setComplexNumValue(double a, double b);double getComplexNumMold();double A();double B();private:double a, b;
};//ComplexNum.cpp
ComplexNum::ComplexNum() :a(0), b(0)
{}ComplexNum::ComplexNum(double a, double b) {this->a = a;this->b = b;
}//复数的四则运算
ComplexNum ComplexNum::operator +(const ComplexNum& num) {return ComplexNum(this->a + num.a, this->b + num.b);
}ComplexNum ComplexNum::operator -(const ComplexNum& num) {return ComplexNum(this->a - num.a, this->b - num.b);
}//复数的相乘(a+bi)(c+di)=(ac-bd)+(bc+ad)i两个复数的积仍然是一个复数
ComplexNum ComplexNum::operator *(const ComplexNum& num) {return ComplexNum(this->a * num.a - this->b * num.b, this->b * num.a + this->a * num.b);
}//复数的除法
ComplexNum ComplexNum::operator /(const ComplexNum& num) {if (!num.a && !num.b) {return ComplexNum(a, b);}else {return ComplexNum((a * num.a + b * num.b) / (num.a * num.a + num.b * num.b),(b * num.a - a * num.b) / (num.a * num.a + num.b * num.b));}
}//其他函数,设置和取模
void ComplexNum::setComplexNumValue(double a, double b) {this->a = a;this->b = b;
}double ComplexNum::getComplexNumMold() {return sqrt(a * a + b * b);
}double ComplexNum::A() {return this->a;
}
double ComplexNum::B() {return this->b;
}//定义圆弧信息结构体,计算圆弧信息的函数返回该结构体对象
struct ArcInfo
{double startAngle;double spanAngle;QRectF rectangle;
};//计算圆弧信息的函数
ArcInfo PixelConversionLibrary::CalculateArc(QPointF start, QPointF end, QPointF center, bool isAcw)
{//计算画弧所需的参数有3个:起始角度、夹角、外切矩形double startAngle = 0, spanAngle = 0;QRectF rectangle;//定义起始向量和终止向量QPointF startVector = start - center;QPointF endVector = end - center;//构建两个复数,一个是起点的复数,一个是终点的复数,两者相除即得到旋转子的复数//乘以一个模为1的复数时,不会导致缩放,只会产生旋转,这样的复数就称为旋转子(rotor)//逆时针:*旋转子(cos(θ)+sin(θ)i)   顺时针:*旋转子的共轨复数(cos(θ)-sin(θ)i)//默认逆时针角度为正,顺时针为负//若span角为0,说明弧是一个整圆,spanAngle需修正为360°ComplexNum c1(startVector.x(), startVector.y());ComplexNum c2(endVector.x(), endVector.y());//ComplexNum rotor = c2 / c1;ComplexNum rotor = c1 / c2;if (isAcw) {spanAngle = qAtan2(rotor.B(), rotor.A());if (spanAngle < 0) {spanAngle += 2 * PI;}}else {spanAngle = -qAtan2(-rotor.B(), rotor.A());if (spanAngle > 0) {spanAngle -= 2 * PI;}}if (fabs(spanAngle) < 0.0001)spanAngle = 2 * PI;//计算起始角c1.setComplexNumValue(1, 0);c2.setComplexNumValue(startVector.x(), startVector.y());//rotor = c2 / c1;rotor = c1 / c2;startAngle = qAtan2(rotor.B(), rotor.A());//弧度转角度spanAngle = spanAngle * (180 / PI);startAngle = startAngle * (180 / PI);double r = sqrtf(pow(startVector.x(), 2) + pow(startVector.y(), 2));QPointF upperLeftPointOfRect = QPointF(center.x() - r, center.y() - r);rectangle.setRect(upperLeftPointOfRect.x(), upperLeftPointOfRect.y(), 2 * r, 2 * r);return { startAngle, spanAngle, rectangle };
}//调用
ArcInfo arcInfo = CalculateArc(pixelStartPoint, pixelEndPoint, pixelCenter, true);
painter.drawArc(arcInfo.rectangle, arcInfo.startAngle * 16, arcInfo.spanAngle * 16);

注意,CalculateArc函数的参数传递的必须都是像素值,这样算出的矩形信息才是像素信息,但是算出的角度依然是实际角度,需要乘以16转化为像素角度。

http://www.lryc.cn/news/275165.html

相关文章:

  • C++ Trie树模版 及模版题 || Trie字符串统计
  • Linux基础命令@echo、tail、重定向符
  • uniapp:签字版、绘画板 插件l-signature
  • Python Pillow(PIL)库的用法介绍
  • uniapp 【专题详解 -- 时间】云数据库时间类型设计,时间生成、时间格式化渲染(uni-dateformat 组件的使用)
  • k8s之flink的几种创建方式
  • 应用OpenCV绘制箭头
  • 信息学奥赛一本通1032:大象喝水查
  • 聊聊jvm的direct buffer统计
  • C/C++ 位段
  • Peter算法小课堂—树的应用
  • FineBI:简介
  • 原神单机版【完全无脑搭建】⭐纯单机⭐*稳定版*
  • 用通俗易懂的方式讲解:万字长文带你入门大模型
  • Invalid options in vue.config.js: “plugins“ is not allowed
  • 四、C语言中的数组:数组的创建与初始化
  • html5中各标签的语法格式总结以及属性值说明
  • 力扣(leetcode)第412题Fizz Buzz(Python)
  • 苦学golang半年,写了一款web服务器
  • uniapp vue2 车牌号输入组件记录
  • Unity 点击对话系统(含Demo)
  • vue接入高德地图
  • Linux的基本指令(5)
  • 华为商城秒杀时加密验证 device_data 的算法研究
  • Wrk压测发送Post请求的正确姿势
  • 【管理篇 / 登录】❀ 06. macOS下使用USB配置线登录 ❀ FortiGate 防火墙
  • linux系统shell语言的自动化交互
  • HarmonyOS ArkTS 三方库的基本使用(十六)
  • Spring boot封装rocket mq 教程
  • Java Swing手搓童年坦克大战游戏(I)