26 Stimmen

Der leistungsfähigste Weg, um Tausende von Datenpunkten mit WPF grafisch darzustellen?

Ich habe ein Diagramm geschrieben, das Finanzdaten anzeigt. Die Leistung war gut, solange ich weniger als 10.000 Punkte als zusammenhängende Linie gezeichnet habe, indem ich PathGeometry zusammen mit PathFigure y LineSegment s. Aber jetzt muss ich bis zu 100.000 Punkte gleichzeitig anzeigen (ohne Scrollen) und es ist schon mit 50.000 Punkten sehr langsam. Ich dachte an StreamGeometry aber ich bin mir nicht sicher, da es im Grunde dasselbe ist wie ein PathGeometry die Informationen als Byte-Stream zu speichern. Hat jemand eine Idee, wie man das viel performanter machen kann oder hat vielleicht sogar schon jemand etwas Ähnliches gemacht?

EDIT: Diese Datenpunkte ändern sich nicht, wenn sie einmal gezeichnet sind. Wenn es also Optimierungsmöglichkeiten gibt, lassen Sie es mich bitte wissen (die Liniensegmente sind im Moment eingefroren).

EDIT: Ich habe StreamGeometry ausprobiert. Das Erstellen der Grafik dauerte aus irgendeinem Grund noch länger, aber das ist nicht das Problem. Das Zeichnen auf dem Diagramm nach dem Zeichnen aller Punkte ist immer noch so langsam wie die vorherige Methode. Ich denke, es ist einfach zu viele Datenpunkte für WPF zu behandeln.

EDIT: Ich habe ein bisschen herumexperimentiert und festgestellt, dass sich die Leistung etwas verbessert hat, indem ich die Koordinaten, die vorher in double waren, in int umgewandelt habe, um zu verhindern, dass WPF Anti-Aliasing Sub-Pixel-Linien.

EDIT: Vielen Dank für alle Antworten, die vorschlagen, die Anzahl der Liniensegmente zu reduzieren. Ich habe sie auf höchstens das Doppelte der horizontalen Auflösung für gestufte Linien und höchstens die horizontale Auflösung für einfache Linien reduziert und die Leistung ist jetzt ziemlich gut.

19voto

Crashworks Punkte 39230

Ich würde in Erwägung ziehen, die Anzahl der Punkte, die Sie zu rendern versuchen, herunterzurechnen. Sie haben vielleicht 50.000 Datenpunkte, aber es ist unwahrscheinlich, dass sie alle auf den Bildschirm passen; selbst wenn Sie jeden einzelnen Punkt in einer Anzeige darstellen würden, bräuchten Sie 100,000 Pixel horizontale Auflösung, um sie alle zu zeichnen! Selbst in D3D ist das eine Menge zu zeichnen.

Da Sie eher mit 2.048 Pixeln rechnen, können Sie die Punkte, die Sie grafisch darstellen, auch reduzieren und eine ungefähre Kurve zeichnen, die auf den Bildschirm passt und nur ein paar tausend Scheitelpunkte hat. Wenn der Benutzer beispielsweise einen Zeitrahmen mit 10000 Punkten grafisch darstellt, dann reduzieren Sie diese 10000 Punkte auf 1000, bevor Sie sie grafisch darstellen. Es gibt zahlreiche Techniken, die Sie ausprobieren können, von einfacher Mittelwertbildung über Median-Nachbarn bis hin zur Gaußschen Faltung (mein Vorschlag) bikubische Interpolation . Das Zeichnen einer Anzahl von Punkten, die größer ist als die Hälfte der Bildschirmauflösung, ist einfach eine Verschwendung. .

Wenn der Benutzer einen Teil eines Diagramms heranzoomt, können Sie die Abtastung ändern, um eine höhere Auflösung und eine genauere Kurvenanpassung zu erhalten.

6voto

Dathan Punkte 7137

Wenn Sie anfangen, mit Hunderttausenden von verschiedenen Scheitelpunkten und Vektoren in Ihrer Geometrie umzugehen, sollten Sie wahrscheinlich in Betracht ziehen, Ihren Grafikcode zu migrieren, um ein Grafik-Framework zu verwenden, anstatt von WPF abhängig zu sein (das, obwohl es auf Direct3D aufbaut und daher in der Lage ist, Vektorgrafiken bemerkenswert effizient zu rendern, eine Menge zusätzlichen Overhead hat, der seine Effizienz beeinträchtigt). Es ist möglich, sowohl Direct3D als auch OpenGL-Grafik-Rendering-Windows innerhalb von WPF zu hosten - ich würde vorschlagen, in diese Richtung zu gehen, anstatt weiterhin nur innerhalb von WPF zu arbeiten.

(EDIT: "DirectX" in der ursprünglichen Antwort in "Direct3D" geändert)

5voto

cplotts Punkte 13743

Ich bin gerade auf diese Frage gestoßen, aber wie ich bereits in diese Thema, der leistungsfähigste Ansatz könnte darin bestehen, gegen die Visual-Schicht von WPF zu programmieren .

Alles Visuelle in WPF geht schließlich gegen diese Schicht ... und so ist es der leichteste Ansatz von allen.

Voir diese y diese für weitere Informationen. Kapitel 14 von Matthew MacDonalds Pro WPF in C# 2008 Buch hat auch einen guten Abschnitt darüber.

Als weitere Referenz ... siehe Kapitel 2 des Buches von Pavan Podila WPF Control Entwicklung entfesselt . Auf Seite 13 erörtert er, wie DrawingVisuals eine ausgezeichnete Wahl für eine Diagrammkomponente sein könnte.

Schließlich habe ich gerade festgestellt, dass Charles Petzold schrieb ein MSDN Magazin Artikel bei dem die beste Gesamtlösung (für ein Streudiagramm) ein DrawingVisual-Ansatz war (jedenfalls was die Leistung betrifft).

5voto

Peter O'Brien Punkte 51

Eine andere Idee wäre, das Image-Steuerelement zu verwenden, wobei die Eigenschaft Source auf ein dynamisch erstelltes DrawingImage gesetzt wird.

Laut Pavan Podila in WPF Control Development Unleashed kann dieser Ansatz sehr hilfreich sein, wenn Sie Tausende und Abertausende von Bildern haben, die keine Interaktivität benötigen. Auf Seite 25 seines Buches finden Sie weitere Informationen.

Dies ist ein altes Thema, aber ich dachte, es wäre erwähnenswert, dass man mit der obigen Methode Interaktivität erreichen kann, indem man das MouseUp()-Ereignis verwendet. Sie kennen die Größe des Bildausschnitts, die Auflösung des Bildes und die Position der Maus. Sie könnten zum Beispiel die Sammlung actualScreenPoints über einen Timer verwalten, der an das Ereignis UserControl_SizeChanged angehängt ist:

    double xworth = viewport.ActualWidth / (XEnd - XStart);
    double xworth = viewport.ActualHeight / (YEnd - YStart);
    List<Point> actualScreenPoints = new List<Point>(); 
    for (var i = 0; i < points.Count; i++)
    {
        double posX = points[i].X * xworth;
        double posY = points[i].Y * yworth;
        actualScreenPoints.Add(posX, posY);
    }

Und dann, wenn Ihre MouseUp()-Ereignis auslöst, überprüfen Sie, ob einer der Punkte in der Sammlung sind innerhalb +-2px. Es ist Ihre MouseUp auf einen bestimmten Punkt.

4voto

Mark Carpenter Punkte 16847

Ich weiß nicht, wie gut es skaliert, aber ich habe einige Erfolge mit ZedGraph in WPF (WinForms-Steuerelement innerhalb eines WindowsFormsPresenter) hatte. Ich bin überrascht, dass niemand es noch erwähnt. Es lohnt sich ein Blick auf, auch wenn Sie nicht planen, es für Ihr aktuelles Projekt zu verwenden.

ZedGraph

Viel Glück!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X