Answer the question
In order to leave comments, you need to log in
Bezier curve algorithm, how can I convert the code?
Found the code for implementing the Bezier curve. It did not start for me, I podshamanit it a little. In this code, a part of a Bezier curve is described in terms of another Bezier curve. And this other Bezier curve is already being drawn using conventional means, as I understand it. Is it possible to implement this algorithm in a simpler way, for example, to draw a curve right away? I tried to radically change everything, but it does not work.
Here is the code itself:
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QApplication>
#include <QWidget>
#include <QLabel>
#include <QSlider>
#include <QLayout>
#include <QPainter>
#include <QMouseEvent>
#include <QSignalMapper>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
public slots:
// from 0 to 100%
void setT0(int val) { setPart(0, 0.01*val); }
void setT1(int val) { setPart(1, 0.01*val); }
protected:
virtual void paintEvent(QPaintEvent *event);
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);
private:
int pointIdx(const QPointF& p);
void updatePart();
void setPart(int idx, qreal val);
QList<QPointF> pts;
QList<QPointF> ptsPart;
qreal t0, t1;
QPointF prev;
int movingIdx;
int overIdx;
Ui::Widget *ui;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
setMouseTracking(true);
pts << QPointF(50, 50) << QPointF(450, 100)
<< QPointF(350, 450) << QPointF(750, 500);
ptsPart = pts;
updatePart();
ui->setupUi(this);
}
const qreal r = 5.0;
void Widget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter painter(this);
painter.fillRect(0, 0, width(), height(), Qt::darkGray);
painter.setRenderHint(QPainter::Antialiasing);
// draw original bezier
painter.setPen(QPen(QBrush(Qt::white), 1.5));
painter.setBrush(Qt::NoBrush);
QPainterPath path(pts[0]);
path.cubicTo(pts[1], pts[2], pts[3]);
painter.drawPath(path);
// draw path for control points
path = QPainterPath(pts[0]);
path.lineTo(pts[1]);
path.lineTo(pts[2]);
path.lineTo(pts[3]);
QBrush b(Qt::yellow);
painter.setPen(QPen(b, 0.75));
painter.setBrush(Qt::NoBrush);
painter.drawPath(path);
// draw control points
QBrush b1(Qt::cyan);
painter.setPen(Qt::NoPen);
for (int idx = 0; idx < pts.size(); ++idx) {
painter.setBrush(idx == overIdx ? b1 : b);
painter.drawEllipse(pts[idx], r, r);
// draw part of original bezier
painter.setPen(QPen(QBrush(QColor(0, 255, 0, 100)), 12.0));
painter.setBrush(Qt::NoBrush);
path = QPainterPath(ptsPart[0]);
path.cubicTo(ptsPart[1], ptsPart[2], ptsPart[3]);
painter.drawPath(path);
}
}
void Widget::mousePressEvent(QMouseEvent *event)
{
if (movingIdx == -1 && event->button() == Qt::LeftButton) {
movingIdx = pointIdx(event->pos());
prev = event->pos();
}
}
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
if (movingIdx != -1 && event->button() == Qt::LeftButton)
movingIdx = -1;
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
if (movingIdx != -1) {
pts[movingIdx] += (event->pos() - prev);
updatePart();
prev = event->pos();
update();
} else {
int idx = pointIdx(event->pos());
if (idx != overIdx)
update();
overIdx = idx;
}
}
int Widget::pointIdx(const QPointF& p)
{
for (int idx = 0; idx < pts.size(); ++idx) {
if (QLineF(p, pts[idx]).length() <= 1.2*r)
return idx;
}
return -1;
}
void Widget::updatePart()
{
qreal u0 = 1.0 - t0;
qreal u1 = 1.0 - t1;
qreal x1 = pts[0].x();
qreal y1 = pts[0].y();
qreal x2 = pts[3].x();
qreal y2 = pts[3].y();
qreal bx1 = pts[1].x();
qreal by1 = pts[1].y();
qreal bx2 = pts[2].x();
qreal by2 = pts[2].y();
qreal qxa = x1*u0*u0 + bx1*2*t0*u0 + bx2*t0*t0;
qreal qxb = x1*u1*u1 + bx1*2*t1*u1 + bx2*t1*t1;
qreal qxc = bx1*u0*u0 + bx2*2*t0*u0 + x2*t0*t0;
qreal qxd = bx1*u1*u1 + bx2*2*t1*u1 + x2*t1*t1;
qreal qya = y1*u0*u0 + by1*2*t0*u0 + by2*t0*t0;
qreal qyb = y1*u1*u1 + by1*2*t1*u1 + by2*t1*t1;
qreal qyc = by1*u0*u0 + by2*2*t0*u0 + y2*t0*t0;
qreal qyd = by1*u1*u1 + by2*2*t1*u1 + y2*t1*t1;
ptsPart[0].setX(qxa*u0 + qxc*t0);
ptsPart[1].setX(qxa*u1 + qxc*t1);
ptsPart[2].setX(qxb*u0 + qxd*t0);
ptsPart[3].setX(qxb*u1 + qxd*t1);
ptsPart[0].setY(qya*u0 + qyc*t0);
ptsPart[1].setY(qya*u1 + qyc*t1);
ptsPart[2].setY(qyb*u0 + qyd*t0);
ptsPart[3].setY(qyb*u1 + qyd*t1);
}
void Widget::setPart(int idx, qreal val)
{
qreal& t = (idx == 0) ? t0 : t1;
t = val;
updatePart();
update();
}
Widget::~Widget()
{
delete ui;
}
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
QGridLayout* layout = new QGridLayout(&w);
layout->addWidget(new QLabel("t0:"), 0, 0);
layout->addWidget(new QLabel("t1:"), 1, 0);
QSlider* s0 = new QSlider(Qt::Horizontal);
QSlider* s1 = new QSlider(Qt::Horizontal);
layout->addWidget(s0, 0, 1);
layout->addWidget(s1, 1, 1);
s0->setRange(0, 100);
s1->setRange(0, 100);
Widget* widget = new Widget();
layout->addWidget(widget, 2, 0, 1, 2);
QObject::connect(s0, SIGNAL(valueChanged(int)), widget, SLOT(setT0(int)));
QObject::connect(s1, SIGNAL(valueChanged(int)), widget, SLOT(setT1(int)));
s0->setSliderPosition(20);
s1->setSliderPosition(75);
w.resize(800, 600);
w.show();
return a.exec();
}
Answer the question
In order to leave comments, you need to log in
The curve is given by four points, which is what happens in this algorithm.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question