Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Cross-Platform-Entwicklung (https://www.delphipraxis.net/91-cross-platform-entwicklung/)
-   -   Delphi FMX: Schnelles zeichnen gesucht (https://www.delphipraxis.net/190966-fmx-schnelles-zeichnen-gesucht.html)

Sherlock 24. Nov 2016 10:12

FMX: Schnelles zeichnen gesucht
 
Hallo zusammen,

ich arbeite an einem Projekt, bei dem ich Messwerte eines externen Gerätes auf dem Bildschirm plotten muss. Es gibt dabei folgende Rahmenbedingungen:
es kommen vier Messungen mit jeweils drei Werten pro Sekunde rein - angezeigter Maßstab ist 1cm/Minute
  • die Messung kann auch mal ein bis zwei Tage dauern
  • es sollte möglich sein flüssig hin und her zu scrollen
  • es gibt ein Aktualisierungsintervall, das derzeit bei 6 Sekunden liegt, eventuell später auf 3 reduziert wird
Bisher bin ich wie folgt vorgegangen:
  • ich habe einen Thread, der die Messdaten abholt, Intervall 5s, Abholdauer 1s
  • ich habe einen weiteren Thread, der die kompletten Messdaten in zwei Bitmaps immer wieder neu zeichnet, sobald eine Aktualisierung der Daten anliegt und die Images auf der Oberfläche aktualisiert
Das läuft soweit so gut. Nur stellt sich heraus, daß das Neuzeichnen keine so gute Idee ist. Ab ca 30 Minuten Messdauer, benötigt das Zeichnen mehr Zeit als das Holen der Daten, und es wird immer langsamer. Also habe ich zumindest da einen Flaschenhals. Ich zeichne wie folgt (vereinfacht und aufs wesentliche reduziert, vermutlich nicht compilierbar):
Delphi-Quellcode:
procedure TCTGGrid.PaintFHR(aBitmap: TBitmap);
var
  rowList     : TStringList;
  i           : Integer;
  GID1Path    : TPathData;
  GID2Path    : TPathData;
  myX, myY    : Single;
begin
  if aBitmap.Canvas.BeginScene then
    try
      GID1Path := TPathData.Create;
      GID2Path := TPathData.Create;
      try
        // In der fValuelist stehen alle Messwerte als Stringliste zur Verfügung. Im Prinzip ist
        // ist das eine CSV-Datei, in eine Stringliste eingelesen.
        for i := 0 to fValueList.Count - 1 do
        begin
          // Methoden aufrufen, die aus einem Zeitstempel die X-Koordinate und
          // aus einem Messwert die y-Koordinate errechnen. Ich bezweifle, daß die zeitkritisch
          // sind. Der Aufruf ist auch nur exemplarisch zu verstehen.
          myX := ConvertTimeToXCoord(StrToFloatDef(fvaluelist[i][keyTimeOffset], 0, fs));
          myY := ConvertBPMToYCoord(StrToFloatDef(fvaluelist[i][aGID1Key], 0, fs));
          GID1Path.LineTo(Pointf(myX, myY));
          myY := ConvertBPMToYCoord(StrToFloatDef(fvaluelist[i][aGID2Key], 0, fs));
          GID2Path.LineTo(Pointf(myX, myY));
        end;
        aBitmap.Canvas.Stroke.Dash := TStrokeDash.Solid;
        aBitmap.Canvas.Stroke.Color := claBlack;
        aBitmap.Canvas.StrokeThickness := 1;
        aBitmap.Canvas.DrawPath(GID1Path, 1);
        aBitmap.Canvas.Stroke.Color := claBlue;
        aBitmap.Canvas.DrawPath(GID2Path, 1);
      finally
        GID1Path.Free;
        GID2Path.Free;
      end;
    finally
      aBitmap.Canvas.EndScene;
    end;
Für eine Stunde dauert das mehr als 10 Sekunden... das ist zu langsam für meinen Anwendungsfall.

Frage eins ist jetzt: Ist es möglich hier etwas zu beschleunigen? Was für Optionen gibt es? Kann ich vielleicht ein bestehendes Image verbreitern und ergänzen? So daß also nur meine 6 Sekunden Intervalle neu zu zeichnen sind, was eine Sache von Millisekunden ist.

Frage zwei: Wie überkomme ich die Bitmapgrößenbeschränkung? Die maximale Breite ist schnell erreicht.

Sherlock

himitsu 24. Nov 2016 10:22

AW: FMX: Schnelles zeichnen gesucht
 
Das wird für jeden Refresh neu gemalt?
* vorher malen und das fertige Bild auf's Canvas malen nutzen

* StringList und die Stringkonvertierungen weg -> eine TList<> mit den Floats
* und diese Floats schon vorher mit Convert###To#Coord konvertieren
* oder die TPathData vorher generieren und dann nur noch auf's Canvas malen

Sherlock 24. Nov 2016 10:27

AW: FMX: Schnelles zeichnen gesucht
 
OK, mir ist während des Schreibens auch gekommen, daß die Konvertierung eventuell doch nicht so schnell gehen könnte wie gedacht. Da gehe ich sofort ran. Ist insgesamt ja auch schöner dann. Danke.

Was das angeht
Zitat:

Zitat von himitsu (Beitrag 1354584)
* vorher malen und das fertige Bild auf's Canvas malen nutzen
...
* oder die TPathData vorher generieren und dann nur noch auf's Canvas malen

So denke ich das ich das tue... also der Thread zeichnet die Bitmap, und wenn er damit durch ist wird die Bitmp auf das Image in der Anwendung "synchronisiert". Nur im Thread braucht es schon verdammt lange die Bitmap zu malen, das haben Zeitmessungen ergeben. :\

Sherlock

stahli 24. Nov 2016 10:34

AW: FMX: Schnelles zeichnen gesucht
 
Es gab kürzlich mal einen ähnlichen Thread: http://www.delphipraxis.net/190798-[fmx]-eigene-komponente-aufbau-performance.html

Ich würde aus der Datenmenge immer den "sichtbaren Bereich" ermitteln und nur den als Grafik berechnen.
Eine Scrollbar dient dann dazu, den sichtbaren Ausschnitt auszuwählen.

Oder habe ich Dich falsch verstanden?

Sherlock 24. Nov 2016 10:39

AW: FMX: Schnelles zeichnen gesucht
 
Im Prinzip richtig verstanden, ich möchte aber "weich" scrollen können, vor allem auf mobilen Devices. Darum ein Bild so groß wie möglich mit so vielen Daten wie möglich...

Bin aber jetzt gerade schonmal dabei die Datenstruktur zu optimieren, um die Stringkonvertierungsaufrufe beim zeichnen zu eliminieren... wie blöd, das ich das nicht selbst gesehen habe :stupid:.

Sherlock

Uwe Raabe 24. Nov 2016 10:41

AW: FMX: Schnelles zeichnen gesucht
 
Ich bin ja immer geneigt, Dinge zu nehmen, die schon da sind. Hier würde ich mal einfach das in Delphi mitgelieferte
Delphi-Quellcode:
TChart
mit einer FastLine-Series in den Ring werfen.

himitsu 24. Nov 2016 12:18

AW: FMX: Schnelles zeichnen gesucht
 
Erstelle dir vorher mehrere TPath, immer ausschnittsweise, also ideal jeweils so groß oder halb so groß, wie die Anzeige breit ist.
Dann brauchst du nur noch jeweils die TPath "live" zeichnen zu lassen, die grade sichtbar sind.

TiGü 24. Nov 2016 13:21

AW: FMX: Schnelles zeichnen gesucht
 
Ab 30 Minuten ist die Anzahl der Messwerte in fValueList zuviel.
Wie schon von stahli vorgeschlagen anstatt von
Delphi-Quellcode:
for i := 0 to fValueList.Count - 1 do
einfach von
Delphi-Quellcode:
for i := MesswertVomBeginnDesSichtbarenBereichs to MesswertVomEndeDesSichtbarenBereichs do
.
Das ist schnell und wird auch auf mobilen Devices gut funktionieren. Bei denen kommst du mit deinem Ansatz eh schnell ans Ende.
Korrigiere mich wenn ich mich irre, aber bei steigender Anzahl der Messwerte werden doch eh die meisten Messwerte auf die gleichen Pixel gezeichnet, oder?

Delphi-Laie 24. Nov 2016 20:42

AW: FMX: Schnelles zeichnen gesucht
 
Hallo liebe Leute, ich stehe vor dem prinzipiell gleichen Problem und hätte dazu vielleicht eine eigene Anfrage gestartet, so melde ich mich jetzt aber erstmal hier.

Um die FMX-Graphik zu beschleunigen, gab mir ein hilfreiches DP-Mitglied folgenden Hinweis:

"Du must FMX wie eine Game-Engine programmieren...
Delphi-Quellcode:
TThread.Synchrionize(NIL,Procedure
begin
Form.BeginUpdate
Form.Image1.Bitmap.Assign(NewBitmap)
Form.EndUpdate
end
(Teil eines Threads der wartet bis alles fertig ist)

Somit machst Du locker 1000 FPS Fullscreen Images..."

Leider bekam ich aus ihm nicht mehr herausgekitzelt.

Hat jemand ein funktionierendes FMX-Graphik-Beispielprojekt oder kann das Zitat noch ein wenig ergänzen, bitte?

Zwar kenne ich mich mit Threadprogrammierung ein kleines bißchen aus, jedoch längst nicht soviel, daß mir nun genau klar ist, was zu programmieren ist.

Ergänzung: Das mit dem Image auf dem Formular ist inzwischen auch geklärt.

Rollo62 25. Nov 2016 07:59

AW: FMX: Schnelles zeichnen gesucht
 
Hast du das denn mal versucht mit z.B. zwei festen FullScreen Images im Wechsel ?
Welche FPS bekommst du da raus, das wäre ja der BestCase.
1. Das wäre das reine Bitmap-Schreiben.

Dazu käme ja noch das Zeichnen des Bitmaps, was wohl i.d.R. länger als 1ms dauern wird gerade bei
komplexen Daten.
2. Das wäre das Erzeugen des Hintergrundbildes

Ich denke 1. + 2. wird unter 1000FPS liegen, es sei denn das es wirklich nur um einzelne, oder vorberechnete Bitmaps geht.
Wäre aber schön wenn ich mich da irre.

Rollo

Daniel 25. Nov 2016 09:07

AW: FMX: Schnelles zeichnen gesucht
 
Ist die Verwendung von FMX Pflicht?
Ich werde hier mit 60 Messwerten pro Sekunde konfrontiert, die ich wegspeichern und - in Intervallen - verarbeiten und zeichnen muss, am Ende dann auch die Daten von 6-12 Stunden. Ich bin vom VCL-TBitmap auf die Graphics32-Bibliothek umgestiegen und damit war das Thema "Grafikausgabe" erledigt. Das Zeichnen erfolgt schnell genug, dass ich mich wieder in Ruhe dem verrechnen/glätten/eindampfen der Daten widmen kann.

Sherlock 25. Nov 2016 09:41

AW: FMX: Schnelles zeichnen gesucht
 
Leider ist FMX für mich Pflicht, weil ich auf iDevices, Windows, Androiden und MacOS laufen muss...äh, also mein Programm. Also klassischer FMX Use Case :D

Ich habe gestern Nachmittag meine Datenstruktur umgebaut, bin noch am Testen. Eine Beschleunigung ist auf jeden Fall festzustellen. Schaue jetzt noch nach andern Zeichenstrategien.

Sherlock

Delphi-Laie 25. Nov 2016 14:21

AW: FMX: Schnelles zeichnen gesucht
 
Zitat:

Zitat von Rollo62 (Beitrag 1354666)
Hast du das denn mal versucht mit z.B. zwei festen FullScreen Images im Wechsel ?

Rollo62, danke für Deine Antwort, aber ich habe es nunmehr aufgegeben. FMX-Graphik ist mir einfach zu kompliziert und - trotz aller möglichen Versuche damit - auch zu langsam. Und wenn man es auch auf Windows XP laufen lassen möchte, wird es evtl. noch schwieriger. Auch wenn beständiges Lernen auch was für sich hat, so ziehe ich meine Motivation auch und vor allem daraus, mit vertretbarem Auwand spätestens mittelfristig auch zufriedenstellende Ergebnisse zu erreichen.

Hier muß ich wirklich mal die Lazarus-/Freepascalprogrammierer loben: Obwohl diese eine "VCL-artige", also delphiähnliche Graphik implementierte, ist diese dennoch - mehr oder weniger? - plattformunabhängig. Meine Lazarus-Compilate erfüllen jedenfalls meine Vorstellungen deutlich besser als die mit Delphi XEx erzeugten FMX-Resultate.

Vielleicht hat es damit zu tun, daß man sich für VGScene entschied, keine Ahnung. Daß es aber grundsätzlich auch mit einem VCL(-Derivat) möglich gewesen wäre, beweist die Lazarus-/FP-Entwicklergemeinde.

Rollo62 25. Nov 2016 16:25

AW: FMX: Schnelles zeichnen gesucht
 
Dann versuch es doch noch einmal mit TChart, wie schon Uwe richtig vorgeschlagen hatte.

Zitat:

Zitat von Uwe Raabe (Beitrag 1354592)
Ich bin ja immer geneigt, Dinge zu nehmen, die schon da sind. Hier würde ich mal einfach das in Delphi mitgelieferte
Delphi-Quellcode:
TChart
mit einer FastLine-Series in den Ring werfen.

Das kann schon eine ganze Menge, ist gut konfigurierbar und sollte auch schnell genug sein.
Wenn das nicht schnell genug läuft wird es sowieso schwierig werden.

Rollo

Sherlock 28. Nov 2016 08:41

AW: FMX: Schnelles zeichnen gesucht
 
Ja, ich werde mich wohl ins TeeChart reinfuchsen, hoffentlich ist die inkludierte Variante ausreichend für meinen Bedarf.

Sherlok

Sherlock 29. Nov 2016 12:43

AW: FMX: Schnelles zeichnen gesucht
 
Zitat:

Zitat von Mavarik (Beitrag 1354925)
Zu Deiner Zeichenroutine...

Musst Du immer wieder gemäß min max neu skalieren?

Wenn nein -> OMG, warum erzeugst Du jedes mal eine Monster-Bitmap, die Werte ändern sich doch nicht mehr?

Zeigst Du alle Werte immer an auf einem Bildschirm oder ist das eine große horizontale Bitmap mit jedem einzelnen Wert?

Also skaliert habe ich auf 1cm/Minute, indem ich einmalig die Skalierung des Systems lese und davon abhängig dann über die Pixel pro Centimeter einzeichne. Es wird also nur einmal skaliert... pro Bitmaperzeugung.
Ich würde ja gerne einfach nur die neuen Werte anhängen. Es ist eine große horizontale Bitmap. Und irgendwann ist diese Bitmap natürlich zu breit, so daß ich mir behelfen müsste mit mehreren Bitmaps aneinandergeklebt, oder sowas.

Sherlock

Mavarik 29. Nov 2016 13:07

AW: FMX: Schnelles zeichnen gesucht
 
Zitat:

Zitat von Delphi-Laie (Beitrag 1354696)

FMX-Graphik ist mir einfach zu kompliziert und - trotz aller möglichen Versuche damit - auch zu langsam.

FMX nutz die GPU - wenn man es richtig macht...

Bedeutet FMX ist gerade in der Grafikausgabe so schnell wie es Deinen Hardware ermöglicht... Auf jeden Fall schneller als ALLES was in einfachem Pascal implementiert ist!

Abgesehen von ein paar Taktzyklen overhead, hat man nahezu reine DirectX performance...

Zitat:

Zitat von Sherlock (Beitrag 1354927)
Also skaliert habe ich auf 1cm/Minute, indem ich einmalig die Skalierung des Systems lese und davon abhängig dann über die Pixel pro Centimeter einzeichne. Es wird also nur einmal skaliert... pro Bitmaperzeugung.
Ich würde ja gerne einfach nur die neuen Werte anhängen. Es ist eine große horizontale Bitmap. Und irgendwann ist diese Bitmap natürlich zu breit, so daß ich mir behelfen müsste mit mehreren Bitmaps aneinandergeklebt, oder sowas.

Sherlock

Dann nimm doch
1. jeweils für eine Minute eine eigene Bitmap und bau dir daraus für den Bildschirm eine Grafik...
2. baue diese Grafik im Hintergrund und stelle diese dann dar...
3. Keine Scrollbox (ginge zwar auch) einfach beim scrollen neu zusammen stellen...
4. so schaffst Du mindestens 60 FPS... Wahrscheinlich eher 1000 FPS (je nach Auflösung)

Mavarik

Sherlock 29. Nov 2016 13:14

AW: FMX: Schnelles zeichnen gesucht
 
An dieser Methode bin ich gerade dran. :D

Sherlock

Sherlock 1. Dez 2016 10:51

AW: FMX: Schnelles zeichnen gesucht
 
Die Teilbilder malen in der Tat Pfeilschnell, passen dafür aber nicht schön zusammen. Ich vermute Antialiasing. Wie kann ich das beim TBitmap.Canvas.DrawPath abschalten?

Sherlock

Mavarik 1. Dez 2016 10:58

AW: FMX: Schnelles zeichnen gesucht
 
Zitat:

Zitat von Sherlock (Beitrag 1355105)
Die Teilbilder malen in der Tat Pfeilschnell, passen dafür aber nicht schön zusammen. Ich vermute Antialiasing. Wie kann ich das beim TBitmap.Canvas.DrawPath abschalten?

Sherlock

Kind auf Original?
Scale auf 1?

Rollo62 1. Dez 2016 11:35

AW: FMX: Schnelles zeichnen gesucht
 
Verstehe nicht so ganz was du jetzt machst, du nimmst Teilbilder und scrollst die durch ?
Also ein Bild für eine Minute, und bei 60 Minuten 60 Bilder hintereinander ?

Das fände ich aber etwas gefährlich, wenn dem so sein sollte. Das klingt nach Memory-Overflow.

Ich würde vielleicht 2 Teilbilder nehmen, frame1, frame2, und diese dann jeweils umschalten.
Eines ist aktiv, whährend das andere dann im Hintergrund aufgebaut wird, und dann das neue Umschalten.
Die Steuerung wo du gerade in den Daten bist würde ich versuchen in den Daten zu filtern, also
nur das aktuelle Anzeige-Fenster in den Daten auf das Bitmap malen.

Oder verstehe ich das etwa falsch was du vorhast ?

Ich meinte ja auch schon dass das Anzeigen der Teilbilder sehr schnell sein kann, die Frage ist
wie schnell das Malen der Daten sein kann.
Wenn deine Daten endlos anwachsen hast du wohl wenig Chancen, eben nur mit dem Filtern der Daten
zu einem Anzeige-Fenster.
Oder musst du immer die kompletten Daten auf einem Frame anzeigen ?

Rollo

Sherlock 1. Dez 2016 12:54

AW: FMX: Schnelles zeichnen gesucht
 
@Mavarick: Stroke.Kind := Original hat nichts geändert. Scale ist 1.

Rollo, eigentlich läuft das jetzt so, daß ein Bild von ca. 10 Sekunden Breite gezeichnet wird, und an ein bestehendes Bild angehängt wird. Faktisch gibt es nur ein Image das angezeigt wird. Im Hintergrund wird mit maximal drei Bitmaps gleichzeitig hantiert. Sollte also keine argen Probleme geben.

Sherlock

Mavarik 1. Dez 2016 13:02

AW: FMX: Schnelles zeichnen gesucht
 
Mach doch mal ne ScreenCopy

Sherlock 1. Dez 2016 13:34

AW: FMX: Schnelles zeichnen gesucht
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hier mal zum Vergleich einmal "klassisch" in einem Stück gezeichnet, und dann für rechtesten zwei bis drei Zentimeter "zusammengestückelt" wobei aktuell nicht mehr nahtlos sondern überlappend gezeichnet wird. Das sieht schon besser aus, aber ist noch nicht das "Original".

Klassisch:
Anhang 46241


Schnell:
Anhang 46242

Sherlock

Mavarik 1. Dez 2016 13:41

AW: FMX: Schnelles zeichnen gesucht
 
Zitat:

Zitat von Sherlock (Beitrag 1355140)
Hier mal zum Vergleich einmal "klassisch" in einem Stück gezeichnet, und dann für rechtesten zwei bis drei Zentimeter "zusammengestückelt" wobei aktuell nicht mehr nahtlos sondern überlappend gezeichnet wird. Das sieht schon besser aus, aber ist noch nicht das "Original".

Klassisch:
Anhang 46241


Schnell:
Anhang 46242

Sherlock

hmm...

Das sieht mir aber ganz danach aus, als hättest Du noch "ein bisschen" mehr geändert...

Sherlock 1. Dez 2016 14:26

AW: FMX: Schnelles zeichnen gesucht
 
Hehehe, in der Tat. Und weil Du das sagtest, wurde der Code nochmal überflogen und jetzt ist es hübsch :) Eine Breite der beteiligten Bitmaps wurde falsch errechnet/gesetzt. Danke für den Beistand und die Ideen! :thumb:

Sherlock

Mavarik 1. Dez 2016 14:33

AW: FMX: Schnelles zeichnen gesucht
 
Zitat:

Zitat von Sherlock (Beitrag 1355152)
Hehehe, in der Tat. Und weil Du das sagtest, wurde der Code nochmal überflogen und jetzt ist es hübsch :) Eine Breite der beteiligten Bitmaps wurde falsch errechnet/gesetzt. Danke für den Beistand und die Ideen! :thumb:

Sherlock

Ja, Fein gemacht... :lol:

Und wieviel FPS bekommst Du so?

Sherlock 1. Dez 2016 14:39

AW: FMX: Schnelles zeichnen gesucht
 
Eine Messung hab ich noch nicht gemacht, weil da noch einiges an Trümmern und Spänen drumherum aufzuräumen ist. Aber es sollte wie gewünscht laufen. :D

Sherlock


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:32 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz