2010-03-25 9 views
9

Ho cercato di capire quale sia il modo appropriato per visualizzare dati in tempo reale come un grafico a linee in WPF. E in tempo reale intendo davvero, i dati raccolti da un dispositivo USB che genera dati a una velocità di circa 40Hz. Ci sono più (fino a 7) flussi di dati che sto leggendo a 40Hz in modo asincrono.Mappatura WPF/visualizzazione di dati in tempo reale

Ho provato a utilizzare due soluzioni off-the-shelf (grafici WPF Toolkit e Swordfish) e ho quasi esaminato il componente Dynamic Data Visualization, ma ci siamo arresi dopo aver letto alcuni commenti sul loro forum. Sembra che le soluzioni cartografiche standard siano orientate verso grafici statici e in realtà ho bisogno di qualcosa di simile al Task Manager di Windows - solo molto più velocemente e con un maggior numero di punti dati.

Attualmente ho eseguito il rollover della mia soluzione, che sembra funzionare al meglio finora, ma ho la sensazione che mi manchi qualcosa perché sembra che dovrei essere in grado di ottenere prestazioni migliori.

I requisiti sono che dovrebbe essere in grado di gestire un intervallo costante di circa 10000 punti in una finestra scorrevole - con l'arrivo di nuovi dati (a 40Hz), i dati vecchi vengono spostati a sinistra al di fuori dell'intervallo visibile. E ha bisogno di sostenere questo ritmo per almeno 20 - 30 minuti (per un totale di circa 75 - 100 mila punti per flusso di dati).

La mia implementazione personalizzata corrente si basa su un componente che eredita da Shape e utilizza un metodo StreamingGeometry per DefinigGeometry. I dati provenienti dal dispositivo vengono passati al componente tramite una coda per migliorare le prestazioni a causa dell'effetto "bursting" intrinseco e dopo l'operazione di annullamento della coda il componente viene invalidato.

Quindi, la mia domanda è, sono sulla buona strada o ho completamente torto? Qual è il modo più efficiente per realizzare tale visualizzazione dei dati in WPF? Qualsiasi aiuto o suggerimento sarebbe molto apprezzato.

+0

L'interoperabilità di DirectX è la direzione. Alcuni useranno slimDX ma è un'enorme dipendenza e una curva di apprendimento astratta. Raccomando l'uso diretto di DX9 o (DX11 via DXGI) mentre agita la mano con l'interfaccia D3DImage di WPF. Ancora una curva di apprendimento ma uguale a slimdx e più gestibile per creare un dispositivo DX, contesto, buffer, shader e ottenere l'app utilizzando Direct3D. I documenti sono terribili ma abbastanza buoni, e quando hai finito, hai realizzato qualcosa di interessante senza dipendenza dagli altri. Guarda il nostro mondo reale [18M charting demo] (http://www.gigasoft.com) con WPF WinForm MFC EXE, i suoi dati prevalentemente audio WAV e GIS. – Robert

+0

@Robert, grazie per l'input. Idealmente mi piacerebbe inserire w DX9 per essere compatibile con XP, ma così non sono riuscito a capire no per disegnare linee spesse arbitrariamente con D3D in un modo paragonabile per qualità ai percorsi con l'alias che ho ottenuto con WPF. Qualche indicazione? Hai dovuto scrivere la tua routine di tessellazione? Sarei anche a posto con DX10 se riesco a ottenere ciò che voglio per prestazioni/qualità. –

+0

Le linee spesse rappresentano il più grande inconveniente con D3D. Anche se non è un grosso problema. Se è possibile progettare attorno a una dimensione di grafico nota, la logica del buffer del vertice conoscerà una dimensione e sarà semplice disegnare la linea come quad (triangoli doppi) b) se non si desidera ricostruire il buffer dei vertici in base a un evento di dimensioni, quindi lo shader dovrebbe essere progettato per contenere un rapporto di aspetto e le impostazioni della dimensione fisica in un buffer costante, quindi questi dati utilizzati all'interno del vertex shader per modificare al volo i quad della linea. Questo è il caso di dx9/11. Oppure puoi usare D2D e la logica di riduzione dei dati per tracciare grandi quantità. – Robert

risposta

1

Il rendering in modalità permanente di WPF rende difficile disegnare/ridisegnare grafici e immagini personalizzati, soprattutto quando questi disegni contengono molti oggetti.

Il disegno più veloce che ho potuto fare in WPF è l'utilizzo di un WritableBitmap e il suo riempimento con una chiamata a WritePixels, che potrebbe essere un'opzione per voi. Ha ampiamente superato la velocità di disegno del grafico che ho scritto usando PathGeometries e disegno su una tela.

Sono interessato a vedere se c'è una via di mezzo più veloce.

+0

Una possibile "via di mezzo" sarebbe disegnarla su un RenderContext in un override di OnRender. Se non altro, questo dà un enorme senso di sollievo mentale in quanto è molto più simile alla pittura GDI/WinForms tradizionale ... (Più seriamente, dovrebbe dare accesso a primitive di rendering decenti senza il sovraccarico di costruire l'albero in modalità mantenuta che è così spesso solo una ripetizione ridondante del proprio oggetto grafico) –

+0

temo che OnRender usi ancora la pipeline in modalità conservata. Tutto ciò che stai facendo è pubblicare oggetti in modalità conservata nella pipeline grafica usando questo. Per testarlo, inserisci un punto di interruzione all'interno e riduci/ingrandisci la finestra.Se si trattava di un metodo della modalità immediata (ad esempio OnPaint in Winforms), si forza un ridisegno. Non sono sicuro al 100%, ma penso che il ridimensionamento non causerà l'attivazione di OnRender a meno che non si imposti esplicitamente come flag. –

1

Disclosure: ho proprio software ABT e hanno sviluppato SciChart, più hanno contribuito verso la biblioteca WriteableBitmapEx open source

Purtroppo non ti manca nulla. Il motore di rendering in modalità mantenuta in WPF/Silverlight offre scarse prestazioni per questo tipo di lavoro. Ho lavorato su un numero di sistemi che sono stati aggiornati da Windows Forms a WPF, dove il cliente è rimasto dolorosamente deluso dalle prestazioni di rendering di questo framework "GPU Accelerated"!

In ogni caso, c'è un modo. Usa il rendering in modalità immediata. Scopri le classi WriteableBitmap o InteropBitmap. C'è un'eccellente libreria open source chiamata WriteableBitmapEx da Rene Schulte alla quale ho contribuito. WriteableBitmapEx fornisce alcune funzioni di disegno di basso livello (stile GDI) per disegnare direttamente in bitmap. Ciò offre prestazioni fantastiche e un basso ingombro di memoria (sì, il quadro di fantasia di MS è battuto da un paio di for-loops ottimizzati e da un puntatore a un array di byte).

Se si tratta di uno specifico componente grafico di terze parti che stai cercando, prova a SciChart. SciChart è un componente che ho sviluppato io stesso che cerca di colmare il divario per i grafici scientifici/azionari WPF o Silverlight ad altissime prestazioni. Utilizza algoritmi di ricampionamento proprietari per ridurre il set di dati prima del disegno, il rendering in modalità immediata e una serie di altre ottimizzazioni come il pool di oggetti e il riutilizzo delle risorse, ottenendo frequenze di aggiornamento uniformi per dataset di grandi dimensioni e ingombro di memoria ridotto.

Fare clic sulla demo delle prestazioni sul link sopra (richiede Silverlight 4). Attualmente SciChart è in grado di rendere 1.000.000 punti dati a circa 5 FPS (a seconda dell'hardware di destinazione), equivalenti a 5.000.000 di punti dati al secondo. Una licenza commerciale sarà disponibile nel primo trimestre 2012.

+0

@DrABT: per pura curiosità, WritableBitmapEx supporta arbitrariamente l'anti-aliasing come lo spessore o hai dovuto implementarlo separatamente nel componente SciChart? –

+0

Ciao Miky, WBEX non supporta questo per quanto ne so. L'abbiamo implementato noi stessi con alcuni algoritmi diversi per ottenere un buon compromesso tra qualità e velocità. Un semplice algoritmo è discusso nei forum WBEX in cui pre-cache un'ellisse di dimensione N e blitalo in ogni punto di una linea di Bresenham. Sorprendentemente questo funziona, ma porterà a bordi frastagliati come WBEX ha coordinate intere. Per ottenere una linea ampia e lineare è necessario disporre di virgola mobile, anche costosa in termini di CPU! Il renderer SciChart High Quality fa questo come un riproduttore D3D sperimentale. –

+0

@DrABT grazie per la rapida risposta. In questo momento non sto lavorando attivamente su questo argomento, ma forse a un certo punto rivisiterò la nostra implementazione. –

1

I migliori risultati possono essere ottenuti con la programmazione DirectX di basso livello e utilizzando gli shader HLSL. Il rendering basato sullo spazio dei nomi System.Windows.Media dovrebbe essere dimenticato immediatamente quando le massime prestazioni e le esigenze in tempo reale sono importanti.

Siamo stati in grado di sviluppare routine in grado di tracciare oltre 1000 milioni di punti dati, ad es. 8 feed di dati x 125 punti di dati M, utilizzando una linea ampia, senza downsampling. Le routine fanno parte di LightningChart, grafici WPF (e grafico WinForms). Ci sono voluti 7 anni per arrivare a questo punto ... Abbiamo creato uno billion points example, con il progetto VS e il video di YouTube inclusi.

[I'm tech lead of LightningChart]

+0

Ciao Pasi - grazie per la tua risposta; LightningChart è open source? in caso contrario, ti dispiacerebbe condividere ulteriori dettagli su quale tipo di primitive e shader DirectX di basso livello stai usando? stai usando Direct2D o Direct3D? E per cosa stai usando gli shader? –

+0

Ciao Mike, LightningChart non è open source. Stiamo utilizzando Direct3D anche per la grafica 2D. Direct2D è qualcosa che è lento e limitato. Scuse Non posso condividere tutti i dettagli qui in pubblico. Le nostre prestazioni sono il risultato di anni di lavoro, sperimentando approcci diversi e reali esigenze dei clienti. –