2010-03-25 20 views
9

He estado tratando de averiguar cuál es la forma adecuada de representar datos en tiempo real como un gráfico de líneas en WPF. Y en realidad quiero decir en realidad, datos que se están recopilando de un dispositivo USB que genera datos a una velocidad de aproximadamente 40Hz. Hay múltiples (hasta 7) flujos de datos que estoy leyendo a 40Hz de manera asincrónica.Gráficos/visualización WPF de datos en tiempo real

He intentado usar dos soluciones estándar (gráficos de WPF Toolkit y gráficos Swordfish) y casi busqué en el componente Dynamic Data Visualization pero me rendí después de leer algunos comentarios en su foro. Parece que las soluciones de gráficos listas para usar están orientadas a gráficos estáticos y realmente necesito algo similar al Administrador de tareas de Windows, solo que es mucho más rápido y con muchos más puntos de datos.

Actualmente, he lanzado mi propia solución que parece funcionar mejor hasta el momento, pero tengo la sensación de que me falta algo porque parece que debería ser capaz de obtener un mejor rendimiento de la misma.

Los requisitos son que debería ser capaz de manejar un rango constante de aproximadamente 10000 puntos en una ventana deslizante: a medida que ingresan datos nuevos (a 40Hz), los datos viejos se desplazan hacia la izquierda fuera del rango visible. Y necesita mantener esta velocidad durante al menos 20 - 30 minutos (un total de aproximadamente 75 - 100 mil puntos por flujo de datos).

Mi implementación personalizada actual se basa en un componente que hereda de Shape y usa un StreamingGeometry para DefinigGeometry. Los datos que llegan del dispositivo se pasan al componente a través de una cola para mejorar el rendimiento debido al "efecto de estallido" inherente y, después de una operación de dequeue, el componente se invalida.

Entonces, mi pregunta es, ¿estoy en el camino correcto o estoy completamente equivocado? ¿Cuál es la forma más eficiente de lograr dicha visualización de datos en WPF? Cualquier ayuda o sugerencia sería muy apreciada.

+0

La interoperabilidad de DirectX es la dirección. Algunos usarán SlimDX pero es una gran curva de aprendizaje de dependencia y abstracción. Recomiendo el uso directo de DX9 o (DX11 a través de DXGI) mientras agita con la interfaz D3DImage de WPF. Sigue siendo una curva de aprendizaje, pero igual que slimdx y más fácil de mantener para crear un dispositivo DX, contexto, búfer, shader y obtener su aplicación con Direct3D. Los documentos son terribles pero lo suficientemente buenos, y una vez hecho, has logrado algo genial sin dependencia de los demás. Vea nuestro mundo real [demostración de gráficos 18M] (http://www.gigasoft.com) con WPF WinForm MFC EXEs, principalmente audio WAV y datos GIS. – Robert

+0

@Robert, gracias por la entrada. Idealmente me gustaría que w DX9 sea compatible con XP pero no pude deducir que dibuje líneas arbitrariamente gruesas con D3D de una manera comparable a la calidad de las rutas con alias que logré con WPF. ¿Alguna sugerencia? ¿Tuviste que escribir tu propia rutina de tesselación? Incluso estaría bien con DX10 si puedo obtener lo que quiero rendimiento/calidad. –

+0

Las líneas gruesas son la desventaja más grande con D3D. Aunque no es un gran problema. Si puede diseñar alrededor de un tamaño de gráfico conocido, entonces la lógica del búfer de vértices conocerá un tamaño y es una simple cuestión de dibujar la línea como cuadrantes (triángulos dobles) b) si no desea reconstruir su búfer de vértices en función de un tamaño de evento, entonces el sombreador debe estar diseñado para mantener una relación de aspecto y ajustes de tamaño físico en un búfer constante, luego estos datos se utilizan dentro del sombreado de vértices para modificar los cuadrantes de línea sobre la marcha. Este es el caso para dx9/11. O puede usar D2D y la lógica de reducción de datos para trazar grandes cantidades. – Robert

Respuesta

1

El modo de reproducción retenida de WPF hace que dibujar/redibujar gráficos e imágenes personalizados sea difícil de lograr, especialmente cuando esos dibujos contienen una gran cantidad de objetos.

El dibujo más rápido que he podido hacer en WPF es utilizando un WritableBitmap y llenándolo con una llamada a WritePixels, que puede ser una opción para usted. Excedió ampliamente la velocidad de dibujo del gráfico que escribí utilizando PathGeometries y dibujando en un lienzo.

Me interesa saber si hay un término medio más rápido.

+0

Un posible 'término medio' sería dibujarlo en un RenderContext en una anulación OnRender. Esto proporciona una enorme sensación de alivio mental, ya que se parece mucho más a la pintura trad GDI/WinForms ... (Más en serio, debería dar acceso a primitivas de representación decentes sin la sobrecarga de construir el árbol de modo retenido que es tan a menudo simplemente una repetición redundante de su propio objeto-gráfico) –

+0

Me temo que OnRender todavía usa la canalización de modo retenido. Todo lo que está haciendo es publicar objetos en modo retenido en la canalización de gráficos usando esto. Para probarlo, ponga un punto de interrupción dentro y minimice/maximice su ventana.Si se tratara de un método de modo inmediato (por ejemplo, OnPaint in Winforms), obligaría a volver a dibujar. No estoy 100% seguro, pero creo que el redimensionamiento tampoco hará que OnRender se active a menos que establezcas esto como una bandera. –

1

Revelación: Yo propio software ABT y han desarrollado SciChart, además de haber contribuido a la biblioteca de código abierto WriteableBitmapEx

Desafortunadamente usted no está perdiendo nada. El motor de renderización de modo retenido en WPF/Silverlight ofrece un rendimiento bajo para este tipo de trabajo. Trabajé en una serie de sistemas que se actualizaron de Windows Forms a WPF, donde el cliente se sintió muy decepcionado por el rendimiento de renderizado de este marco "GPU acelerado".

De todos modos, hay una manera. Use renderizado de modo inmediato. Consulte las clases WriteableBitmap o InteropBitmap. Hay una excelente biblioteca de código abierto llamada WriteableBitmapEx por Rene Schulte a la que he contribuido. WriteableBitmapEx proporciona algunas funciones de dibujo de bajo nivel (estilo GDI) para dibujar directamente en mapa de bits. Esto ofrece un rendimiento fantástico y una huella de memoria baja (sí, el marco sofisticado de MS es superado por un par de bucles forzados optimizados y una matriz de puntero a byte).

Si se trata de un componente de gráfico de terceros específico que está buscando, intente SciChart. SciChart es un componente que he desarrollado yo mismo que busca llenar el vacío para WPF o gráficos científicos/de stock de alto rendimiento. Utiliza algoritmos de remuestreo exclusivos para reducir el conjunto de datos antes de dibujar, renderizado de modo inmediato y una gran cantidad de otras optimizaciones como la agrupación de objetos y la reutilización de recursos, lo que genera tasas de actualización uniformes para conjuntos de datos de gran tamaño y escasa memoria.

Haga clic en la demostración de rendimiento en el enlace de arriba (requiere Silverlight 4). Actualmente, SciChart puede generar 1,000,000 de puntos de datos a alrededor de 5FPS (dependiendo del hardware de destino), lo que equivale a 5,000,000 de puntos de datos por segundo. Una licencia comercial estará disponible en el primer trimestre de 2012.

+0

@DrABT - por curiosidad, ¿admite WritableBitmapEx el grosor de alias arbitrario como grosor o tuvo que implementarlo por separado en el componente de SciChart? –

+0

Hola Miky, WBEX no es compatible con esto hasta donde sé. Lo hemos implementado nosotros mismos con algunos algoritmos diferentes para obtener una buena compensación entre calidad y velocidad. Se discute un algoritmo simple en los foros de WBEX donde precampana una elipse de tamaño N y la recorta en todos los puntos de una línea bresenham. Sorprendentemente, esto funciona pero dará lugar a bordes dentados ya que WBEX tiene coordenadas enteras. Para obtener una línea ancha verdaderamente suave, necesita punto flotante, ¡también costoso en términos de CPU! El renderizador de alta calidad SciChart hace esto al igual que un renderizador D3D experimental. –

+0

@DrABT gracias por la respuesta rápida. No estoy trabajando activamente en esto en este momento, pero quizás vuelva a visitar nuestra implementación en algún momento. –

1

Los mejores resultados se pueden lograr mediante la programación de DirectX de bajo nivel y la utilización de sombreadores HLSL. El renderizado basado en el espacio de nombres de System.Windows.Media se debe olvidar al instante cuando el rendimiento máximo y las necesidades en tiempo real son importantes.

Pudimos desarrollar rutinas que pueden trazar más de 1000 millones de puntos de datos, p. 8 datos alimentan x 125 puntos de datos M, utilizando línea ancha, sin reducción de muestreo. Las rutinas son parte de LightningChart, tablas de WPF (y tabla de WinForms). Nos tomó como 7 años llegar a este punto ... Hicimos un billion points example, con el proyecto VS y el video de Youtube incluidos.

[Soy el líder tecnológico de LightningChart]

+0

Hola Pasi, gracias por tu respuesta; ¿LightningChart es de código abierto? si no, ¿te importaría compartir más detalles sobre qué tipo de primitivas y shaders DirectX de bajo nivel estás utilizando? ¿Estás usando Direct2D o Direct3D? ¿Y para qué estás usando los sombreadores? –

+0

Hola Mike, LightningChart no es de código abierto. Estamos utilizando Direct3D también para gráficos 2D. Direct2D es algo lento y limitado. Disculpas, no puedo compartir todos los detalles aquí en público. Nuestro rendimiento es el resultado de años de trabajo, experimentando con diferentes enfoques y necesidades reales de los clientes. –