Высокопроизводительный модуль отрисовки графиков на базе использования библиотеки Qt (Олег Латий, OSSDEVCONF-2018)
Материал из 0x1.tv
- Докладчик
- Олег Латий
В докладе представлен авторский высокопроизводительный компонент библиотеки Qt для отрисовки 2D-графиков в реальном времени. Приводятся архитектура и особенности реализации, а также результаты сравнения с другими средствами построения графиков для платформы Qt.
Код проекта доступен по адресу https://github.com/lattoo/plotter под лицензией GPL v.2.
Содержание
Видео
Посмотрели доклад? Понравился? Напишите комментарий! Не согласны? Тем более напишите.
Презентация
Thesis
При необходимости реализовать функционал построения графиков Qt-разработчик сталкивается с выбором из нескольких вариантов, причём это одна из немногочисленных задач, где на сегодняшний день всё ещё сохраняется конкурентноспособность проприетарных Qt-компонентов. Так, к актуальным построителям графиков для Qt можно отнести следующие:
- QCustomPlot — виджет на C++ для построения графиков и визуализации данных, который фокусируется в первую очередь на создании визуально-привлекательных 2D-графиков, и при этом декларирует высокую производительность для визуализации в реальном времени .
- QChart — набор для отрисовки графиков от Qt (до релиза 5.6.0 библиотеки Qt платный) .
- Qwt — библиотека, содержащая дополнительные виджеты, компоненты и утилиты GUI, включая фреймворк для 2D-графиков .
- ChartDirector — профессиональный коммерческий компонент для построения графиков, известный широким охватом типов графиков .
Причиной разработки собственного инструмента построения графиков для Qt, который описывается в данной работе, появилась недостаточная производительность одних бесплатных фреймворков, которая делает их малопригодными для отрисовки динамично изменяющихся графиков в реальном времени, и сильно ограниченные визуальные возможности других.
Для написании виджета отрисовки графиков выбор между языком С++ и языком разметки QML был сделан в пользу C++ в силу требований максимальной производительности кода.
Программная реализация компонента Plotter представляет собой многоуровневую архитектуру, что позволяет настроить построитель под требования пользователя.
В общем случае структура классов принимает вид, изображённый на рисунке 1. Как видно из данной диаграммы, основные интерфейсные базовые классы включают IGraphicItem, IFilledItem, ITextItem, ITitleItem.
Подклассы, унаследованные непосредственно от IGraphicItem соответствуют различным видам линий: MainGridX и MainGridY для отрисовки главной сетки, SubGridX и SubGridY для отрисовки вторичной сетки, ZeroLineX и ZeroLineY для отрисовки нулевых линий, MainTicksX и MainTicksY для отрисовки штрихов, соответствующих главной сетке, SubTicksX и SubTicksY для отрисовки штрихов, соответствующих вторичной сетке и IFilledItem для отрисовки графических элементов с заливкой.
Список подклассов интерфейса IFilledItem включает: Background для заливки внешней области виджета, PlotArea для заливки области построения, а также класс IChart, предоставляющий возможность заливки области под графиком.
Подклассы, унаследованные от ITextItem отвечают за отрисовку текстовых полей и включают AxisLabelX и AxisLabelY для отображения подписей осей, AxisTitleX и AxisTitleY для отображения названия осей, LegendText для отображения легенды графиков, Title для отображения названия графиков.
Также стоит упомянуть, что благодаря многоуровневой архитектуре расчёты для отрисовки графических элементов отделены от непосредственной отрисовки, а в качестве дополнительных бонусов реализован экспорт графиков в формат масштабируемой векторной графики SVG, и опциональное хранение пакета настроек графика в конфигурационном файле.
Очевидно, что возможности построения и оформления графиков у всех рассмотренных компонент различаются. Таблицы 1 и 2 показывают результаты сравнения, полученные с помощью равноценных по визуальному оформлению и структуре кода тестовых программ, использующих компоненты в минимальной конфигурации: одновременная отрисовка трёх кривых со сплошными линиями толщиной 1 пиксель, с легендой и заголовком, без каких-либо заливок областей построения. По условиям тестирования был выставлен минимальный интервал обновления данных и отрисовки графиков, равный 50мс. Тестирование выполнялось на системе с мобильной версией процессора Intel Celeron B820 частотой 1,7ГГц с операционными системами Ubuntu Linux 17.10.1 x64 и Windows 7 x32.
Как можно видеть из таблицы 1 в сборках отладки и выпуска относительно загрузки ЦП, лидирующую позицию занимает виджет QCustomPlot.
По аналогии дополнительно было проведено сравнение производительности отрисовщиков графиков при использовании дополнительных средств визуального оформления: заданные толщину и стиль линии, градиентная заливка области построения, градиентная заливка области заднего плана. Результаты сравнения представлены в таблицах 3 и 4. Можно заметить, что лидирующую позицию занимает представляемый модуль Plotter.
В листинге ниже приведён минимальный код для подключения, инициализации, добавления данных и отрисовки графика.
<source lang="c">
const QString chart_name = "Chart 1";
plotter->add_chart(chart_name); //отвечает за добавление графика на область построения
const QPen pen = QPen(QColor(220,170,170), 1, Qt::SolidLine);
plotter->chart(chart_name)->set_pen(pen); //отвечает за инициализацию пера отрисовки.
plotter->chart(chart_name)->add_data(x, y); //отвечает за добавление данных.
plotter->scroll_graph(); //необходима для прокрутки области построения графика.
plotter->replot(); //инициирует общее обновление для области построения.
</source>
Общий вид графика представлен на рисунке 1 справа.
Для работы с настройками отрисовщика был разработан дополнительный модуль, реализованный по шаблону проектирования MVP (model-view-presenter) . Данный подход позволяет улучшить разделение ответственности в презентационной логике, а именно: модель содержит всю бизнес-логику, представление реализует отображение данных, представитель реализует двустороннее взаимодействие между моделью и представлением. Также использование данного подхода реализации связи интерфейса с данными позволяет увеличить уровень портируемости модуля.
Модуль представляет собой набор написанных и скомбинированных Qt-виджетов, позволяющий довольно быстро и удобно отредактировать вышеупомянутые настройки отрисовщика.
Примечания и ссылки
Plays:112 Comments:2