[WPF] Charts
От: Glas  
Дата: 06.02.12 10:10
Оценка:
Подскажите, пожалуйста, какие-нибудь бесплатные Chart для WPF. Пробовал тут поискать, но темы очень старые, может есть что поновее?
Dynamic Data Display вроде неплохой, но Behavior's на биндинги громоздить не хочется.
Re: [WPF] Charts
От: Аноним  
Дата: 06.02.12 10:44
Оценка:
Здравствуйте, Glas, Вы писали:

G>Подскажите, пожалуйста, какие-нибудь бесплатные Chart для WPF. Пробовал тут поискать, но темы очень старые, может есть что поновее?

G>Dynamic Data Display вроде неплохой, но Behavior's на биндинги громоздить не хочется.

Привет. В WPF пока не увидел еще адекватных примеров компонентов Chart.
Все Chart которые я видел для WPF имеют один общий минус- тормознутость.
Если у тебя задача выводить реал-тайм точки на график и точек под 10к штук нужно отображать сразу все на графике, то это дело сложное.
Dynamic Data Display — лучший бесплатный компонент, который это тянет(но нет всех плюшек от WPF, всякие биндинги и т.д.).
А к примеру, WPF ToolKit — аналог MS Chart(WinForms) созданный тоже сотрудниками Microsoft на сегодня поддерживает(вроде) все фишки WPF, но
платит за это все дорогой ценой- тормознутостью. Как вариант можно использовать WinFormHost для хостинга в окна WPF элементов Win32, но при этом
не сможешь использовать полноценно возможности WPF по композиции элементов окна(по части наложения одних на другие, вроде созданию слоев).
Зато получишь быстродействие уровня GDI(GDI+) для графика лежащего в WinFormHost- адаптере.
Следующий вариант: написать свой контрол, используя WriteableBitmap(Ex) или D3DImage с ортогональной проэкцией камеры и z=0.
Родными средствами WPF последний вариант- самый быстрый способ отрисовки графики, быстрее только привязка HWd от поверхности DirectX к D3DImage,
через Texture2D. Ну это уже полный интеропп и привет C++.
Вот такая картина с графиками в WPF. Но если тебе нужен статический график и мало точек, то нарисуй его сам или бери любой беспланый, с codeplex.com или поройся на codeproject.com с поиском "wpf Chart"(там есть простенькие поделки).

P.S. Я сам сейчас маюсь с этой задачей,пишу свой Chart.
Re[2]: [WPF] Charts
От: Glas  
Дата: 06.02.12 11:54
Оценка:
Здравствуйте, Аноним, Вы писали:

А>А к примеру, WPF ToolKit — аналог MS Chart(WinForms) созданный тоже сотрудниками Microsoft на сегодня поддерживает(вроде) все фишки WPF, но

А>платит за это все дорогой ценой- тормознутостью.
Вот не вижу я в последней версии WPF Toolkit этого Charta, хотя я думаю мне бы его хватило, да и там нет Zoom and Pan
Re[3]: [WPF] Charts
От: Dmitry_Sharp2008  
Дата: 06.02.12 15:20
Оценка:
Здравствуйте, Glas, Вы писали:

G>Здравствуйте, Аноним, Вы писали:


А>>А к примеру, WPF ToolKit — аналог MS Chart(WinForms) созданный тоже сотрудниками Microsoft на сегодня поддерживает(вроде) все фишки WPF, но

А>>платит за это все дорогой ценой- тормознутостью.
G>Вот не вижу я в последней версии WPF Toolkit этого Charta, хотя я думаю мне бы его хватило, да и там нет Zoom and Pan

Привет. Можешь глянуть блог
Там как раз один из авторов этого тулкита выкладывает материал...
... << RSDN@Home 1.2.0 alpha 5 rev. 1539>>
Re[2]: [WPF] Charts
От: alesterre Удмуртия  
Дата: 08.02.12 11:23
Оценка:
Здравствуйте, Аноним, Вы писали:

А>P.S. Я сам сейчас маюсь с этой задачей,пишу свой Chart.


Как посоветуете рисовать вот такой график (исходное изображение по клику, 450 КБ)?



Текущая реализация сильно тормозит при перемещении (зажали мышкой и таскаем влево-вправо). Профайлер говорит, что 97% нагрузки на совести System.Windows.Application.Run, что для меня ничего не значит . Интересно, что если в области видимости мало точек (0-20), двигается плавно.

Сейчас реализовано через вложенные ItemsControl'ы, самый верхний из которых двигается влево-вправо изменением свойства "X", к которому привязан его TranslateTransform.
С зумом вообще беда, из-за того что он только по одной оси, то чтобы не искажались пропорции линий и точек, приходится пересчитывать координаты всех точек и обновлять их через вызов OnPropertyChanged("PosX"), а это совсем медленно.
Re[3]: [WPF] Charts
От: alesterre Удмуртия  
Дата: 08.02.12 11:39
Оценка:
Здравствуйте, alesterre, Вы писали:

A>Как посоветуете рисовать вот такой график (исходное изображение по клику, 450 КБ)?


Нарыл в интернете следующее мнение:

In terms of application speed, with WPF you have two choices:

1. Using Shapes and higher lever objects will make development easy, but slow when you want to add a lot of shapes to the screen. They inherit from System.Windows.FrameworkElement, and as such contain a lot of baggage that you can do without if you want faster graphics.

2. Using the DrawingContext of a canvas to draw the shapes directly onto it (also look at StreamGeometry). You will have to use VisualHitTesting to handle mouse interation (not that difficult), but rendering is far far quicker when handling lots of objects on the screen. This option will take longer to get to grips with, but the application performance will be an order of magnitude better.


Получается, мне стоит пойти по второму пути?
Re[4]: [WPF] Charts
От: Dmitry_Sharp2008  
Дата: 08.02.12 14:03
Оценка: 2 (1)
Здравствуйте, alesterre, Вы писали:

A>1. Using Shapes and higher lever objects will make development easy, but slow when you want to add a lot of shapes to the screen. They inherit from System.Windows.FrameworkElement, and as such contain a lot of baggage that you can do without if you want faster graphics.


A>2. Using the DrawingContext of a canvas to draw the shapes directly onto it (also look at StreamGeometry). You will have to use VisualHitTesting to handle mouse interation (not that difficult), but rendering is far far quicker when handling lots of objects on the screen. This option will take longer to get to grips with, but the application performance will be an order of magnitude better.

A>[/q]

A>Получается, мне стоит пойти по второму пути?


Путь 2. наиболее актуален для таких задач. Однако, в случае работы с большим числом данных(более 10к точек) и особенно с всякими ресайзами, скроллингами и т.д. уже одного такого направления- мало. Очень быстро прийдется столкнуться с необходимостью предварительной фильтрации данных. Основное правило: показывать только то, что видит пользователь и не более. Так, нет смысла выводить больше точек, чем разрешение экрана, на котором производится отображение изображения. Чаще всего 2048 точек на один экран будет уже достаточно для многих мониторов. Далее, прийдется заботится о механизмах кеширования участков изображения. Основной принцип: обновлять только те участки, которые изменились, а не все изображение целиком. Это приведет к использованию различного рода блитингов и к WriteableBitmap и(или) DirectX под WPF. Тут поможет библиотека-надстройка над стандартным WriteableBitmap от Рене Шульца(ссылка на writeablebitmapex.codeplex.com/). Ну а король скорости под WPF — прямой вызов DirectX(как упоминалость постами выше).
Для дальнейших советов нужно больше информации о специфике выводимого графика и на какие компромисы вы готовы пойти.
... << RSDN@Home 1.2.0 alpha 5 rev. 1539>>
Re[5]: [WPF] Charts
От: alesterre Удмуртия  
Дата: 15.02.12 11:35
Оценка:
Здравствуйте, Dmitry_Sharp2008, Вы писали:

D_S>Путь 2. наиболее актуален для таких задач. Однако, в случае работы с большим числом данных(более 10к точек) и особенно с всякими ресайзами, скроллингами и т.д. уже одного такого направления- мало.


Наследовал свой класс от канвы, переопределяя OnRender, в нем рисовал 1000 эллипсов — все равно тормозит Я имею в виду тормоза при перемещении канвы через RenderTransform. Пробовал на каждое движение мыши перерисовывать эллипсы в новых позициях — так еще в несколько раз медленнее. Единственный способ, который позволил заметно ускорить перемещение объектов — кэширование через BitmapCache. С ним работает идеально. Но при размере кэша порядка 1.5-2 тысяч пикселей начинают лезть какие-то непонятные артефакты. Я пытался сделать так: двигаем закешированный грид с видимой в данный момент частью точек. Когда нужно подгрузить новые точки, грид сдвигается в начало координат, координаты существующих точек относительно грида обновляются (чтобы не скакали по экрану), новые подгружаются сразу в нужные места. Работает абсолютно плавно (подгрузка происходит после отпускания мыши, то есть пользователь уже не замечает тормозов), но при этом появляется какой-то мусор кругом, если окно развернуто на весь экран.
Также идеально двигаются 1000 квадратиков (их можно и 10000 нарисовать, все равно быстро). А эллипсы тормозят. Кэширование каждого отдельного эллипса тоже ничего не дает. Перемещение каждого отдельного эллипса через рендертрансформ (если эллипсы — Shape) также работает медленнее, чем перемещение всей канвы (или грида, короче, где лежат фигуры) целиком.

В общем, или не давать пользователю смотреть сразу весь график (~2к точек + столько же линий + сетка и надписи), или как-то пытаться сделать свое нормальное кэширование в битмап, чтобы двигать по экрану битмап, а не фигуры. Или кэшировать кусочками

Как вообще правильно двигать сложное векторное изображение по экрану? Перерисовывать вручную каждый кадр или двигать целиком контейнер с изображением, заставляя впф думать самой?
Re[6]: [WPF] Charts
От: Dmitry_Sharp2008  
Дата: 15.02.12 19:28
Оценка:
Здравствуйте, alesterre, Вы писали:

A>В общем, или не давать пользователю смотреть сразу весь график (~2к точек + столько же линий + сетка и надписи), или как-то пытаться сделать свое нормальное кэширование в битмап, чтобы двигать по экрану битмап, а не фигуры. Или кэшировать кусочками


A>Как вообще правильно двигать сложное векторное изображение по экрану? Перерисовывать вручную каждый кадр или двигать целиком контейнер с изображением, заставляя впф думать самой?


Я полагаю, что вы уже убедились, что в случае отрисовки большого числа примитивов(наследники Shape), WPF быстро сдается.
Похоже, что остается несколько вариантов: 1. Ограничивать число видимых на экране элементов до приемлемого уровня быстродействия.
2. Заняться ручной подготовкой конечного изображения используя средства работы с 2д такие, как GDI(GDI+) или аналогичными библиотеками.
3. Уходить в интеропп с DirectX. Рисовать все его средствами и полученную поверхность передавать в D3DImage.Этот вариант — самый производительный и, похоже, наиболее сложный.
Если оставаться на уровне "родных" WPF средств работы с 2д, то прийдется пробовать создавать дополнительные потоки отрисовки(что бы создать иллюзию "свободы" основного интерфейса для пользователя).
Далее думать о комбинации чего то вроде StreamGeometry, DrawingBrush, DrawingImage и желательно с "заморозкой"(Freez) кистей, перьев.
Стоит подумать о том, как бы сетку создавать заливкой области текстурой используя DrawingBrush.
Но в любом случае все это как то неуместно смотрится.
Наиболее адекватные решения- п.2 или 3.

P.S. Что там за "артефакты" лезут, да еще и при полноэкранном размере- вообще не представляю. Может драйверы видеокарты "воду мутят"? У меня на Radeon HD 2600Pro под Windows 7 были артефакты вообще на всех WPF приложениях.
... << RSDN@Home 1.2.0 alpha 5 rev. 1539>>
Re[7]: [WPF] Charts
От: alesterre Удмуртия  
Дата: 16.02.12 10:27
Оценка:
Здравствуйте, Dmitry_Sharp2008, Вы писали:

D_S>P.S. Что там за "артефакты" лезут, да еще и при полноэкранном размере- вообще не представляю. Может драйверы видеокарты "воду мутят"? У меня на Radeon HD 2600Pro под Windows 7 были артефакты вообще на всех WPF приложениях.


Чтобы было лучше видно, сделал такой бэкграунг гриду, в который складываю фигуры:

<Grid.Background>
    <LinearGradientBrush StartPoint="0, 0.5" EndPoint="1,0.5">
        <GradientStopCollection>
            <GradientStop Color="#EE1111FF" Offset="0"></GradientStop>
            <GradientStop Color="#111111FF" Offset="0.01"></GradientStop>
            <GradientStop Color="#111111FF" Offset="0.99"></GradientStop>
            <GradientStop Color="#EE1111FF" Offset="1"></GradientStop>
        </GradientStopCollection>
    </LinearGradientBrush>
</Grid.Background>


Скриншот, когда все хорошо (фон грида рисуется как нужно, в виде двух синих полос по краям):
http://i.imgur.com/9UPWo.png

Но если "поездить" мышкой туда-сюда, происходит следующее:
http://i.imgur.com/wBCuW.png

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

Проблему удалось победить так (возможно, не обязательно вызывать всё, пока для верности оставил все три):

MainGrid.InvalidateArrange();
MainGrid.InvalidateMeasure();
MainGrid.InvalidateVisual();


В итоге, мой подход пока меня устраивает, посмотрим, как будет дальше, когда будет больше объектов (отрезки между точками, надписи, линии сетки). Пока что перемещение 2 тысяч точек — не проблема даже для Селерона 2.2 ГГц и встроенного видеочипа. Абсолютно плавный panning; zoom на мелких масштабах подтормаживает, но уже гораздо меньше, чем в исходной реализации, когда положения всех-всех эллипсов менялись через OnPropertyChanged.
Re[8]: [WPF] Charts
От: Dmitry_Sharp2008  
Дата: 16.02.12 13:44
Оценка: 2 (1)
Здравствуйте, alesterre, Вы писали:

A>Кроме явных проблем с фоном, иногда в некоторых местах рисуются точки, которых не должно быть видно, причем иногда они рисуются вытянутыми, сжатыми или обрезанными.


A>Проблему удалось победить так (возможно, не обязательно вызывать всё, пока для верности оставил все три):


A>
A>MainGrid.InvalidateArrange();
A>MainGrid.InvalidateMeasure();
A>MainGrid.InvalidateVisual();
A>


Все верно, когда "дергаешь" контейнер с визуалами нужно обязательно вызывать пересчет системы макета WPF(чтобы контейнер был всегда в курсе, что у него с визуалами ему принадлежащими творится). Первая строка вызывает пересчет положений всех визуалов лежащих в коллекции Childrens контейнера. Вторая строка запрашивает пересчет их размеров. Третья, по моему, уже избыточна. Почитайте еще про UpdateLayout.

P.S. Да, на ваших картинках не увидел "глюков" с точками, о которых вы пишите.
... << RSDN@Home 1.2.0 alpha 5 rev. 1539>>
Re[8]: [WPF] Charts
От: MxMsk Португалия  
Дата: 17.02.12 16:28
Оценка:
Здравствуйте, alesterre, Вы писали:

A>Проблему удалось победить так (возможно, не обязательно вызывать всё, пока для верности оставил все три):

A>MainGrid.InvalidateArrange();
A>MainGrid.InvalidateMeasure();
A>MainGrid.InvalidateVisual();
Здесь можно обойтись одной строкой. InvalidateArrange вызывается самой WPF как из InvalidateVisual, так и из InvalidateMeasure. InvalidateMeasure должно быть достаточно. Если размеры или положение элементов изменятся, то WPF их перерендерит.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.