Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: Гурман от Октябрь 31, 2016, 22:21



Название: (РЕШЕНО) Что у меня не так с трансформациями?
Отправлено: Гурман от Октябрь 31, 2016, 22:21
Надо вращать и одновременно масштабировать QGraphicsItem. Вращение с помощью item->setRotation(angle) без проблем. Но масштабировать надо только по одному размеру (конкретно по высоте), а почему-то item->setScale(scale) только по обоим размерам пропорционально. Нет варианта item->setScale(scaleX, scaleY). Попытался сделать с помощью item->setTransformations(transformationsList). Получается какая-то ерунда.

Код:
    QGraphicsRotation rotator;
    rotator.setOrigin(QVector3D(item->mapToScene(itemOriginQPointF)));
    QGraphicsScale scaler;
    scaler.setOrigin(QVector3D(item->mapToScene(itemOriginQPointF)));
    qDebug()<<item->mapToScene(itemOriginQPointF);
    qreal angle = ............
    rotator.setAngle( angle );
    qDebug()<<angle;
    qreal scale = ...........
    scaler.setYScale( scale );
    qDebug()<<scale;
    qDebug()<<rotator.origin()<<rotator.angle()<<scaler.origin()<<scaler.yScale();
и вывод...
Код:
QPointF(575,220)
49.0028
0.754266
QVector3D(575, 220, 0) -10.9972 QVector3D(575, 220, 0) 1
И как же работать с этим? Разумеется, после item->setTransformations() ни вращение, ни масштабирование не верные.


Название: Re: Что у меня не так с трансформациями?
Отправлено: Old от Октябрь 31, 2016, 23:08
В документации по QTransform есть примеры с одновременным rotate и scale.


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Октябрь 31, 2016, 23:40
В документации по QTransform есть примеры с одновременным rotate и scale.

Там примеры другие, для paintEvent. И QTransform я так понял несколько для другого. Он не айтемы вращает и масштабирует, а системы координат. Я пробовал и им тоже - с первого раза отдельный айтем как надо повернуть и изменить не получилось. Крутит и масштабирует, но совершенно не так, как я ожидаю.


Название: Re: Что у меня не так с трансформациями?
Отправлено: Old от Октябрь 31, 2016, 23:45
Готовьте матрицу трансформаций и устанавливайте ее через
void QGraphicsItem::setTransform(const QTransform &matrix, bool combine = false)


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Октябрь 31, 2016, 23:51
Готовьте матрицу трансформаций и устанавливайте ее через
void QGraphicsItem::setTransform(const QTransform &matrix, bool combine = false)


Я так и сделал, получил не то вращение и масштабирование, которое ожидал.


Название: Re: Что у меня не так с трансформациями?
Отправлено: Old от Октябрь 31, 2016, 23:59
Я так и сделал, получил не то вращение и масштабирование, которое ожидал.
Пришлось встать и сесть за компьютер. :)

Код
C++ (Qt)
#include "widget.h"
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsSimpleTextItem>
#include <QVBoxLayout>
 
Widget::Widget( QWidget *parent ) :
QWidget( parent ),
m_view( new QGraphicsView( this ) )
{
QVBoxLayout *l = new QVBoxLayout;
l->addWidget( m_view );
setLayout( l );
 
QGraphicsScene *scene = new QGraphicsScene( this );
m_view->setScene( scene );
 
QGraphicsSimpleTextItem *item0 = new QGraphicsSimpleTextItem( tr( "Test string" ) );
scene->addItem( item0 );
 
QGraphicsSimpleTextItem *item1 = new QGraphicsSimpleTextItem( tr( "Test string" ) );
item1->setPos( 0, 20 );
item1->setTransform( QTransform().scale( 2, 1 ).rotate( 45 ) );
scene->addItem( item1 );
}
 


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Ноябрь 01, 2016, 00:04
И вас совершенно не смущает, что текст искажён???  :-[


Название: Re: Что у меня не так с трансформациями?
Отправлено: Old от Ноябрь 01, 2016, 00:07
И вас совершенно не смущает, что текст искажён???  :-[
Эээ чем искажен? И текст совершенно не причем, итем с текстом я выбрал только потому, что мне было лень искать картинку для примера. :)
Здесь элемент повернут и отмаштабирован.


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Ноябрь 01, 2016, 00:16
Пропорции текста изменились. Он стал "наклонным". Если ровный исходный текст увеличить и повернуть, буквы должны остаться перпендикулярными их основанию. А здесь они получились под углом к основанию. То есть, кроме масштабирования и поворота, получилось ещё и изменение соотношения сторон айтема. А мне не нужны искажения айтемов.

Текст вот так примерно должен выглядеть после изменений:



Название: Re: Что у меня не так с трансформациями?
Отправлено: Old от Ноябрь 01, 2016, 00:26
Так?


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Ноябрь 01, 2016, 00:29
Ну типа да


Название: Re: Что у меня не так с трансформациями?
Отправлено: Old от Ноябрь 01, 2016, 00:30
Ну типа да
Код
C++ (Qt)
item1->setTransform( QTransform().rotate( 45 ).scale( 2, 1 ) );
 


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Ноябрь 01, 2016, 00:41
Ну у меня примерно также...

Код:
    item->setTransform(QTransform().translate(rotationCenter.x(),rotationCenter.y()).
                       rotate(angle).scale(scaleX,scaleY).translate(-rotationCenter.x(),-rotationCenter.y()));

В результате при поворотах на большие углы айтем сильно искажается.

Красная стрелка в исходном состоянии направлена вверх, и совершенно симметрична вдоль своей оси. А вот что с ней происходит при поворотах влево и вправо:



Название: Re: Что у меня не так с трансформациями?
Отправлено: Old от Ноябрь 01, 2016, 00:56
В результате при поворотах на большие углы айтем сильно искажается.
Большие углы это какие? И что у вас за итем, как он искажается? Если можно со скриншотами.


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Ноябрь 01, 2016, 00:59
См. выше. На айтеме лежит QWidget - это стрелка. Другого пути нет потому что так надо. Если я меняю местами вращение и масштабирование, айтем тоже искажается, но в другую сторону.

Если использовать item->setRotation() и item->setScale(), то всё шикарно крутится как надо, но масштабируется по X и Y одновременно. А мне надо только длину стрелки изменить.

Если менять размеры QWidget, то ничего не происходит, очевидно фальш-айтем вычисляет размеры только при привязке виджета.

Хотя... надо ещё раз проверить...


Название: Re: Что у меня не так с трансформациями?
Отправлено: Old от Ноябрь 01, 2016, 01:04
См. выше. На айтеме лежит QWidget - это стрелка. Другого пути нет потому что так надо. Если я меняю местами вращение и масштабирование, айтем тоже искажается, но в другую сторону.
У QGraphicsView есть флаги renderHints,  с ними не игрались?

Мне лень 3 раз вставать к компьютеру, если не забуду, завтра посмотрю. У меня таких проблем не было.


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Ноябрь 01, 2016, 01:07
А при чём тут эти флаги? Я имею фокусы трансформации, а не рендеринга сцены. Я же сказал, если использовать прямой поворот и масштабирования айтема, всё почти как надо работает.


Название: Re: Что у меня не так с трансформациями?
Отправлено: Old от Ноябрь 01, 2016, 01:14
А при чём тут эти флаги? Я имею фокусы трансформации, а не рендеринга сцены. Я же сказал, если использовать прямой поворот и масштабирования айтема, всё почти как надо работает.
А вы можете прямоугольник нарисовать вокруг объекта, что лучше было видно искажение.


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Ноябрь 01, 2016, 01:18
Ну уже не сейчас - выключил станцию, на которой сборка делается. Спать пора...

Но там и так видно - при повороте влево у описывающего прямоугольника высота уменьшается, а при повороте вправо увеличивается. Ширина одинаковая. Если отключить масштабирование, оставить только поворот, то есть вот так:

Код:
item->setTransform(QTransform().translate(rotationCenter.x(),rotationCenter.y()).
                       rotate(angle).translate(-rotationCenter.x(),-rotationCenter.y()));

- то крутит нормально, без искажения.

Сильно подозреваю, что там есть какой-то мегакосяк внутренний, из-за которого item->setScale() может менять только оба размера сразу...  :-\


Название: Re: Что у меня не так с трансформациями?
Отправлено: Old от Ноябрь 01, 2016, 01:35
Кручу два прямоугольника, вроде никаких искажений нет.


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Ноябрь 01, 2016, 01:44
Если только крутить, то нет. Есть если крутить и масштабировать одновременно. Чтобы было заметнее, на айтем надо какую-нибудь картинку положить.


Название: Re: Что у меня не так с трансформациями?
Отправлено: Igors от Ноябрь 01, 2016, 04:47
Код
C++ (Qt)
tempScaleX = scaleX * cos(angle * M_PI / 180);
tempScaleY = scaleY * sin(angle * M_PI / 180);


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Ноябрь 01, 2016, 13:43
Не спасает. Искажения по-прежнему есть.


Название: Re: Что у меня не так с трансформациями?
Отправлено: ssoft от Ноябрь 01, 2016, 15:12
- перемещаем центр масштабирования/вращения в начало координат
Код:
.translate(-x,-y)
- выполняем масштабирование
Код:
.scale(scale_x, scale_y)
- при этом понимаем, что при scale_x != scale_y исходный item будет сплюснут или вытянут по осям; то есть, если стрелка изначально находится под некоторым углом, то сначала нужно развернуть ее обратно в вертикальное или горизонтальное направление.
Код:
.rotate(-arrow_angle)
- вращаем как нам заблагорассудиться
Код:
.rotate(array)
- перемещаем результат в исходное состояние
Код:
.translate(x,y)

В итоге имеем

Код
C++ (Qt)
item->setTransform( QTransform().translate(x, y).rotate(angle).scale(scale_x, scale_y).rotate(-arrow_angle).translate(-x,-y) );
 

Все трансформации реализуют линейную матричную алгебру, навряд ли там есть ошибки.


Название: Re: Что у меня не так с трансформациями?
Отправлено: Igors от Ноябрь 01, 2016, 15:48
Что-то не могу воспроизвести проблему, не получаю искажений (аттач)


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Ноябрь 01, 2016, 15:53
Кажется я нашёл в чём проблема. От старого кода остался в инициализации начальный поворот с помощью setRotation. А setTransform про него понятия не имеет. Вычитал в каком-то форуме, что в Qt сохранились и работают два совершенно разных канала вращения и масштабирования айтемов. Один из них новый, другой старый, работают совершенно по-разному, и никак друг с другом не согласуются. Я вот тоже не припомню, чтобы в Qt 3 были два способа вращать - напрямую и с помощью матриц трансформации. Достаточно давно это было, 10 лет назад, но помню что проблем не возникало.


Название: Re: Что у меня не так с трансформациями?
Отправлено: Igors от Ноябрь 01, 2016, 16:12
В итоге имеем

Код
C++ (Qt)
item->setTransform( QTransform().translate(x, y).rotate(angle).scale(scale_x, scale_y).rotate(-arrow_angle).translate(-x,-y) );
 

Все трансформации реализуют линейную матричную алгебру, навряд ли там есть ошибки.
Читать эту соплю надо справа налево (как в гребаном OpenGL), т.е. последняя операция выполняется первой. Это не очень удобно/естественно, линейная алгебра к этому не обязывает

Да, и зачем второе вращение? Просто
Код
C++ (Qt)
item->setTransform( QTransform().translate(x, y).rotate(angle).scale(scale_x, scale_y).translate(-x,-y) );


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Ноябрь 01, 2016, 17:53
В общем, да, работает как надо, если перед этим не поворачивать айтем с помощью setRotation. Заменил на поворт трансформацией, вроде проблема пропала
 


Название: Re: Что у меня не так с трансформациями?
Отправлено: Гурман от Ноябрь 01, 2016, 17:54
зачем второе вращение? Просто

...он похоже обсуждение не читал...