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
Seite 1 von 2  1 2   
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.197 Beiträge
 
Delphi 10.4 Sydney
 
#1

Orientierungspunkte für die Y-Achse eines Diagramms berechnen

  Alt 12. Mai 2017, 16:30
Irgendwie hab ich da keine Idee:

Wie kann man, bei gegebenen Werten für die X-Achse (z.B. 12.200, 25.180, 63.738, 130.000) 10 vernünftige Einträge für die Y-Achse eines Diagramms berechnen?

Es sind natürlich alle potentiellen Zahlenbereiche abzudecken (also 1-100, 1-1000, 1-10.000, 1-100.000, usw).

Die Y-Werte auf der Achse sollten natürlich gerade Zahlen und keine krummen Werte sein.

Jemand das schon mal gemacht oder eine Idee?
  Mit Zitat antworten Zitat
Sigi Sandl

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

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

  Alt 12. Mai 2017, 21:14
Hallo, Harry Stahl,

ich werde leider nicht ganz schlau aus Deiner Beschreibung.
Um Y-Werte zu gegebenen X-Werten zu berechnen, brauche ich eine mathematische Funktion der Form Y = Irgendwas * X.

Wenn's Dir aber um die Berechnung der Y-Achsen-Einteilung geht, sowas hab' ich, wie im Anhang dargestellt, schonmal gebastelt.
Die Y-Achse ist hier logarithmisch eingeteilt, so kann ich große und kleine Werte gleichzeitig vernünftig darstellen.

Und, ich bin SpaßProgrammierer, unterstützen kann ich nur theoretisch, professionellen Quellcode kann ich nicht liefern.

Grüße
Sigi Sandl
Miniaturansicht angehängter Grafiken
bild.jpg  
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.197 Beiträge
 
Delphi 10.4 Sydney
 
#3

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

  Alt 13. Mai 2017, 01:03
Hallo, Harry Stahl,

Wenn's Dir aber um die Berechnung der Y-Achsen-Einteilung geht, sowas hab' ich, wie im Anhang dargestellt, schonmal gebastelt.
Die Y-Achse ist hier logarithmisch eingeteilt, so kann ich große und kleine Werte gleichzeitig vernünftig darstellen.

Sigi Sandl
Ja, genau darum geht es.
Eine vernünftige Einteilung der Y-Achse bei gegebenen X-Werten vorzunehmen (also einen sinnvollen Bereich an die Linke Seite zu schreiben).
  Mit Zitat antworten Zitat
samso

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

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

  Alt 13. Mai 2017, 08:05
Die Einteilung der Y-Achse hat mit der X-Achse doch überhaupt nichts zu tun? An Deiner Stelle würde ich Excel starten und mir da ansehen, wie Microsoft das Problem gelöst hat. Zusätzlich kommt es auch noch darauf an, welchen Eindruck der Betrachter haben soll. Die Y-Achse wird unterschiedlich eingeteilt je nachdem, welchen Eindruck der Betrachter haben soll (Beispiel: Die Y-Achse beginnt bei 100000 und endet bei 100010. Da wirkt eine Änderung von 0,01% ganz anders, als wenn ich die Y-Achse bei 0 starten lasse und bei 200000 enden lasse - natürlich alles mit den gleichen Y-Werten). Bei der Einteilung der Y-Achse gibt es keine pauschale Regel, sondern es kommt darauf an, was man darstellen will.
  Mit Zitat antworten Zitat
Poelser

Registriert seit: 21. Apr 2008
Ort: Europa
123 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#5

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

  Alt 13. Mai 2017, 09:28
Die Einteilung der Y-Achse hat mit der X-Achse doch überhaupt nichts zu tun?
Doch! Aus den Y-Werten, die im dargestellten Bereich der X-Achse zu finden sind, sollte die Skalierung der Y-Achse berechnet werden.
Vielleicht grob so: Min() und Max() dieses Bereiches holen, für diese Werte sinvoll abrunden bzw. aufrunden. Aus der Differenz zwischen den beiden Werten könnte man mit Division durch die Anzahl der gewünschten Schritte zu einer Schrittweite gelangen, die dann für die Skalierung zu verwenden ist.

Bis denne, Poelser
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
608 Beiträge
 
Delphi 10.4 Sydney
 
#6

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

  Alt 13. Mai 2017, 11:55
Hallo Harry Stahl

es kommt immer drauf an, wie sich die y Werte in Abhängigkeit der x Werte verhalten und was du darstellen willst.

Wenn sich deine Daten zum Beispiel ziemlich linear verhalten, wenn also für alle Paare (x,y) ungefähr y = mx + b gilt, dann kannst du deine y Achse linear anschreiben; wenn deine Daten zwischen 0 und 400 liegen also zum Beispiel mit 0 50 100 150 200 250 300 350 400.

Es gibt aber auch viel Datenmaterial, welches sich eher wie y = c*e^(k*x) verhält [Beispiele: natürliches Wachstum, Zinseszins, Zerfallsprozesse]. Dann empfiehlt es sich oft, die y Achse logarithmisch zu skalieren. Grund dafür: Die y Werte wachsen enorm rasch an (Wachstum) oder werden enorm rasch kleiner (Zerfall).

Beispiel: Natürliches Wachstum. Werte liegen zwischen 0 und 1045 => y mit 0 10^1 10^2 10^3 anschreiben.
Michael Gasser
  Mit Zitat antworten Zitat
Sigi Sandl

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

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

  Alt 13. Mai 2017, 19: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
 
#8

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

  Alt 13. Mai 2017, 19: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.
Miniaturansicht angehängter Grafiken
chart-beispiel.png   chart-beispiel-2.jpg  
Angehängte Dateien
Dateityp: pas unChart.pas (3,9 KB, 10x aufgerufen)

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

Registriert seit: 2. Apr 2004
Ort: Bonn
2.197 Beiträge
 
Delphi 10.4 Sydney
 
#9

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

  Alt 14. Mai 2017, 00: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.
Miniaturansicht angehängter Grafiken
shot.jpg  
Angehängte Dateien
Dateityp: zip YAxis.zip (52,7 KB, 3x aufgerufen)

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

Registriert seit: 29. Mär 2009
430 Beiträge
 
#10

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

  Alt 14. Mai 2017, 08: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
Antwort Antwort
Seite 1 von 2  1 2   

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 10:36 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf