Einzelnen Beitrag anzeigen

Benutzerbild von Sherlock
Sherlock

Registriert seit: 10. Jan 2006
Ort: Offenbach
3.798 Beiträge
 
Delphi 12 Athens
 
#1

FMX: Schnelles zeichnen gesucht

  Alt 24. Nov 2016, 11:12
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
Oliver
Geändert von Sherlock (Morgen um 16:78 Uhr) Grund: Weil ich es kann

Geändert von Sherlock (24. Nov 2016 um 11:23 Uhr)
  Mit Zitat antworten Zitat