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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: [qwt] Производительность при перерисовки графика  (Прочитано 15578 раз)
carhun
Гость
« : Октябрь 31, 2012, 06:00 »

Добрый день.

Есть следующая проблема:
У меня есть набор QwtPlot'ов, их к-во может сколько угодно, но допустим сейчас их у меня до 100 штук. На каждом из этих QwtPlot'ов может быть по 1-5 кривых и у каждой кривой получается в среднем по 200 000 точек, бывает и под миллион. Собственно, и тогда возникает проблема, что когда я допустим хочу прокрутить все графики, то приходится вызвать setAxisScale(QwtPlot::xBottom, min, max), к-ый за собой потянет вызов replot(), к-ый естственно будет выполнятся ну очень с большими лагами для такого к-во точек и графиков....

Пробывал делать через QwtPlotPanner он тоже не сильно помог, пока дергаешь график туда-сюда оно хорошо не глючит, а когда отпускаешь график, так я понял, там опять вызвается replot() и все таже беда...

Собственно, какие есть способы улучшить производительность? Слишком накладно получается каждый раз вызывать replot() ... Ну или может я вообще ошибаюсь и не в replot'e дело...
Записан
mutineer
Гость
« Ответ #1 : Октябрь 31, 2012, 10:29 »

Может стоит уменьшить количество точек, по которым рисуется кривая? 200000 на экране все равно не видно
Записан
carhun
Гость
« Ответ #2 : Октябрь 31, 2012, 11:30 »

На сколько я понял qwt сама отрисовует только нужную ей часть, у меня точки отобраны так что бы они шли раз в 3 пикселя, а дальше я все это скармилваю ф-ии setSamples() для кривой. и на сколько я понимаю она дальше отрисовует только ту часть, что я указываю при axisScaleX(...).
« Последнее редактирование: Октябрь 31, 2012, 11:42 от carhun » Записан
Akon
Гость
« Ответ #3 : Декабрь 17, 2013, 19:49 »

Подниму вопрос.

Допустим, в плоте у кривой отображается большое кол-во данных, 1000000, например. Далее, приходит новая порция размером в 100000. Необходимо, сдвинуть кривую, т.е. эти новые данные отобразить слева, а самые старые данные (те, что справа) выкинуть. Если не рассматривать искусственное уменьшение данных, то каким образом достичь максимального быстродействия?

Если поразмышлять, то кривая могла бы делать кэш (QPixmap), далее отсекать от него фрагмент, соответствующий сбрасываемым данным, и добавлять фрагмент, соответствующий новым данным. Реализовано ли такое поведение в Qwt?
Записан
popper
Гость
« Ответ #4 : Декабрь 18, 2013, 12:08 »

Посмотри QwtPlotCurve::setRawSamples
Записан
Akon
Гость
« Ответ #5 : Декабрь 18, 2013, 15:39 »

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

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Декабрь 19, 2013, 11:18 »

Если поразмышлять, то кривая могла бы делать кэш (QPixmap), далее отсекать от него фрагмент, соответствующий сбрасываемым данным, и добавлять фрагмент, соответствующий новым данным. Реализовано ли такое поведение в Qwt?
Никогда не пользовался Qwt, просто добавлю еще одно размышление/соображение. Нет уверенности/гарантии что такое оптимизированное рисование будет "бесшовным" и равным полному.  Именно за счет анти-алиаса. Зная натуру Qt (приоритет макс удобство, а не производительность) - вполне возможно что и нет. И это можно проверить перекрыв paintEvent
Записан
Akon
Гость
« Ответ #7 : Декабрь 20, 2013, 09:19 »

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

Поставлю еще один вопрос: отображается кривая в 1000000 точек. Далее, я меняю точки в диапазоне [100000, 200000]. Если я буду использовать QwtSeriesStore<QPointF>::setData(...), то заново установлю все 1000000 точкек, соответственно, будет полная медленная перерисовка (медлительность возникает за счет расчетов по отображению 1000000 точек на текущий размер канваса плота). Мне нужно, чтобы был произведен перерасчет именно этого интервала и отрисовался измененный ограничивающий прямоугольник.

Я вижу
Код:
virtual void QwtPlotSeriesItem::drawSeries 	(	QPainter * 	painter, 
const QwtScaleMap & xMap,
const QwtScaleMap & yMap,
const QRectF & canvasRect,
int from,
int to
) const
которая, похоже, делает то, что мне нужно. Но я не хочу QPainter'ов в интерфейсе. Я хочу нечто в духе updateData(from, to).
Записан
Akon
Гость
« Ответ #8 : Декабрь 20, 2013, 10:04 »

По последнему вопросу сейчас вижу такое решение:
1. Делаю наследника QwtSeriesData<> с тем, чтобы предоставлять для Qwt доступ к внешнему буферу, содержащему 1000000 точек.
2. Изменяю в буфере необходимый фрагмент. Qwt об этом ничего не знает.
3. Для перерисовки обновленных данных использую QwtPlotSeriesItem::drawSeries(). Требуемые функции параметры (canvasRect и т.п.) вычисляю.

Тем, кто в теме, просьба скорректировать мой взгляд, если есть лучший вариант. Qwt выглядит продуманной либой, и меня смущает отсутствие простого интерфейса в духе updateData(from, to). Возможно, я что-то упускаю. Спасибо.
Записан
Akon
Гость
« Ответ #9 : Январь 08, 2014, 10:10 »

Если перерисовка занимает много времени, например, 250 мс в моем случае много, то как-то хотелось бы "разбавить" код перерисовки в Qwt вызовом пользовательского коллбэка, который мог бы вызывать QCoreApplication::processEvents(), например.

Никто не озадачивался подобным?
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #10 : Январь 08, 2014, 21:32 »

Мы когда-то решали подобную проблемы. Qwt тупит и не оптимизирует отрисовку как следует. Все решилось имплементацией собственного рисования с отфильтровкой накладывающихся точек в памяти.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Akon
Гость
« Ответ #11 : Январь 09, 2014, 19:06 »

Спасибо за ответ. Qwt предлагает достаточно широкие возможности отображения (линии, стемы, и т.д., интерполяция, опять же), и мне может потребоваться любая такая фича. На собственное рисование у меня нет времени, но как вариант это отмечу.

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

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Январь 09, 2014, 19:41 »

Если перерисовка занимает много времени, например, 250 мс в моем случае много, то как-то хотелось бы "разбавить" код перерисовки в Qwt вызовом пользовательского коллбэка, который мог бы вызывать QCoreApplication::processEvents(), например.

Никто не озадачивался подобным?
Озадачивался подобным - рисование может быть долгим. Проблема в том что processEvents может быть опасным, напр вызвать рекурсивный paintEvent или изменить данные рисования. Часто встречающаяся рекомендация типа "рисуй в pixMap" при ближайшем рассмотрении ничего не решает, к тому же заметно тормозит. Я ограничился прерыванием: в рисовании периодически проверяю нажата ли клава или мышь, если да - выход с update окна что вызовет след перерисовку.
Записан
Akon
Гость
« Ответ #13 : Январь 09, 2014, 20:26 »

Ок. Спасибо. Да, бездумный вызов processEvent() действительно может быть опасным.

Мне, например, нужно перерисовывать некий виджет с интервалом 100 мс. (анимация). Но у меня есть есть отрисовка в 250 мс...
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #14 : Январь 09, 2014, 20:26 »

Если перерисовка занимает много времени, например, 250 мс в моем случае много, то как-то хотелось бы "разбавить" код перерисовки в Qwt вызовом пользовательского коллбэка, который мог бы вызывать QCoreApplication::processEvents(), например.

Никто не озадачивался подобным?
Лучше рендерить долгую графику в отдельном потоке в теневой буфер и обновлять окно, только когда оно будет полностью сформировано.

Я ограничился прерыванием: в рисовании периодически проверяю нажата ли клава или мышь, если да - выход с update окна что вызовет след перерисовку.
Ага, только никто не гарантирует, что скопившиеся события обработаются быстро. Улыбающийся
Нарисовали половину кадра, пользователь нажал мышь, вышли из рисовалки, пользователь увидел на экране половину картинки, а ваша программа ушла обрабатывать события... и делала это секунду (ну обработку одного из событий делал специалистпрофессионал) и только после этого мы вернулись и дорисовали кадр. Пользователь будет очень грустить, рассматривая не дорисованные кадры или совместно часть старого и часть нового кадра.
Все таки, пока кадр не готов полностью, показывать его не стоит.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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