TChart MaxWert

Für Fragen von Einsteigern und Programmieranfängern...
Johannes
Beiträge: 174
Registriert: Sa 9. Jan 2016, 09:30

TChart MaxWert

Beitrag von Johannes »

Hallo Gemeinde,

zur Auswertung meines Projekts "Heusinger-Steuerung" benutze ich die TChart-Komponente. Ich habe mich damit einige Zeit befasst und bin überrascht von den vielen Möglichkeiten die man hat.
Hier ist das, vorläufige, Ergebnis:

Chart.JPG


Dazu habe ich allerdings noch Fragen.
Kann man Maximalwerte einer Kurve (LineSeries) markieren und auslesen ?
Ist es möglich Schnittpunkte von Kurven ähnlich auszuwerten ?

Bei einer Suche nach Lösungen habe ich leider nix finden können.

Grüße

Hannes

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: TChart MaxWert

Beitrag von wp_xyz »

TLineSeries hat zwar die Funktion Extent, die das zwischen x/y min/max aufgespannte Rechteck zurückgibt, aber du erhält dabei nicht, welcher Datenpunktindex zum Maximum/Minimum gehört. Ich würde da einfach alle Punkte durchlaufen und das Maximum (Minimum) suchen:

Code: Alles auswählen

function FindIndexOfSeriesMax(ASeries: TChartSeries): Integer;
var
  max: Double;
  i: Integer;
begin
  if ASeries.Count > 0 then
  begin
    max := ASeries.GetYValue(0);
    Result := 0;
    for i := 1 the ASeries.Count-1 do
      if ASeries.GetYValue(i) > max then
      begin
        max := ASeries.GetYValue(i);
        Result := i;
      end;
  end else
    Result := -1;
end;

Wie du dann den Maximalwert anzeigen willst, weiß ich natürlich nicht. Recht einfach wäre hier ein Label zu setzen (nicht getestet):

Code: Alles auswählen

procedure HighlightSeriesMax(ASeries: TChartSeries);
var
  i, imax: Integer;
begin
  imax := FindIndexOfSeriesMax(ASeries);
  if imax = -1 then exit;
  // bisherige Labels löschen
  for i:=0 to ASeries.Count-1 do
    ASeries.Source.Item^[i].Text := ''
  // Label am aktuellen Maximum setzen
  ASeries.Source.Item^[imax].Text := Format('Maximum bei x=%f, y=%f',
    [ASeries.GetXValue(imax), ASeries.GetYValue(imax)]);
  // Labels anzeigen
  ASeries.Marks.Style := smsLabel;
end;

Johannes
Beiträge: 174
Registriert: Sa 9. Jan 2016, 09:30

Re: TChart MaxWert

Beitrag von Johannes »

Vielen, herzlichen, Dank !
Das hilft mir sicher weiter.
Die Möglichkeiten vom TChart sind einfach toll. Leider braucht es, jedenfalls bei mir, viel Zeit um damit zurecht zu kommen.

Ich erlaube mir noch eine Frage:
Mittels Ckeckboxes kann ich verschiedene Datenquellen auswählen. Das funktioniert gut.
Wegen der Übersichtlichkeit werden die dazugehörigen Achsbeschriftungen (LeftAxis) dazu eine - bzw ausgeblendet.
Leider ändert sich dabei auch die Breite des Chart-Fensters. Das stört mich ein wenig. Kann man das ev. ändern?

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: TChart MaxWert

Beitrag von wp_xyz »

Johannes hat geschrieben:VKann man das ev. ändern?

Ich glaube nicht, zumindest nicht einfach. Es gibt zwar seit einiger Zeit eine Eigenschaft LabelSize, die den Abstand zwischen Achsenlinie und Achsentitel festzurrt, und mit der man eine fehlende Achse ausgleichen könnte, aber damit rutscht die Achsenbeschriftung immer weiter vom Diagramm weg, was viel unangenehmer ist als die variierenden Chartgröße.

Johannes
Beiträge: 174
Registriert: Sa 9. Jan 2016, 09:30

Re: TChart MaxWert

Beitrag von Johannes »

Nun wollte ich die Function "FindIndexOfSeriesMax(ASeries: TChartSeries): Integer;" einmal ausprobieren.

Leider mit mäßigem Erfolg:
Projekt kompilieren, Ziel: Heusinger.exe: Exit code 1, Fehler: 1
steuerung.pas(368,44) Error: Identifier not found "TChartSeries"

Was muss ich ev. bei mir noch anpassen ?
Der Name meines TChart ist TChart1. Aber auch wenn ich die Function so deklariere : (ASeries: TChart1Series) klappt das nicht.

P:S: Mit der Achsbeschriftung / Diagramm kann ich leben. Danke !

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: TChart MaxWert

Beitrag von wp_xyz »

Johannes hat geschrieben:Error: Identifier not found "TChartSeries"

Das braucht die Unit TACustomSeries.

Johannes hat geschrieben:Was muss ich ev. bei mir noch anpassen ?
Der Name meines TChart ist TChart1. Aber auch wenn ich die Function so deklariere : (ASeries: TChart1Series) klappt das nicht.

Natürlich nicht, denn TChartSeries ist die Bezeichnung der Klasse (=Typ), nicht der Instanz (=Variable). Wenn du deinen Chart mit TChart1 benennst, kannst du das machen, aber das schafft bei allen erhebliche Verwirrung, denn das vorangestellte T bezieht sich üblicherweise auf die Typ-Berzeichnung. Wenn du mit dem T in der Variablen etwas spezielles meinst (z.B. T = Total, also TotalChart: TChart), dann würde ich das ausschreiben oder anders abkürzen.

Johannes
Beiträge: 174
Registriert: Sa 9. Jan 2016, 09:30

Re: TChart MaxWert

Beitrag von Johannes »

Sorry, dass war natürlich ein Tippfehler. Das Ding nennt sich "Chart1" (ohne T).

Mathias
Beiträge: 6194
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TChart MaxWert

Beitrag von Mathias »

Ich habe mir Jonhannes Screenshot im ersten Post angeguckt.

Das die TChart-Komponente so mächtig ist, hätte ich nie gedacht. :shock:
Die muss ich wohl auch mal genauer anschauen.
Da kann man Excel direkt in die Tonne schmeissen.

Ich hatte mal ein Diagramm, komplett selbst gemacht, die war ein recht grosser Aufwand.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Johannes
Beiträge: 174
Registriert: Sa 9. Jan 2016, 09:30

Re: TChart MaxWert

Beitrag von Johannes »

Hallo Mathias,

es lohnt sich wirklich, aus meiner Sicht, diese Komponente kennen zu lernen. Du wirst sicher einen schnelleren Einstieg finden als ein Anfänger wie ich es leider immer noch bin.

@ wp_xyz
Deine Function läuft jetzt. (Ich hatte erst die "Unit TACustomSeries" manuell eingefügt, dann aber eine Meldung erhalten, dass diese schon vorhanden wäre. Es hatte nur der Uses-Eintrag gefehlt.)
Leider funktioniert aber die procedure "HighlightSeriesMax(ASeries: TChartSeries)" nicht.
Ich erhalte folgende Fehlermeldungen:

Projekt kompilieren, Ziel: Heusinger.exe: Exit code 1, Fehler: 5
steuerung.pas(1641,24) Error: Wrong number of parameters specified for call to "GetItem"
tacustomsource.pas(147,14) Error: Found declaration: GetItem(LongInt):^TChartDataItem;
steuerung.pas(1643,22) Error: Wrong number of parameters specified for call to "GetItem"
tacustomsource.pas(147,14) Error: Found declaration: GetItem(LongInt):^TChartDataItem;
steuerung.pas(1646,26) Error: Identifier not found "smsLabel"

Fehlt noch eine Komponente bei mir?

Benutzeravatar
photor
Beiträge: 443
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 2.2.6 FPC 3.2.2 (Gtk2)
CPU-Target: 64Bit

Re: TChart MaxWert

Beitrag von photor »

Mathias hat geschrieben:Ich habe mir Jonhannes Screenshot im ersten Post angeguckt.

Das die TChart-Komponente so mächtig ist, hätte ich nie gedacht. :shock:


Volle Zustimmung! Ich versuche gerade selbst ein paar Plots in meinem Programm aufzuhübschen. Und ich vermisse ein gutes Tutorial zu TChart. Die Artikel im Wiki habe ich durch; die Grundzüge werden ja erklärt, aber für das nette Drum-Rum fühle mich trotzdem ein wenig allein gelassen :?

Gibt's da vielleicht was weietrführendes (geht speziell an johannes :wink: )?

Ciao,

Photor

Johannes
Beiträge: 174
Registriert: Sa 9. Jan 2016, 09:30

Re: TChart MaxWert

Beitrag von Johannes »

Leider bin ich noch weit davon entfernt Ratschläge geben zu können. Das was ich bisher zu Stande gebracht habe basiert auf zeitintensiver Suche.
Der Code dazu würde wohl einiges Grinsen bei den Profis aufkommen lassen. Auch sind meine Englischkenntnisse oft nicht ausreichend um die Ergebnisse meiner Suchen im WWW zu verstehen.
Viele Informationen liefert auch dieses Forum. Das hat mir bisher am meisten geholfen.
Weiterführende Literatur habe ich leider nicht finden können.
Konkrete Fragen zu meinem Machwerk werde ich natürlich gern versuchen zu beantworten.

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: TChart MaxWert

Beitrag von wp_xyz »

Johannes hat geschrieben:Projekt kompilieren, Ziel: Heusinger.exe: Exit code 1, Fehler: 5
steuerung.pas(1641,24) Error: Wrong number of parameters specified for call to "GetItem"
tacustomsource.pas(147,14) Error: Found declaration: GetItem(LongInt):^TChartDataItem;
steuerung.pas(1643,22) Error: Wrong number of parameters specified for call to "GetItem"
tacustomsource.pas(147,14) Error: Found declaration: GetItem(LongInt):^TChartDataItem;
steuerung.pas(1646,26) Error: Identifier not found "smsLabel"

Ich hatte das nicht getestet, sondern "frei Schnauze" geschrieben, und das passiert das eben... Also: Die Items einer ChartSource sind ein Array, in dem die Datenpunkte (TChartDataItem) gespeichert sind, aber nicht direkt, sondern als Pointer. Daher muss das Pointer-Deferenzierungshäkchen hinter die eckige Klammer.

Bei smsLabel fehlt die Unit TAChartUtils. Diese ist übrigens ein guter Kandidat, wenn man zur Laufzeit mit TAChart arbeitet und Typen-Bezeichner nicht gefunden werden. Wichtig auch TAGeometry und TATypes.

Hier ist eine lauffähige Version. Zum Testen einfach einen Chart, eine LineSeries und eine Checkbox aufs Formular klicken, und die entsprechenden beiden Eventhandler zuweisen:

Code: Alles auswählen

unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, TAGraph, TASeries, Forms, Controls, Graphics,
  Dialogs, StdCtrls, TACustomSeries;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Chart1: TChart;
    Chart1LineSeries1: TLineSeries;
    CheckBox1: TCheckBox;
    procedure CheckBox1Change(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
    function FindIndexOfSeriesMax(ASeries: TChartSeries): Integer;
    procedure HighlightSeriesMax(ASeries: TChartSeries; AEnable: Boolean);
  public
    { public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.lfm}
 
uses
  TAChartUtils;
 
{ TForm1 }
 
function TForm1.FindIndexOfSeriesMax(ASeries: TChartSeries): Integer;
var
  max: Double;
  i: Integer;
begin
  if ASeries.Count > 0 then
  begin
    max := ASeries.GetYValue(0);
    Result := 0;
    for i := 1 to ASeries.Count-1 do
      if ASeries.GetYValue(i) > max then
      begin
        max := ASeries.GetYValue(i);
        Result := i;
      end;
  end else
    Result := -1;
end;
 
procedure TForm1.HighlightSeriesMax(ASeries: TChartSeries; AEnable: Boolean);
var
  i, imax: Integer;
begin
  // bisherige Labels löschen
  for i:=0 to ASeries.Count-1 do
    ASeries.Source.Item[i]^.Text := '';
  if AEnable then begin
    // Maximum suchen
    imax := FindIndexOfSeriesMax(ASeries);
    if imax = -1 then exit;
    // Label am aktuellen Maximum setzen
    ASeries.Source.Item[imax]^.Text := Format('Maximum bei x=%g, y=%g',
      [ASeries.GetXValue(imax), ASeries.GetYValue(imax)]);
    // Labels anzeigen
    ASeries.Marks.Style := smsLabel;
  end else
    ASeries.Marks.Style := smsNone;
end;
 
procedure TForm1.CheckBox1Change(Sender: TObject);
begin
  HighlightSeriesMax(Chart1LineSeries1, Checkbox1.Checked)
end;
 
procedure TForm1.FormCreate(Sender: TObject);
const
  MIN = -10;
  MAX = +10;
  N = 101;
var
  i: Integer;
  x: Double;
begin
  for i:=0 to N-1 do begin
    x := MIN + (MAX - MIN) * i / (N-1);
    if x = 0 then
      Chart1LineSeries1.AddXY(x, 1.0) else
      Chart1LineSeries1.AddXY(x, sin(x)/x);
  end;
end;
 
end.
Zuletzt geändert von wp_xyz am Fr 17. Jun 2016, 21:30, insgesamt 1-mal geändert.

Mathias
Beiträge: 6194
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TChart MaxWert

Beitrag von Mathias »

aber für das nette Drum-Rum fühle mich trotzdem ein wenig allein gelassen

Könnte es sein, das gewisse Functionen in TChart noch recht neu ist ?

Wen ich die Trunk von Lazarus aktualisieren, habe ich mehrmals gesehen, das an dieser Komponente gearbeitet wird.


Auch sind meine Englischkenntnisse oft nicht ausreichend

Ich dachte, die Deutschen müssten dies in der Grundschule lernen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: TChart MaxWert

Beitrag von wp_xyz »

photor hat geschrieben:Und ich vermisse ein gutes Tutorial zu TChart. Die Artikel im Wiki habe ich durch; die Grundzüge werden ja erklärt, aber für das nette Drum-Rum fühle mich trotzdem ein wenig allein gelassen :?

Gibt's da vielleicht was weietrführendes (geht speziell an johannes :wink: )?

Hey Photor, da schreibt man 10 Tutorials über TAChart, und es ist den Leuten immer noch nicht recht :(

Im Ernst, die Anwendungen sind so vielseitig, da kann man nicht für jeden spezifischen Fall ein Tutorial schreiben. Die Grundlagen für die mehrfachen y-Achsen, die Johannes verwendet, gibt es als Tutorial. Die schraffiert hinterlegten Flächen sind als Area-Series realisiert (gab es dazu nicht eine Frage hier?), man könnte auch ChartStyles nehmen, wofür es wieder ein Tutorial gibt. Generell gilt: Sich die Grundlagen erarbeiten und dann Hirn einschalten. Und wenn's nicht klappt hier fragen.

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: TChart MaxWert

Beitrag von wp_xyz »

Könnte es sein, das gewisse Functionen in TChart noch recht neu ist ?

Momentan ändert sich relativ wenig. Ab und zu sind halt ein paar Bugs zu fixen. Und vor einigen Monaten kam TFieldSeries dazu, mit der man Vektor-Felder ausgeben kann. Und irgendwann werde ich sicher die Muße finden, die hier mal versprochene Gantt-Series fertigzustellen.

Auch sind meine Englischkenntnisse oft nicht ausreichend

Das ist schlecht. Wenn du programmieren willst, musst du wenigstens soviel Englisch können, um eine Dokumentation lesen zu können. Es gibt nicht alles auf Deutsch.

Antworten