cannot make it work
the result is just wrong
Doesn't describe your problem very well.
Basically I don't know what is needed in terms of the concatenation/multiplications of matrices
In object store:
1. position
2. rotation
3. scale
When you need to draw object, perform operations in this order:
1. Scale using stored scale factor
2. Rotate using stored angle
3. Translate to position
Given scale factor s and rotation angle r, to rotate/scale object (point array, or whatever) around arbitrary point (p.x, p.y), do this:
1. Translate object to -p.x, -p.y . I.e. for every vertex do vertex -= p;
2. Scale object. For every vertex do vertex *= s
3. Rotate object. Rotate every vertex around point zero using angle r.
4. Translate object to p.x, p.y.
Also I'd recommend to take a look at "Affine Transformations" demo in Qt 4. To view demo, launch qtdemo, select "Demonstrations->Affine Transformations".
Consider hiring a geometry tutor. "Months" is too long to deal with rotate/scale/translate problem.
But, I have no clue on how to combine of these function in a proper order
If you're rotating and scaling around same point, the order of operations doesn't matter.
--EDIT--
Live example:
Points indicate pivot, start of transform, and end of transform.
Wireframe letters represent original image.
Red letter represent "rotate and uniformly scale" transform.
Green letters represent "2D scale" transform.
For both transform you need pivot, point where you began to drag shape, and point where you stopped dragging shape.
I will not ever explain this again.
transformtest.pro:
TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .
# Input
HEADERS += MainWindow.h
SOURCES += main.cpp MainWindow.cpp
main.cpp:
#include <QApplication>
#include "MainWindow.h"
int main(int argc, char** argv){
QApplication app(argc, argv);
MainWindow window;
window.show();
return app.exec();
}
MainWindow.h:
#ifndef MAIN_WINDOW_H
#define MAIN_WINDOW_H
#include <QGLWidget>
class QPaintEvent;
class MainWindow: public QWidget{
Q_OBJECT
public:
MainWindow(QWidget* parent = 0);
protected slots:
void updateAngle();
protected:
void paintEvent(QPaintEvent* ev);
float angle;
float distAngle;
};
#endif
MainWindow.cpp:
#include "MainWindow.h"
#include <QTimer>
#include <QPainter>
#include <QColor>
#include <QVector2D>
#include <math.h>
static const int timerMsec = 50;
static const float pi = 3.14159265f;
MainWindow::MainWindow(QWidget* parent)
:QWidget(parent), angle(0), distAngle(0){
QTimer* timer = new QTimer(this);
timer->start(timerMsec);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
connect(timer, SIGNAL(timeout()), this, SLOT(updateAngle()));
}
float randFloat(){
return (qrand()&0xFF)/255.0f;
}
float randFloat(float f){
return randFloat()*f;
}
inline QVector2D perp(const QVector2D v){
return QVector2D(-v.y(), v.x());
}
void MainWindow::updateAngle(){
angle = fmod(angle + pi*5.0f/180.0f, pi*2.0f);
distAngle = fmod(distAngle + pi*1.0f/180.0f, pi*2.0f);
}
QTransform buildRotateScale(QVector2D pivot, QVector2D start, QVector2D end){
QVector2D startDiff = start - pivot;
QVector2D endDiff = end - pivot;
float startLength = startDiff.length();
float endLength = endDiff.length();
if (startLength == 0)
return QTransform();
if (endLength == 0)
return QTransform();
float s = endLength/startLength;
startDiff.normalize();
endDiff.normalize();
QVector2D startPerp = perp(startDiff);
float rotationAngle = acos(QVector2D::dotProduct(startDiff, endDiff))*180.0f/pi;
if (QVector2D::dotProduct(startPerp, endDiff) < 0)
rotationAngle = -rotationAngle;
return QTransform().translate(pivot.x(), pivot.y()).rotate(rotationAngle).scale(s, s).translate(-pivot.x(), -pivot.y());
}
QTransform buildScale(QVector2D pivot, QVector2D start, QVector2D end){
QVector2D startDiff = start - pivot;
QVector2D endDiff = end - pivot;
float startLength = startDiff.length();
float endLength = endDiff.length();
if ((startDiff.x() == 0)||(startDiff.y() == 0))
return QTransform();
QVector2D s(endDiff.x()/startDiff.x(), endDiff.y()/startDiff.y());
return QTransform().translate(pivot.x(), pivot.y()).scale(s.x(), s.y()).translate(-pivot.x(), -pivot.y());
}
void MainWindow::paintEvent(QPaintEvent* ev){
QPainter painter(this);
QPointF pivot(width()/2, height()/2);
QPointF transformStart(pivot.x() + 100.0f, pivot.y() - 100.0f);
float r = sinf(distAngle)*100.0f + 150.0f;
QPointF transformEnd(pivot.x() + r*cosf(angle), pivot.y() - r*sinf(angle));
painter.fillRect(this->rect(), QBrush(QColor(Qt::white)));
QPainterPath path;
QString str(tr("This is a test!"));
QFont textFont("Arial", 40);
QFontMetrics metrics(textFont);
QRect rect = metrics.boundingRect(str);
path.addText(QPoint((width()-rect.width())/2, (height()-rect.height())/2), textFont, str);
painter.setPen(QColor(200, 200, 255));
painter.drawPath(path);
painter.setTransform(buildRotateScale(QVector2D(pivot), QVector2D(transformStart), QVector2D(transformEnd)));
painter.fillPath(path, QBrush(QColor(255, 100, 100)));
painter.setPen(QColor(100, 255, 100));
painter.setTransform(buildScale(QVector2D(pivot), QVector2D(transformStart), QVector2D(transformEnd)));
painter.fillPath(path, QBrush(QColor(100, 255, 100)));
painter.setTransform(QTransform());
QPainterPath coords;
r = 10.0f;
coords.addEllipse(pivot, r, r);
coords.addEllipse(transformStart, r, r);
coords.addEllipse(transformEnd, r, r);
painter.setPen(QPen(QBrush(Qt::red), 5.0f));
painter.setBrush(QBrush(QColor(127, 0, 0)));
painter.setPen(QPen(QBrush(Qt::green), 5.0f));
painter.drawLine(QLineF(pivot, transformStart));
painter.setPen(QPen(QBrush(Qt::blue), 5.0f));
painter.drawLine(QLineF(transformStart, transformEnd));
painter.setPen(Qt::red);
painter.drawPath(coords);
painter.end();
}