Grid-Tick-Größe geschlossen bestimmen
-
Okay, also ich glaube, das gehört nicht wirklich in dieses Forum, aber immerhin ist der Quelltext in meiner Interpretation von C++ geschrieben...
Folgendes Problem:
Für die graphische Darstellung möchte ich eine Grid-Unterteilung bestimmen. Gegeben habe ich ein "Basisgrid", meinetwegen 3. Nun möchte ich dieses Basisgrid so vergrößern/verkleinern, dass zwischen 4 und 8 Gridlinien in dem dargestellten Intervall landen. Ich habe erst geschaut, nachgedacht, mich aufgeregt und anschließend folgende Funktion geschrieben:double CalcTickSize( types::IntervalD d, double baseTick ) { const double coefficients[] = { 2, 2, 2.5 }; for( int i=0; d.width() / baseTick < 4; ++i ) { baseTick /= coefficients[i%3]; } for( int i=0; d.width() / baseTick > 8; ++i ) { baseTick *= coefficients[i%3]; } return baseTick; }Jetzt ist da auch die 2.5 als Faktor, die Idee war, dass 2*2*2.5 eben 10 sind und man dann bei der nächsten Größenordnung landet.
Das funktioniert eigentlich auch ganz gut, aber bei mir bleibt der fade Beigeschmack der Dummheit, dass ich keine "geschlossene" Lösung dafür finde. Seht ihr da eine Lösung?Viele Grüße,
Deci
-
baseTick = Intervall / gewünschte Strichzahl?
-
Heyho!
Also was die Funktion zurückgeben soll, sollte eigentlich ein Vielfaches von dem hereingegebenen baseTick sein, weil ich nicht einfach irgendwelche krummen Grids haben möchte am Ende, sondern nur ein entsprechend skaliertes Grid (die Beispiels-3 würde für Grids wie 0.3, 0.6, 1.2, 3 usw. sorgen). Ich weiß nicht ob die Koeffizientenreihenfolge so wirklich gut ist, aber wenn sich das Intervall dynamisch verändert sieht es auf meinem Bildschirm so eigentlich recht aktzeptabel aus.
-
Leg doch einfach mal alle Fakten auf den Tisch. Bei dir selber hast du schließlich auch einen krummen Faktor 2.5 drin. Daher unter Vorbehalt:
double new_tick = interval_width / lower_bound_tick_count_per_interval; if (new_tick > base_tick) { unsigned ratio = new_tick / base_tick - 1; new_tick = base_tick * ratio; } else { unsigned ratio = base_tick / new_tick + 1; new_tick = base_tick / ratio; } return new_tick;Es geht natürlich nicht immer auf, weil das Problem manchmal eben einfach nicht erfüllbar ist. So hast du aber eine möglichst gute Annäherung an die untere gewünschte Tickzahl. Wenn du lieber näher an die obere Grenze möchtest, dreh die +1 und -1 um und setz oben die Obergrenze ein.
-
Hrmmm, ja, das hat was.
Also warum ich diese Faktoren da hatte, die gehörten auch zu meinem mörderischen Plan: So bekam ich über alle Größenordnungen immer "die drei selben Zahlen", (3,6,12,30,60,120,300,600,1200,...). Ich schaue mir in einer ruhigen Minute mal die Ungleichungen an, die ich da ja im Prinzip habe... Ich habe das Problem nie wirklich formal runtergeschrieben, stelle ich fest.
Tut mir Leid, dass da wichtige Subtext-Information im OP fehlte
-
Dann sag doch gleich, dass du nur Faktoren 1 und 2 mit jeweils 10^X möchtest.
-
Also es ist ja nicht ausschließlich 10^x, es ist die Kombination "kleinster" einigermaßen "harmonischer" Faktoren, auf dem Weg zur "nächsten 10", welche mir eingefallen ist. Vielleicht gibt es ja noch eine viel bessere Herangehensweise.
Dass ich das nicht gleich im OP so gesagt habe, war blöde!
-
Dann definier mal genau, was du möchtest.
Jedoch: Wenn du einfach nur das Ergebnis wie im OP haben möchtest, dann nimm doch einfach den Algorithmus, den du da benutzt hast. Man könnte ich zwar vielleicht bei sehr großen Sprüngen etwas abkürzen (zum Beispiel erst einmal in die richtige Größenordnung springen und dann nachjustieren), aber im Großen und Ganzen ist der für die meisten Szenarien ganz ok. Schlimmstenfalls machst du logarithmisch viele unnötige Durchläufe, was in der Regel so in der Größenordnung 0 bis 2 liegen dürfte.