Как рисовать в C#/WinForms с приличной скоростью?

Я пытаюсь визуализировать график и позволить людям играть с ним. Я нашел отличную библиотеку Graph#, которая может создать начальный макет, чтобы покрыть эту часть. Теперь мне нужно сделать контрол, который его реально отрисовывает и обеспечивает необходимую интерактивность.

Graph # поставляется с хорошим визуализатором, однако мне он не нравится, потому что он написан на WPF (в то время как мое приложение - WinForms), и потому что я хочу добавить еще несколько интерактивных опций, которые в любом случае потребовали бы его переделки. .

Графы, которые я рисую, обычно будут довольно большими, примерно со 100 вершинами и таким же количеством ребер (графы будут деревьями в 99% случаев). Это означает, что результирующий рендеринг может иметь размер до 2000 на 2000 пикселей и даже больше. Пользователи должны иметь возможность увеличивать и уменьшать масштаб, прокручивать, выделять и перетаскивать вершины и ребра, а также получать всплывающие окна с дополнительной информацией при наведении курсора на вершину.

Я беспокоюсь, что стандартный System.Drawing не сможет обеспечить приличную скорость для этого. Я хотел бы, чтобы операции перетаскивания/масштабирования/прокрутки были плавными, а всплывающие окна также должны открываться с небольшой анимацией. Что-то вроде 20 кадров в секунду должно быть необходимостью.

Я знаю, что могу попытаться ускорить работу, предварительно отрендерив множество элементов и сохранив их в виде растровых изображений в памяти, но это, вероятно, займет много оперативной памяти, и я все еще не уверен, что это обеспечит необходимую производительность. .

о чем ты думаешь?


person Vilx-    schedule 27.08.2009    source источник


Ответы (3)


«Преждевременная оптимизация — корень всех зол»

GDI+ отлично подходит для ваших нужд. Не покупайте сторонние библиотеки, пока не узнаете, что они вам нужны.

Я сделал тысячу полигонов на растровом изображении размером 1000x800 пикселей и полностью перерисовал его со скоростью более 100 кадров в секунду, используя только GDI+.

При этом, если вам нужно много рисовать и у вас большое разрешение. Некоторые сторонние библиотеки рисования могут выйти НАМНОГО за пределы того, на что способен управляемый GDI.

person Neil N    schedule 27.08.2009
comment
Вы также перерисовывали сами полигоны каждый кадр? А растровое изображение вы рисовали растянутым (для масштабирования)? ;) - person Vilx-; 27.08.2009
comment
Да, я полностью стер битмап и перерисовал ВСЕ полигоны на каждом кадре. Требовалась некоторая оптимизация, но я заставил ее работать. Масштаб - это то, где он облажался, масштабирование никогда не работало нормально в GDI. Вместо этого я использовал элемент управления Aurigma Bitmap, который использует некоторый неуправляемый код для повышения скорости. - person Neil N; 27.08.2009
comment
Хм, у меня есть класс, предоставляющий растровое изображение, которое использует байт [] в качестве основы... никаких неуправляемых вещей. - person Dykam; 27.08.2009
comment
Согласитесь, не стоит переживать, пока у вас не возникнет реальная проблема. Я без проблем рисую тысячи точек, линий и полигонов в GDI+. - person Blue Toque; 28.08.2009
comment
+1 за цитату, я всегда стараюсь помнить рядом с You Ain't Gonna Need It (YAGNI). - person Camilo Martin; 07.12.2011

Я рекомендую оставить Graph# в покое и просто разместить его в своем приложении Windows Forms.

Производительность, которую вы получите, будет намного выше, чем при попытке перереализовать ее в System.Drawing.

person Reed Copsey    schedule 27.08.2009
comment
Но тогда мне пришлось бы кодировать в WPF, чтобы заставить его работать так, как я хочу, а у меня вообще нет опыта работы с WPF. Мне будет проще переделать его самому без WPF. - person Vilx-; 27.08.2009
comment
Если вы не хотите изучать WPF, то вы не желаете изучать какой-либо другой способ, кроме system.drawing, поскольку любой другой метод требует обучения. - person Neil N; 27.08.2009
comment
Верно, я полагаю... Я просто надеялся, что другие способы могут иметь менее крутую кривую обучения. :П - person Vilx-; 27.08.2009
comment
Нет, я говорю, просто используйте визуализатор Graph# напрямую. Звучало так, как будто вы были довольны этим и его вариантами. Вы можете разместить это в своем приложении Windows Forms, как есть, без работы по реализации. - person Reed Copsey; 27.08.2009
comment
Ну, он делает около 3/4 того, что я хочу. Я бы хотел, чтобы у него были полосы прокрутки, а перетаскивание было совершенно непригодным для использования вблизи краев изображения. Также у него нет всплывающих окон, которые я хочу при наведении. - person Vilx-; 27.08.2009
comment
Я бы, вероятно, по-прежнему делал это через расширение Graph#, так как это намного проще использовать для таких вещей, как масштабирование в GDI. - person Reed Copsey; 27.08.2009
comment
Что ж... Хорошо, я попробую... Прежде чем я сам начну полный поиск, возможно, вы можете указать мне на какую-нибудь хорошую статью, которая поможет мне быстро освоить WPF? У меня довольно большой опыт работы с .NET, так что это не обязательно для новичков. - person Vilx-; 28.08.2009

GDI+ будет достаточно быстрым для того, что вы делаете, особенно если (как это звучит из вашего описания) все, что вы рисуете, представляет собой прямоугольники и вертикальные/горизонтальные линии. Многоугольники и нелинейные формы немного медленнее, но ненамного (разница в скорости частично зависит от SmoothingMode вашего объекта Graphics). Отрисовка кэшированных растровых изображений с изменением размера также выполняется довольно быстро, хотя может значительно замедлиться, если вы используете высококачественную настройку InterpolationMode.

В качестве эталона я написал GPS-приложение .Net Compact Framework для Windows Mobile, которое отображало на экране около 10 000 строк в реальном времени. Это позволило достичь частоты кадров всего в несколько кадров в секунду, но вычислительная мощность смартфона, конечно, намного меньше, чем у современного ПК.

person MusiGenesis    schedule 27.08.2009