![]() |
Orientierungspunkte für die Y-Achse eines Diagramms berechnen
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? |
AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen
Liste der Anhänge anzeigen (Anzahl: 1)
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 |
AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen
Zitat:
Eine vernünftige Einteilung der Y-Achse bei gegebenen X-Werten vorzunehmen (also einen sinnvollen Bereich an die Linke Seite zu schreiben). |
AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen
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.
|
AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen
Zitat:
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 |
AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen
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. |
AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen
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; |
AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen
Liste der Anhänge anzeigen (Anzahl: 3)
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. |
AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen
Liste der Anhänge anzeigen (Anzahl: 2)
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. |
AW: Orientierungspunkte für die Y-Achse eines Diagramms berechnen
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:
Jetzt mache ich die Fallunterscheidung für die "schöne" Zahl:
var
NPotenz: Integer; YDiv: Double; YResult: Double; begin NPotenz := trunc(Log10(YMax)); YDiv:= IntPower(10, NPotenz); YNorm := trunc(YMax / YDiv); end;
Delphi-Quellcode:
Und nun muss ich lediglich die korrekte Potenz wieder herstellen
if YNorm<=3
then YResult := YNorm else if YNorm<=5 then YResult := 5 else YResult := 10;
Delphi-Quellcode:
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.
YResult := YResult * YDiv;
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:20 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