c++ - 如何在两条线之间画圆弧
问题描述
我当前的代码实现类似于所附图像。如何在垂直线(法线)和相交线(折射线和入射线)之间绘制弧线?我不知道该怎么做。弧必须更新以及折射线和入射线移动。
void SnellsLawWidget::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
painter.drawText(QPoint(width - 100, height / 2 + 20), "Interface");
painter.drawText(QPoint(width / 2 + 10, 20), "Normal");
painter.drawText(QPoint(100, height / 2 - 20), "n1");
painter.drawText(QPoint(100, height / 2 + 30), "n2");
painter.setPen(QPen(Qt::black, Qt::SolidLine));
painter.drawLine(0, height / 2, width, height / 2);
painter.setPen(QPen(Qt::green, Qt::DashLine));
painter.drawLine(width / 2, 0, width / 2, height);
QLineF incidenceLine;
painter.setPen(QPen(Qt::red, Qt::SolidLine));
incidenceLine.setP1(QPoint(width / 2, height / 2));
incidenceLine.setAngle(qreal(angleOfIncidence) + angleOffset);
incidenceLine.setLength(indexLength);
painter.drawLine(incidenceLine);
painter.drawText(QPoint(incidenceLine.x2(), incidenceLine.y2()), theta + QString("1"));
QLineF refractiveLine;
refractiveLine.setP1(QPoint(width / 2, height / 2));
refractiveLine.setAngle(qreal(angleOfRefraction) - angleOffset);
refractiveLine.setLength(indexLength);
painter.drawText(QPoint(refractiveLine.x2(), refractiveLine.y2()), theta + QString("2"));
painter.drawLine(refractiveLine);
}
解决方案
QPainter::drawPie() 将起作用,现在实现它会很头疼。
我不太确定哪个细节会导致头痛。
关于QPainter::drawPie()有一些事情你必须注意:
- 矩形描述了绘制饼图的完整椭圆的范围。
因此,如果a和b是椭圆的水平和垂直半径,并且cx cy是中心点,则矩形必须是QRect(cx - a, cy - b, 2 * a, 2 * b)
。 - 有一个以 16 度为单位的startAngle 。
如果角度 alpha 存储为浮点数,则 startAngle 可以通过 计算(int)(alpha * 16)
。 - spanAngle不是结束角度,而是作为第二个参数给出。跨度角是结束角和开始角的差。它也以 16 度数给出。
- 对于圆形饼图,只需将半径r用于a和b。
圆只是椭圆的一个特例。
例子:
#include <QtWidgets>
class PieWidget: public QWidget {
private:
int _alpha, _omega; // start/end angle in degree
public:
PieWidget(QWidget* pQParent = nullptr):
QWidget(pQParent)
{ }
virtual ~PieWidget() = default;
PieWidget(const PieWidget&) = delete;
PieWidget& operator=(const PieWidget&) = delete;
void setAngles(int alpha, int omega)
{
_alpha = alpha; _omega = omega;
update();
}
protected:
virtual QSize sizeHint() const override { return QSize(20, 20); }
virtual void paintEvent(QPaintEvent* pQEvent) override;
};
void PieWidget::paintEvent(QPaintEvent* pQEvent)
{
const int w = width(), h = height();
QPainter qPainter(this);
qPainter.setPen(Qt::blue);
qPainter.setBrush(Qt::yellow);
const int startAngle = _alpha * 16;
const int spanAngle = (_omega - _alpha) % 360 * 16;
qPainter.drawPie(0, 0, w, h, startAngle, spanAngle);
}
int main(int argc, char** argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup GUI
PieWidget qPie;
qPie.setWindowTitle("QPainter::pie()");
qPie.resize(256, 256);
qPie.show();
// setup animation
QTimer qTimer;
qTimer.setInterval(50); // 20/s seems reasonable
int alpha = 0, omega = 0;
QObject::connect(&qTimer, &QTimer::timeout,
[&]() {
qPie.setAngles(alpha, omega);
alpha += 10; alpha %= 360;
omega += 5; omega %= 360;
});
qTimer.start();
// runtime loop
return app.exec();
}
输出:
推荐阅读
- php - I want to make a filter of my selecting Data, using PHP and MySQL
- oracle - 触发语句的大小限制为 32KB
- wordpress - 通过加入WordPress从三个表中选择数据
- c# - Programmatically verify SNS topic permission to send messages to SQS (using IAM?)
- c# - 检查数据库表是否包含任何行
- javascript - 从文件中动态注入 ui-router 中的 js/css 文件
- rest - 实施 Acumatica REST API 时出错
- ios - 为 iOS 存档编译程序集文件时出现 Clang 错误
- r - dplyr mutate by row names
- azure - Can I use VSTS Release Manager to deploy a single web job under my app service without deploying the entire app service?