Russian Qt Forum
Май 08, 2024, 22:01 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: [Решено] Рисование в фоновом слое QGraphicsScene  (Прочитано 6200 раз)
surendil
Гость
« : Июнь 29, 2011, 17:28 »

Привет всем!
С графикой никогда не работал, а тут вот пришлось... Я поделюсь своими соображениями, а вы скажите, на правильном ли я пути, ок? Подмигивающий

Задача такая: нужно в фоне QGraphicsScene менять картинки с эффектом перехода "часовая стрелка" -- это когда старая картинка замещается новой по движению стрелки.

Для этого я организую два QImage: в первом будет хранится текущая картинка (назовём её Front), во втором (Back) -- следующая. Также будет таймер, по которому фрагменты из Back будут перерисовываться Front. Вообще, будет перерисовываться вся картинка (QPainter::drawImage), но будет QPainter::setClipRegion(QRegion(QPolygon(...))).

Потом в наследнике от сцены будет переопределена drawBackground, в котором будут перерисовываться куски Front.
« Последнее редактирование: Июль 04, 2011, 17:17 от surendil » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Июнь 29, 2011, 18:04 »

Ну здесь самое интересное как сделать переход "часовая стрелка" и особенно - антиалиас в месте перехода  Улыбающийся 
Записан
surendil
Гость
« Ответ #2 : Июнь 29, 2011, 18:38 »

Эмм.. полагаю, часовая стрелка -- это просто вращающийся сектор. Есть два угла, фиксированная длинна -- две полярные точки, только в прямоугольные координаты преобразовать -- и крути в своё удовольствие. Получившаяся "стрелка" определяет многоугольник, из которого делается clipRegion, а потом -- перерисовать из одного Image в другой.

Должно сработать наверное )

Да, ещё одно. Антиалиаса не надо, это не существенно  Оо
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Июнь 29, 2011, 19:09 »

Эмм.. полагаю, часовая стрелка -- это просто вращающийся сектор. Есть два угла, фиксированная длинна -- две полярные точки, только в прямоугольные координаты преобразовать -- и крути в своё удовольствие. Получившаяся "стрелка" определяет многоугольник, из которого делается clipRegion, а потом -- перерисовать из одного Image в другой.
Не вижу как здесь задействовать clip - больше мороки будет, да и в общем случае переход между 2-мя картинками требует полной перерисовки. А "полярные точки", "многоугольники", "clipRegion", "белка-стрелка" и.т.п. - все это здесь ни при чем, просто нужно

- работать с буферами имеджей напрямую
- ф-ция atan2 (math.h)

Без AA это все
Записан
surendil
Гость
« Ответ #4 : Июнь 29, 2011, 19:17 »

- работать с буферами имеджей напрямую
- ф-ция atan2 (math.h)

Поясните пожалуйста.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Июнь 29, 2011, 20:24 »

Пишу прямо здесь, если что отрихтуете
Код
C++ (Qt)
void TransitionClock( const QImage & src1, const QImage & src2, QImage & dst, qreal clock_angle_in_radian )
{
// все 3 имеджа должны быть ARGB 32 и иметь одинаковый размер
 int width = src1.width(), height = src1.height();
 qreal cntrX = width * 0.5, cntrY = height * 0.5;
 
 for (int y = 0; y < height; ++y) {
  const quint32 * p1 = (quint32 *) src1.scanLine(y);
  const quint32 * p2 = (quint32 *) src2.scanLine(y);
  quint32 * p3 = (quint32 *) dst.scanLine(y);
  for (int x = 0; x < width; ++x) {
   qreal pt_angle = atan2(cntrY - y, x - cntrX);
   pt_angle = PI * 0.5 - pt_angle;        // rotate direction = clockwise, start = north
   if (pt_angle < 0) pt_angle += PI * 2; // to range [0..PI *2]
   p3[x] = (pt_angle < clock_angle_in_radian) ? p2[x] : p1[x];
  }
 }
}
 
« Последнее редактирование: Июнь 30, 2011, 13:06 от Igors » Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #6 : Июнь 29, 2011, 20:29 »

а QTransform нынче не в моде?
Записан
ufna
Гость
« Ответ #7 : Июнь 29, 2011, 20:34 »

а QTransform нынче не в моде?

ну что вы! так же не интересно )
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Июнь 29, 2011, 20:40 »

А до чого тут QTransform если поворачивать нечего? Та и сделан тот QTransform через одно место.

Edit: а вот наверное "раскрутка по спирали" смотрелась бы поживее, интереснее. Ну там неск. строк добавить - разберется
« Последнее редактирование: Июнь 29, 2011, 20:53 от Igors » Записан
surendil
Гость
« Ответ #9 : Июнь 29, 2011, 21:06 »

Igors, я почти догнал что в вашем коде.. эх, надо было геометрию учить Веселый
Раскрутка по спирали здорово, подумаю Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Июнь 29, 2011, 22:18 »

эх, надо было геометрию учить Веселый
Да нормально Вы ее учили - просто не было "практики", и знания не применялись

Раскрутка по спирали здорово, подумаю Улыбающийся
Там несложно, если хотите объясню "на пальцах"
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #11 : Июнь 29, 2011, 22:43 »

Igors
кстати бигэндиан процессор над вами смеется:)
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Июнь 30, 2011, 13:05 »

Igors
кстати бигэндиан процессор над вами смеется:)
Пока я отработал на big endian больше чем на little, только на PPC от его рождения до самой кончины Улыбающийся  При присваивании одного (q)uint другому никаких дополнительных/неявных преобразований выполняться не будет, "источник" копируется в "приемник" как есть - на любом endian.
Записан
surendil
Гость
« Ответ #13 : Июль 04, 2011, 17:17 »

Код
C++ (Qt)
// start, end определяют треугольник, в пределах которого нужно обновить изображение
void BackgroundCanvas::rayMoved(qreal start, qreal end)
{
 // deg => rad
 start *= .01745329252;
 end *= .01745329252;
 
 // определить фрагмент изображения для обновления
 QPoint rayA = PPointF::toCartesian(start, qMin(m_height,m_width)/2).toPoint(); // полярные координаты
 QPoint rayB = PPointF::toCartesian(end, qMin(m_height,m_width)/2).toPoint();
 int x1 = qMin(0, qMin(rayA.x(), rayB.x())) + m_height/2;
 int x2 = qMax(0, qMax(rayA.x(), rayB.x())) + m_height/2;
 int y1 = qMin(0, qMin(rayA.y(), rayB.y())) + m_height/2;
 int y2 = qMax(0, qMax(rayA.y(), rayB.y())) + m_height/2;
 
 int x, y;
 
 for(y=y1; y<y2; ++y)
 {
   const quint32 *src = (quint32*) m_source->scanLine(y);
   quint32 *dst = (quint32*) m_destination->scanLine(y);
 
   for(x=x1; x<x2; ++x)
   {
     qreal angle_p = atan2(y-m_y0, x-m_x0);
     if( angle_p < 0 ) angle_p += 2. * M_PI;
     dst[x] = ( start < angle_p && angle_p <= end ) ? src[x] : dst[x] ;
     if( start > end )
       dst[x] = ( ( start <= angle_p && angle_p <= 2 * M_PI ) ||
                  ( 0. <= angle_p && angle_p <= end  ) ) ? src[x] : dst[x];
   }
 }
}
 

Спасибо вам за помощь! Веселый
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.103 секунд. Запросов: 22.