Delphi-PRAXiS
Seite 1 von 3  1 23      

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


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:15 Uhr.
Seite 1 von 3  1 23      

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