WPF карт / визуализация данных в реальном времени - PullRequest
10 голосов
/ 25 марта 2010

Я пытался выяснить, как правильно представлять данные в реальном времени в виде линейного графика в WPF. Под реальным временем я имею в виду данные, которые собираются с устройства USB, которое генерирует данные с частотой примерно 40 Гц. Существует несколько (до 7) потоков данных, которые я читаю на частоте 40 Гц асинхронно.

Я попытался использовать два готовых решения (графики WPF Toolkit и Swordfish) и почти изучил компонент динамической визуализации данных, но отказался от него после прочтения некоторых комментариев на их форуме. Кажется, что готовые решения для построения диаграмм ориентированы на статические диаграммы, и мне действительно нужно что-то похожее на диспетчер задач Windows - только намного быстрее и с большим количеством точек данных.

В настоящее время я разработал свое собственное решение, которое пока работает лучше всего, но у меня есть ощущение, что я что-то упустил, потому что, похоже, я смогу добиться от него большей производительности.

Требования заключаются в том, что он должен иметь возможность обрабатывать постоянный диапазон около 10000 точек в скользящем окне - по мере поступления новых данных (с частотой 40 Гц) старые данные перемещаются влево за пределы видимого диапазона. И он должен поддерживать эту скорость в течение не менее 20–30 минут (всего около 75–100 тысяч точек на поток данных).

Моя текущая пользовательская реализация основана на компоненте, который наследуется от Shape и использует StreamingGeometry для DefinigGeometry. Данные, поступающие с устройства, передаются компоненту через очередь для повышения производительности благодаря присущему «эффекту пакетирования», и после операции удаления из очереди компонент становится недействительным.

Итак, мой вопрос: я на правильном пути или я совершенно не прав? Каков наиболее эффективный способ сделать такую ​​визуализацию данных в WPF? Буду очень признателен за любую помощь или подсказки.

Ответы [ 4 ]

3 голосов
/ 21 декабря 2011

Раскрытие информации: я владею программным обеспечением ABT и разработал SciChart , а также внес свой вклад в WriteableBitmapEx библиотеку с открытым исходным кодом

К сожалению, вы 'ничего не пропустил.Механизм рендеринга с сохранением режима в WPF / Silverlight обеспечивает низкую производительность для этого типа работы.Я работал над несколькими системами, которые были обновлены с Windows Forms до WPF, где клиент был очень разочарован производительностью рендеринга этой среды "GPU Accelerated"!

В любом случае, есть способ.Используйте немедленный режим рендеринга.Проверьте классы WriteableBitmap или InteropBitmap.Существует отличная библиотека с открытым исходным кодом, которая называется WriteableBitmapEx от Rene Schulte , в которую я внес свой вклад.WriteableBitmapEx предоставляет некоторые низкоуровневые функции рисования (стиль GDI) для рисования непосредственно в растровое изображение.Это обеспечивает фантастическую производительность и низкий объем занимаемой памяти (да, модная среда MS превосходит пару хорошо оптимизированных циклов for и указатель на байтовый массив).

Если это конкретный компонент стороннего графика, который вы ищете, попробуйте SciChart .SciChart - это компонент, который я сам разработал и который стремится заполнить пробел в сверхвысокой производительности научных / фондовых графиков WPF или Silverlight.Он использует собственные алгоритмы передискретизации, чтобы уменьшить набор данных перед рисованием, рендеринг в непосредственном режиме и множество других оптимизаций, таких как пул объектов и повторное использование ресурсов, что приводит к плавной частоте обновления для очень больших наборов данных и малой занимаемой памяти.

Нажмите на демонстрацию производительности по ссылке выше (требуется Silverlight 4).В настоящее время SciChart может отображать 1 000 000 точек данных со скоростью около 5 кадров в секунду (в зависимости от целевого оборудования), что эквивалентно 5 000 000 точек данных в секунду.Коммерческая лицензия будет доступна в первом квартале 2012 года.

2 голосов
/ 31 августа 2016

Наилучших результатов можно достичь при низкоуровневом программировании DirectX и использовании шейдеров HLSL. Рендеринг на основе пространства имен System.Windows.Media должен быть немедленно забыт, когда важны максимальная производительность и потребности в реальном времени.

Нам удалось разработать процедуры, которые могут отображать более 1000 миллионов точек данных, например, 8 потоков данных x 125 M точек данных, с использованием широкой линии, без понижающей дискретизации. Подпрограммы являются частью LightningChart , диаграмм WPF (и диаграммы WinForms). Нам потребовалось около 7 лет, чтобы достичь этой цели ... Мы сделали пример млрд. Баллов , с проектом VS и видео с YouTube

[Я технический руководитель LightningChart]

2 голосов
/ 25 марта 2010

Визуализация с сохранением режима WPF делает рисование / перерисовку пользовательских диаграмм и изображений непростым делом, особенно если эти рисунки содержат много объектов.

Самым быстрым рисунком, который я смог сделать в WPF, является использование WritableBitmap и заполнение его вызовом WritePixels, который может быть вариантом для вас. Он значительно превысил скорость рисования диаграммы, которую я написал с помощью PathGeometries и рисования на холсте.

Мне интересно посмотреть, есть ли более быстрый средний план.

1 голос
/ 08 февраля 2019

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

  1. Использование геометрии WPF.
  2. Использование Direct2D.

Оба они вообще не были исполнителями.

Одна вещь, которую я знаю, это то, что WPF хорош для рендеринга изображений (BitmapSource), поэтому я решил пойти в этом направлении и использовать WriteableBitmapEx, чтобы нарисовать график на WriteableBitmap и затем передать его ...

Одна проблема с библиотекой WriteableBitmapEx состоит в том, что она не имеет таких функций рисования, как, например, GDI. Так почему бы просто не использовать GDI? нет разницы, если вы все сделаете правильно.

Пример:

    public void BeginDraw()
    {
        _writeable_bitmap = new WriteableBitmap((int)Math.Max(_size.Width, 1), 
        (int)Math.Max(_size.Height, 1), 96.0, 96.0, PixelFormats.Pbgra32, null);

        _gdi_bitmap = new System.Drawing.Bitmap(_writeable_bitmap.PixelWidth, 
        _writeable_bitmap.PixelHeight,_writeable_bitmap.BackBufferStride,
        System.Drawing.Imaging.PixelFormat.Format32bppPArgb,
        _writeable_bitmap.BackBuffer);

        _writeable_bitmap.Lock();

        _g = System.Drawing.Graphics.FromImage(_gdi_bitmap);
        _g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

        _g.Clear(System.Drawing.Color.Transparent);
    }

    public void DrawSeries(IEnumerable<System.Drawing.PointF> points)
    {
        _g.DrawCurve(dataSeries.GdiPen, points.ToArray());
    }

    public void EndDraw()
    {
        _writeable_bitmap.AddDirtyRect(new Int32Rect(0, 0, 
        _writeable_bitmap.PixelWidth, _writeable_bitmap.PixelHeight));
        _writeable_bitmap.Unlock();

        var cloned = _writeable_bitmap.Clone();
        cloned.Freeze();

        Dispatcher.BeginInvoke(new Action((() =>
        {
            Image = cloned;
        })));

        _g.Dispose();
    }

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

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

  • Более 1 миллиарда точек данных.
  • Частота обновления 5FPS.
  • 10000 новых точек данных, выдвигаемых с частотой 100 Гц.
  • 10% ЦП на ноутбуке i7 Core.
  • Потоки пользовательского интерфейса и рендеринга WPF полностью свободны для других операций.

Я являюсь автором библиотеки с открытым исходным кодом RealTimeGraphX ​​(для WPF и UWP), которая делает именно это. https://github.com/royben/RealTimeGraphX

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

...