Hallo Alexander,
ich möchte vorausschicken, dass ich mich noch nie richtig mit Farblehre auseinandergesetzt habe, Deinen Ansatz als einen "logischen" Ansatz ansehe, dessen Praxistauglichkeit man zuerst ermitteln muss. Ich fürchte, der Ansatz ist zu einfach.
Ich habe jetzt den Code kommentiert
Dazu an geeigneter Stelle mehr.
und den Variablen aussagekräftigere Namen gegeben.
Ich fände 'value' besser als 'number', noch besser gar kein Postfix.
Es folgt die Aufgabe der Funktion, diese schreibt man gern in einen Kommentar.
„sich möglichst gut voneinander abheben“ heißt, dass ich Punkte auf eine weise Fläche malen möchte und Normalsterbliche diese Punkte einigermaßen auseinander halten bzw. einer Liste mit Farben zuordnen können sollen.
function get_colors($number) {
Kommentare zu Abschnitten einer Funktion schreibt man üblicherweise über den Abschnitt, nicht darunter.
/*
Dieser Teil der Funktion ermittelt für jeden Farbkanal einzeln, in wie viele Teile die 255 Werte
des jeweiligen Farbkanals mindestens zerlegt werden müssen, damit die Funktion die geforderte Anzahl
Farben durch Permutationen erzeugen kann.
*/
Hier machst Du etwas falsch, Deine Werte fallen zu groß aus. Wenn Du Dir die von Dir erzeugten Farben ansiehst, so muss Dir doch auffallen, dass die Farben vorwiegend im blaugrünen Bereich angesiedelt sind, dass Rot unterrepäsentiert ist. Schaust Du Dir die Werte an, so muss Dir auffallen, dass
a) Ein "\n" hinter jedem DIV-Element angebracht wäre :-)
b) der Rot-Anteil nicht ausgeschöpft wird.
Nun zu Deinem Fehler. Du zerlegst jeden Farbteil in n(farbe) Intervalle, darauf ist Dein n ausgelegt. Tatsächlich durchläufst Du nicht Intervalle, sondern Intervallgrenzen - und dies sind eben n(farbe)+1.
$root = pow($number, 1/3);
Diese Fallunterscheidung wäre meiner Meinung nach kommentierungswürdig.
Warum machst Du das? Das ist nicht auf Anhieb ersichtlich. D.h. erläutere Deine Berechnungsgrundlage.
if (ceil($root)*pow(floor($root), 2) >= $number) {
$red_number = ceil($root);
$green_number = $blue_number = floor($root);
}
elseif (pow(ceil($root), 2)*floor($root) >= $number) {
$red_number = $green_number = ceil($root);
$blue_number = floor($root);
}
else
$red_number = $green_number = $blue_number = ceil($root);
Nächster Abschnitt: Ort des Kommentars, siehe oben.
/*
Dieser Teil berechnet die Permutationen und bricht ab, wenn genügend erzeugt wurden.
*/
$counter = 0;
$result = array();
for ($red_counter = 0; $red_counter <= $red_number; $red_counter++) {
Hier kannst Du es sehen. Du lässt die Variable von 0 bis zum ermittelten Wert laufen (inklusive). Bei den folgenden Schleifen natürlich auch.
for ($green_counter = 0; $green_counter <= $green_number; $green_counter++) {
for ($blue_counter = 0; $blue_counter <= $blue_number; $blue_counter++) {
if ($counter >= $number)
return $res;
$res[] = array('r' => $red_counterfloor(255/$red_number), 'g' => $green_counterfloor(255/$green_number), 'b' => $blue_counter*floor(255/$blue_number));
$counter++;
}
}
}
}
Als weitere Idee, damit Du von den dunkellastigen Farben wegkommst: Fange bei 255 als Farbwert je Kanal an und ziehe ab, statt bei 0 anzufangen und zu addieren. Dass Du den ersten Wert 255, 255, 255 weglassen musst, sehe ich als selbstverständlich an.
Danach (bereits mit meinem ersten Vorschlag) solltest Du die gleichmäßige Verteilung der Farbkanalwerte erreichen. Ob dies in der Praxis gute Farben ergibt, wirst Du dann sehen. Verbreitete Programme zeigen, dass dies offensichtlich nicht trivial ist.
Zur Farblehre könntest Du Dich an Andreas Lindig wenden, für seinen Farbfinder hat er nach meinem Wissen intensiv recherchiert.
Freundliche Grüße
Vinzenz