Страницы

Поиск по вопросам

понедельник, 23 декабря 2019 г.

Как правильно обрабатывать и рисовать большой объем данных?

#c_sharp #gdi+ #graphics


Добрый день. 
Дано множество точек (100.000-500.000). Точки образуют кривые(волны), которые отображаются
на графике. Пример графика
Сейчас программа работает в такой последовательности:

Считывание точек из файла
Создание bitmap
Преобразование значений точек в координаты bitmap
Запись точек в bitmap через Graphics.DrawCurve()
Если нужно закрасить часть волны (например, положительную часть) - находиться область
пересечения некоторых областей через Region.Intersect и заливается.
Рисование bitmap

Программа работает медленно.

Подходит ли GDI+ для отображения большого количества данных? Или нужно использовать
что-то другое?
Какая правильная последовательность действий?
Как правильно и в какой момент преобразовывать значения в координаты?
Что почитать?

Спасибо.    


Ответы

Ответ 1



Для подобным манипуляций GDI+ вряд ли подходит. Насколько мне известно, эта технология не работает напрямую с железом, а кроме того, если не ошибаюсь, графические операции просчитываются CPU, а не GPU. За все вышесказанное на 100% не поручусь, однако объем данных , который вы указали, для GDI явно велик. Вам, вероятнее, всего, имеет смысл обратиться к DirectX или OpenGL. Если говорить о C#, то для работы с DX есть ряд оберток, плюс еще XNA (поддержка которого, правда, прекращается)

Ответ 2



Могу Вам посоветовать отбрасывать точки, которые не видны (накладываются друг на друга)в следствии масштаба. Для этого есть алгоритм Дугласа-Пекера.

Ответ 3



В целом можно быстро рисовать на GDI, все как и всегда в компьютерной графике: батчинг и LOD. У вас 500.000 в одной линии? Получается, что нарисованных пикселей меньше, чем точек что вы отдали. Советы, если узкое место это DrawCurves: Надо уменьшить плотность точек на пиксель хотя бы до одного. В вашем случае можно для каждого пикселя выбрать точку (из всех точек которые попадают в этот пиксель), которая по модулю как можно дальше отстоит от предыдущего пикселя. 1 точка на 1 пиксель, как я понимаю, даст все равно гладкую линию, так что можно рисовать просто через DrawLines. Если точки равномерно распределены, то можно выбить каждую вторую или каждую третью. Если результат будет приемлим, то можно оставить =) (применимо в основном для DrawCurves) Прорядить данные и по Y координате: в случае, если точки не отстоят друг от друга по Y координате, то предыдущую можно убрать. Это сделает меньше точек на прямых линиях и больше на изгибах. (Можно комбинировать с 2 пунктом) Насчет закрашивания не особо понятно, приведите пример с ним. Рисовать можно необязательно сначала в битмап. Если процедура быстрая, то можно сразу в OnDraw. Для простых рисовалок на один раз это самое то. Если нужен крутой реалтайм, то я склоняюсь к способам, описанным в этих статьях (тыц и тыц). (Только я бы не советовал сразу браться за них и думать что у вас тоже будет крутой фпс, нужен сначала быстрый способ отрисовки своих данных)

Ответ 4



Выгрузите медленные операции в фоновый поток, и всё будет хорошо.

Комментариев нет:

Отправить комментарий