AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Orientierungspunkte für die Y-Achse eines Diagramms berechnen

Orientierungspunkte für die Y-Achse eines Diagramms berechnen

Ein Thema von Harry Stahl · begonnen am 12. Mai 2017 · letzter Beitrag vom 16. Mai 2017
Antwort Antwort
Sigi Sandl

Registriert seit: 24. Jun 2008
Ort: Mallersdorf
9 Beiträge
 
Delphi 7 Professional
 
#1

AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen

  Alt 13. Mai 2017, 18:43
Hallo, Harry Stahl,

hier mein Quellcode zum Zeichnen einer Y-Achse aus vorgegebener Wertetabelle.
Teile davon sind zwanzig Jahre alt, Teile davon kann ich auf die Schnelle nicht mehr nachvollziehen, Teile sind durch Ausprobieren entstanden, geschrieben in D7.
Alles andere hab' ich versucht, einigermaßen zu kommentieren.
Für das Format des Postings entschuldige ich mich, besser kann ich's nicht.
Dann hoffe ich nur noch, daß Du was damit anfangen kannst.

Gruß
Sigi

--------------------------------------------------------------------------

Funktionen, hab' ich irgendwo abgeschrieben, was die genau machen, weiß ich nicht mehr
--------------------------------------------------------------------------------------

function Pot(Basis,Exponent : LongInt) : LongInt;
var
P : real;
n : word;
begin
P := 1;
for n := 1 to exponent do
P := P * Basis;
Pot := Trunc(P);
end;


Function Basis(W : LongInt) : LongInt;
var
n : word;
wert : LongInt;
begin
n := 0;
while (W div Pot(10,n)) > 0 do
inc(n);
Basis := Pot(10,n-1);
end;

-------------------------------------------------------------------
Im Hauptformular steht:
-------------------------------------------------------------------

var
CPC : TCanvas;
xL, yO, xR, yU : integer;
CxL, CyO, CxR, CyU : integer;
B, BC, H : integer;

IMin, IMax : Integer; // Kleinster und größter Y-Wert
Interval : Real; // davon das interval
TeilerY : integer; // Y-Achsen-Abschnitt
ARY : Real; // AspektRatio zum Zeichnen

FKx, FKy, FKxL, FKxR, FKyO, FKyU : integer;

PFirstPoint,
PLastPoint : TKurs;



Function GetRelativKoordinate(R : Real) : word;
begin
Result := yU - Trunc((ARY *((Log2(Max(R,1)))-(Log2(Max(Imin,1)))))); // yU = Diagramm Unten
end; // für absolute Darstellung die log2-Funktion weglassen


--------------------------------------------------------------------------
Y-Achse berechnen und zeichnen, der Nullpunkt des Canvas ist LinksOben
--------------------------------------------------------------------------



PLastPoint := TKurs(AktKursliste.Last); // Meine WerteListe


PK := PLastPoint;
K1 := MaxInt;
G1 := 0;
while (PK <> PFirstPoint) do // größten und kleinsten Y-Wert ermitteln
begin
K1 := Min(K1,PK.GetMinimum);
G1 := Max(G1,PK.GetMaximum);
PK := TKurs(AktKursliste.GetPrev(PK));
end;
IMin := trunc(K1/1.02); // IMin verkleinern
IMax := trunc(G1*1.02); // IMax vergrößern
Interval := (IMax-IMin+1); // damit ich nicht bis an die Grenzen zeichne

TeilerY := Basis(Trunc(Interval)); // Y-Achsen-Abschnitt berechnen
while ((Interval/TeilerY) < 4) do teilerY := TeilerY div 2; // ist durch Ausprobieren entstanden
Interval := (log2(IMax)) - (log2(Max(IMin,1))); // Interval berechnen, für absolute Darstellung die log2-Funktion weglassen
ARY := (H/Interval); // AspektRatio berechnen, H = DiagrammHöhe

n := IMin; // Zeichnen
while ((n mod teilerY) <> 0) do inc(n); // durch Ausprobieren entstanden
while (n <= IMax) do
begin
if ((n mod TeilerY) = 0) then Ky := GetRelativKoordinate(n);
R := n;
if (Frac(R/ChF) <> 0)
then S := FloatToStrF(R/ChF,ffFixed,6,2)
else S := FloatToStrF(R/ChF,ffFixed,6,0);
CPC.Pen.Style := PsSolid;
CPC.Font.Color := ClBlack;
CPC.Brush.Style := BsClear;
CPC.TextOut(xL-10-CPC.Textwidth(S),round(ky-CPC.TextHeight(S) div 2),S);
CPC.TextOut(xR+10,round(ky-CPC.TextHeight(S) div 2),S);
CPC.Pen.Style := PsDot;
CPC.Pen.Color := ClGray;
CPC.Pen.Width := 1;
CPC.MoveTo(CxL-20,Round(Max(Ky,CyO))); CPC.LineTo(CxR+20,round(Max(Ky,CyO)));
Inc(n,TeilerY);
end;
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#2

AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen

  Alt 13. Mai 2017, 18:55
Ich habe vor Jahren auch mal sowas programmiert. Weiß aber auch nicht mehr, was ich damals genau gemacht habe. In dem Code steckt offenbar einiges "Engineering" drin

Die Grundidee ist, dass man mit der Konstanten GRID_APROX_PIXEL_DIST den Abstand (in Pixeln) festlegt, den aufeinanderfolgende Achsenabschnitte "ungefähr" haben sollten. Der Code wählt dann automatisch passende "schöne" Schrittweiten für die Achsenbeschriftungen wie z.B. (10, 20, 30, 40, ...) oder (20, 40, 60, 80, ...) oder (50, 100, 150, 200, ...) etc.

Weiß nicht, ob jemand mit dem Code etwas anfangen kann, aber macht damit was ihr wollt.

Edit: Habe noch einen Screenshot angehängt, wie das beispielsweise aussieht. Die Einteilung ändert sich dynamisch, wenn man die Fenstergröße verwändert.
Angehängte Grafiken
Dateityp: png chart beispiel.png (65,3 KB, 27x aufgerufen)
Dateityp: jpg chart beispiel 2.jpg (57,7 KB, 20x aufgerufen)
Angehängte Dateien
Dateityp: pas unChart.pas (3,9 KB, 10x aufgerufen)

Geändert von Namenloser (13. Mai 2017 um 19:14 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.561 Beiträge
 
Delphi 12 Athens
 
#3

AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen

  Alt 13. Mai 2017, 23:11
Vielen Dank erst mal für die Rückmeldungen.

Um die Frage noch einmal etwas zu verdeutlichen ein Demo-Projekt (VCL) im Anhang. Siehe auch screenshot. Wenn man die einzelnen Schalter Random... drückt, wird eine Chart mit den jeweiligen x-Werten erzeugt und links auf der Y-Achse die passenden Werte angezeigt.

Das sind mal Schritte im Abstand von 50, mal 100, mal 1000, mal 100.000 usw.

Ich bräuchte letztlich nur eine Funktion, welche (vergleichbar dem TChart) z.B. 10 sinnvolle Werte für die Y-Achse berechnet (wie und wo die gemalt werden, ist Nebensache, es geht mir nur im die sinnvollen Zahlen).

Dabei ist schon klar, dass man, nachdem man die Zahlen erzeugt hat, den Maximalbetrag ermitteln muss (mit der MAX-Funktion). Dann reicht es aber nicht, diese Maximalzahl durch 10 zu teilen, da man da ja krumme werte bekommt. Hier geht es letztlich darum, die einzelnen Werte sinnvoll zu runden oder sonstwie zu ermitteln.
Angehängte Grafiken
Dateityp: jpg shot.jpg (74,3 KB, 31x aufgerufen)
Angehängte Dateien
Dateityp: zip YAxis.zip (52,7 KB, 3x aufgerufen)

Geändert von Harry Stahl (13. Mai 2017 um 23:15 Uhr)
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#4

AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen

  Alt 14. Mai 2017, 07:49
Ich formuliere die Anforderung mal um. Der Maximalwert der Y-Achse soll abhängig vom Wertebereich der Y-Werte eine "schöne" Zahl sein. Ich vermute für Dich ist eine "schöne" Zahl: 1,2,3,5 bzw. 10,20,30,50 usw. Die Teilung der Y-Achse ergibt sich direkt aus dem Maximalwert.
1: 0,1/0,2/0,3/0,4/0,5/0,6/0,7/0,8/0,9/1,0
2: 0,2/../1,8/2,0
3: 1/2/3
5: 1/2/3/4/5
Oder so ähnlich. Das bleibt Dir überlassen.
Falls ich Dich da dann also richtig verstanden habe, geht es also lediglich darum den Maximalwert der Y-Werte in eine der vier Kategorien einzuordnen. Dazu würde ich Max(Y) zunächst normieren, also auf das Intervall [0..10[ herunter rechnen.

Delphi-Quellcode:
var
  NPotenz: Integer;
  YDiv: Double;
  YResult: Double;
begin
  NPotenz := trunc(Log10(YMax));
  YDiv:= IntPower(10, NPotenz);
  YNorm := trunc(YMax / YDiv);
end;
Jetzt mache ich die Fallunterscheidung für die "schöne" Zahl:
Delphi-Quellcode:
    if YNorm<=3
    then
      YResult := YNorm
    else
    if YNorm<=5
    then
      YResult := 5
    else
      YResult := 10;
Und nun muss ich lediglich die korrekte Potenz wieder herstellen

  YResult := YResult * YDiv; Vielleicht gibt es jetzt noch irgendwelche Rundungsprobleme usw. Aber das soll hier ja auch nur einen möglichen Lösungsweg skizzieren und keine fertige Lösung sein.
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.561 Beiträge
 
Delphi 12 Athens
 
#5

AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen

  Alt 14. Mai 2017, 18:38
Die von Samso vorgeschlagene Lösung sieht schon sehr gut aus. Habe das mal in den Source gepackt, der sieht nun so aus:
Delphi-Quellcode:
procedure TForm82.Button1Click(Sender: TObject);
var
  L: Integer;
  Val, MaxVal: Extended;

  NPotenz: Integer;
  YDiv, YNorm: Double;
  YResult: Double;

begin
  with chart1 do begin
    series1.clear;
    title.Text.Text := 'Monatliche Umsätze im Jahr 2017';

    Maxval := 0;

    sgUmsatz.cells[0, 0] := 'Monat';
    sgUmsatz.cells[1,0] := 'Betrag';
    sgUmsatz.cells[2,0] := 'Wert Y-Achse';

    for L := 1 to 12 do begin
      sgUmsatz.cells[0, L] := FormatDateTime ('mmm', StrToDate ('01.01.2017') + ((L-1) * 33));
      Val := Random (TButton(sender).tag);
      MaxVal := max (MaxVal, val);
      sgUmsatz.cells[1, L] := Val.ToString;
      series1.Add (StrToFloat (sgUmsatz.cells[1, L]), sgUmsatz.cells[0,L], clGreen);
    end;
  end;

  NPotenz := trunc(Log10(MaxVal));
  YDiv:= IntPower(10, NPotenz);
  YNorm := trunc(MaxVal / YDiv);

  if YNorm<=3
    then
      YResult := YNorm
    else
    if YNorm<=5
    then
      YResult := 5
    else
      YResult := 10;

  // Soll hier nun die selbst errechneten Werte für die Y-Achse ausgeben
  for L := 1 to 10 do begin
    sgUmsatz.cells[2,L] := (L * YDiv).tostring;
  end;

  // Nicht benötigt, oder?
  YResult := YResult * YDiv;
end;
Eigentlich brauche ich doch nur den YDiv-Wert, oder?

Siehe neuer Screenshot und angepasstes Demo im Anhang.
Angehängte Grafiken
Dateityp: jpg Bild-BCF6E9F7-2CF.jpg (125,6 KB, 21x aufgerufen)
Angehängte Dateien
Dateityp: zip YAxis.zip (56,5 KB, 8x aufgerufen)
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#6

AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen

  Alt 15. Mai 2017, 06:51
Da liegt ein Missverständnis vor. YDiv hat nichts mit der Einteilung der Y-Achse zu tun. Eventuell komme ich heute Abend dazu, mir Dein Demoprogramm mal vorzunehmen.
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#7

AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen

  Alt 15. Mai 2017, 07:26
Ist Dein Ziel eine Nachbildung von TChart? Der Maximalwert der Y-Achse ist dort daran orientiert, dass oberhalb der Säule mit dem maximalen Umsatz noch genug Platz sein muss um das zugehörige Monats-Label anzubringen. Da muss dann natürlich die Schriftgröße des Labels, die Größe der Zeichenfläche usw. in der Berechnung berücksichtigt werden.
  Mit Zitat antworten Zitat
Antwort Antwort

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:26 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