Aussenplan an die Farbgebung der Geschoss-Renderings angleichen
Aus OG.png gemessen, nicht geschaetzt: die hellste Stufe ist genau neutral und liegt bei 200 - heller wird dort nichts -, und je dunkler eine Flaeche wird, desto blauer wird sie. Beides steckt jetzt in aussenSchatten(), das bisher farbtreu gegen Schwarz gerechnet hat. Damit allein fehlte dem Plan aber immer noch das obere Drittel der Helligkeitsskala, das die Renderings haben. Grund war, dass jede Aussenwand denselben Faktor bekam, egal wohin sie zeigte - der Plan hatte gar kein gerichtetes Licht. aussenBeleuchtung() liefert es jetzt aus einer Sonne im Westsuedwesten und ersetzt nebenbei die grobe Zweistufung am Dach. Waagerechte Flaechen bleiben knapp unter der besonnten Wand. Mit vollem Licht waren Boden und Terrassen das Hellste im Bild; im Vorbild sind es die Waende. Die Deckflaeche lief bisher an aussenSchatten() vorbei, sonst haette der Deckel die flachen Flaechen nie erreicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+118
-15
@@ -73,6 +73,49 @@ const PLAN_STAUCHUNG = 0.55;
|
||||
*/
|
||||
const PLAN_UEBERHOEHUNG = 1.4;
|
||||
|
||||
/**
|
||||
* Hellster Wert, den eine Flaeche annehmen darf.
|
||||
*
|
||||
* Aus den Renderings der Innengeschosse gemessen: dort geht kein einziger
|
||||
* Bildpunkt ueber 200. Reines Weiss kommt nicht vor, und genau das laesst die
|
||||
* Bilder ruhig wirken. Ohne diesen Deckel steht der Aussenplan grell neben
|
||||
* ihnen.
|
||||
*/
|
||||
const PLAN_LICHT = 200;
|
||||
|
||||
/**
|
||||
* Wohin abgedunkelt wird - nicht nach Schwarz, sondern ins Blaugraue.
|
||||
*
|
||||
* Ebenfalls gemessen: im Vorbild ist die hellste Stufe genau neutral, und mit
|
||||
* abnehmender Helligkeit waechst der Blauanteil auf rund 30 Stufen an. Das ist
|
||||
* kein Stilmittel, sondern Physik - eine Flaeche, die keine Sonne abbekommt,
|
||||
* bekommt ihr Licht vom Himmel, und der ist blau.
|
||||
*/
|
||||
const PLAN_SCHATTEN = [40, 62, 98];
|
||||
|
||||
/**
|
||||
* Woher das Licht kommt, als Richtung in der Grundflaeche - x nach Osten,
|
||||
* y nach Sueden. Westsuedwest, also Nachmittagssonne.
|
||||
*
|
||||
* Nicht genau aus Suedwesten, obwohl von dort geschaut wird: Dann laegen die
|
||||
* beiden sichtbaren Seiten gleich hell, und die Kante zwischen ihnen waere
|
||||
* verschwunden. Etwas nach Westen versetzt trennt sie sich.
|
||||
*/
|
||||
const PLAN_LICHTRICHTUNG = [-0.85, 0.53];
|
||||
|
||||
/** Wieviel Licht eine Flaeche bekommt, die von der Sonne abgewandt ist. */
|
||||
const PLAN_UMGEBUNG = 0.58;
|
||||
|
||||
/**
|
||||
* Licht auf einer waagerechten Flaeche - Boden, Terrasse, Wandoberkante.
|
||||
*
|
||||
* Etwas weniger als eine gut zur Sonne stehende Wand. Bei rund 40 Grad
|
||||
* Sonnenhoehe bekommen beide fast dasselbe ab, und die Wand einen Hauch mehr.
|
||||
* Mit vollem Licht waren Boden und Terrassen das Hellste im Bild und zogen den
|
||||
* Blick auf sich; im Vorbild sind es die Waende.
|
||||
*/
|
||||
const PLAN_WAAGERECHT = 0.88;
|
||||
|
||||
/** So groß ist die Zeichenfläche, in die alles hineinpassen muss. */
|
||||
const PLAN_BREITE = 400;
|
||||
const PLAN_HOEHE = 300;
|
||||
@@ -126,7 +169,7 @@ function aussenFlaechen()
|
||||
// Die Anlage liegt auf der Suedschraege. Die Wiederkehr wird danach
|
||||
// gezeichnet und deckt die Mitte ab - genau wie auf dem Luftbild, wo
|
||||
// die Module links und rechts von ihr liegen.
|
||||
["raum" => null, "z" => 0, "hoehe" => 6, "farbe" => "#d5d9df",
|
||||
["raum" => null, "z" => 0, "hoehe" => 6, "farbe" => "#c8c8c8",
|
||||
"dachfarbe" => "#9aa3ad", "dach" => ["art" => "sattel", "hoehe" => 3],
|
||||
"pv" => "S",
|
||||
"ecken" => [[36.8, 17.2], [39.2, 31.2], [24.2, 33.8], [21.8, 19.8]]],
|
||||
@@ -140,7 +183,7 @@ function aussenFlaechen()
|
||||
//
|
||||
// Breite und Tiefe sind vom Luftbild geschaetzt - wenn es genauer sein
|
||||
// soll, klick die Flaeche in tools/lageplan.php ab.
|
||||
["raum" => null, "z" => 6, "hoehe" => 0, "farbe" => "#d5d9df",
|
||||
["raum" => null, "z" => 6, "hoehe" => 0, "farbe" => "#c8c8c8",
|
||||
"dachfarbe" => "#9aa3ad",
|
||||
"dach" => ["art" => "sattel", "hoehe" => 1.3, "achse" => "NS"],
|
||||
"ecken" => [[34.7, 32.0], [28.7, 33.0], [27.5, 25.6], [33.4, 24.6]]],
|
||||
@@ -169,7 +212,7 @@ function aussenFlaechen()
|
||||
// an der westlichen setzt der OG-Carport an. Ausgeschrieben, weil bei
|
||||
// einem fast quadratischen Grundriss sonst die zweite Nachkommastelle
|
||||
// entscheidet, welche Seite die laengere ist.
|
||||
["raum" => "Garage", "z" => 0, "hoehe" => 2.5, "farbe" => "#c9ced5",
|
||||
["raum" => "Garage", "z" => 0, "hoehe" => 2.5, "farbe" => "#c8c8c8",
|
||||
"dachfarbe" => "#7d9470", "tor" => "S",
|
||||
"dach" => ["art" => "sattel", "hoehe" => 1.5, "achse" => "NS"],
|
||||
"ecken" => [[12.2, 19.2], [13.3, 25.4], [19.6, 24.3], [18.5, 18.0]]],
|
||||
@@ -298,14 +341,54 @@ function aussenMitte($punkte)
|
||||
return [$sx / $n, $sy / $n];
|
||||
}
|
||||
|
||||
/** Eine Farbe abdunkeln - die Seitenflächen liegen im Schatten. */
|
||||
/**
|
||||
* Eine Farbe ins Licht setzen - Faktor 1 volle Beleuchtung, kleiner ist
|
||||
* Schatten.
|
||||
*
|
||||
* Zwei Dinge unterscheiden das vom blossen Abdunkeln, und beide sind aus den
|
||||
* Renderings der Innengeschosse abgelesen:
|
||||
*
|
||||
* - Der Deckel. Keine Flaeche wird heller als PLAN_LICHT, auch wenn die
|
||||
* Grundfarbe es waere. Der Farbton bleibt dabei erhalten, weil alle drei
|
||||
* Kanaele mit demselben Wert heruntergezogen werden.
|
||||
* - Die Richtung. Abgedunkelt wird nicht nach Schwarz, sondern nach
|
||||
* PLAN_SCHATTEN. Deshalb wird eine Flaeche blauer, je weniger Licht sie
|
||||
* bekommt - der farbtreue Weg dorthin sah daneben stumpf aus.
|
||||
*/
|
||||
function aussenSchatten($hex, $faktor)
|
||||
{
|
||||
$n = hexdec(ltrim($hex, "#"));
|
||||
$kanal = [($n >> 16) & 255, ($n >> 8) & 255, $n & 255];
|
||||
|
||||
$spitze = max($kanal);
|
||||
if ($spitze > PLAN_LICHT) {
|
||||
foreach ($kanal as $i => $wert) {
|
||||
$kanal[$i] = $wert * PLAN_LICHT / $spitze;
|
||||
}
|
||||
}
|
||||
|
||||
$f = max(0.0, min(1.0, $faktor));
|
||||
return sprintf("#%02x%02x%02x",
|
||||
(int) round(($n >> 16) * $faktor),
|
||||
(int) round((($n >> 8) & 255) * $faktor),
|
||||
(int) round(($n & 255) * $faktor));
|
||||
(int) round($kanal[0] * $f + PLAN_SCHATTEN[0] * (1 - $f)),
|
||||
(int) round($kanal[1] * $f + PLAN_SCHATTEN[1] * (1 - $f)),
|
||||
(int) round($kanal[2] * $f + PLAN_SCHATTEN[2] * (1 - $f)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wie hell eine senkrechte Flaeche mit dieser Aussennormalen liegt.
|
||||
*
|
||||
* Bisher bekam jede Aussenwand denselben Wert, egal wohin sie zeigte. Der Plan
|
||||
* sah dadurch flach aus, und nachgemessen fehlte ihm genau das obere Drittel
|
||||
* der Helligkeitsskala, das die Renderings haben. Eine Lichtrichtung fuellt es.
|
||||
*/
|
||||
function aussenBeleuchtung($nx, $ny)
|
||||
{
|
||||
$laenge = hypot($nx, $ny);
|
||||
if ($laenge <= 0) {
|
||||
return 1.0; // waagerecht, volle Beleuchtung von oben
|
||||
}
|
||||
$anteil = ($nx * PLAN_LICHTRICHTUNG[0] + $ny * PLAN_LICHTRICHTUNG[1]) / $laenge;
|
||||
return PLAN_UMGEBUNG + (1 - PLAN_UMGEBUNG) * max(0.0, $anteil);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -542,7 +625,8 @@ function aussenZeichnung()
|
||||
};
|
||||
// Aussenseite
|
||||
$seiten[] = [$viereck($von, $z, $bis, $z, $bis, $zBis, $von, $zVon),
|
||||
0.72, "Wand " . $k["richtung"] . " aussen"];
|
||||
aussenBeleuchtung($k["nx"], $k["ny"]),
|
||||
"Wand " . $k["richtung"] . " aussen"];
|
||||
if ($dicke > 0) {
|
||||
// Innenseite - umgekehrter Umlauf, damit sie zaehlt, wenn
|
||||
// man durch die Oeffnung hineinsieht.
|
||||
@@ -552,12 +636,21 @@ function aussenZeichnung()
|
||||
// Oberkante
|
||||
$seiten[] = [$viereck($von, $zVon, $bis, $zBis,
|
||||
$innenBis, $zBis, $innenVon, $zVon),
|
||||
0.86, "Wand " . $k["richtung"] . " Oberkante"];
|
||||
PLAN_WAAGERECHT,
|
||||
"Wand " . $k["richtung"] . " Oberkante"];
|
||||
// Die beiden Schnittkanten an den Enden der Wand
|
||||
// Eine Schnittkante steht quer zur Wand und bekommt deshalb
|
||||
// ihr eigenes Licht. Mit einem festen Wert sprangen die
|
||||
// Ecken je nach Wandhelligkeit als Pfosten hervor.
|
||||
$laengsL = hypot($bis[0] - $von[0], $bis[1] - $von[1]);
|
||||
$lx = $laengsL > 0 ? ($bis[0] - $von[0]) / $laengsL : 0;
|
||||
$ly = $laengsL > 0 ? ($bis[1] - $von[1]) / $laengsL : 0;
|
||||
$seiten[] = [$viereck($innenVon, $z, $von, $z, $von, $zVon, $innenVon, $zVon),
|
||||
0.66, "Wand " . $k["richtung"] . " Schnitt A"];
|
||||
aussenBeleuchtung(-$lx, -$ly),
|
||||
"Wand " . $k["richtung"] . " Schnitt A"];
|
||||
$seiten[] = [$viereck($bis, $z, $innenBis, $z, $innenBis, $zBis, $bis, $zBis),
|
||||
0.66, "Wand " . $k["richtung"] . " Schnitt B"];
|
||||
aussenBeleuchtung($lx, $ly),
|
||||
"Wand " . $k["richtung"] . " Schnitt B"];
|
||||
}
|
||||
$etwasSichtbar = false;
|
||||
foreach ($seiten as $seite) {
|
||||
@@ -655,7 +748,9 @@ function aussenZeichnung()
|
||||
$first[$r],
|
||||
];
|
||||
if (aussenSichtbar($giebel)) {
|
||||
$polygone[] = ["punkte" => $giebel, "farbe" => aussenSchatten($farbe, 0.86)];
|
||||
$polygone[] = ["punkte" => $giebel,
|
||||
"farbe" => aussenSchatten($farbe,
|
||||
aussenBeleuchtung($k["nx"], $k["ny"]))];
|
||||
}
|
||||
}
|
||||
foreach ($seiten as $r) {
|
||||
@@ -683,7 +778,7 @@ function aussenZeichnung()
|
||||
if (aussenSichtbar($schraege)) {
|
||||
$polygone[] = ["punkte" => $schraege,
|
||||
"farbe" => aussenSchatten($f["dachfarbe"] ?? "#9aa3ad",
|
||||
$r === "S" || $r === "W" ? 1.0 : 0.82)];
|
||||
aussenBeleuchtung($k["nx"], $k["ny"]))];
|
||||
// Module auf genau dieser Schraege. Eingezogen wird hier
|
||||
// im Bild und nicht in Metern: die Flaeche ist schon
|
||||
// projiziert, und auf ihrer Ebene bleibt der Einzug auch
|
||||
@@ -721,12 +816,20 @@ function aussenZeichnung()
|
||||
aussenPunkt($einpassung, $pkt[0], $pkt[1], $zOben[$i]),
|
||||
];
|
||||
if (aussenSichtbar($stirn)) {
|
||||
// Die Stirn laeuft um den ganzen Koerper und zeigt
|
||||
// dabei in alle Richtungen - ein fester Wert liesse
|
||||
// die abgewandte Seite so hell wie die besonnte.
|
||||
$sdx = $dachEcken[$j][0] - $pkt[0];
|
||||
$sdy = $dachEcken[$j][1] - $pkt[1];
|
||||
$polygone[] = ["punkte" => $stirn,
|
||||
"farbe" => aussenSchatten($f["dachfarbe"] ?? $farbe, 0.78)];
|
||||
"farbe" => aussenSchatten($f["dachfarbe"] ?? $farbe,
|
||||
aussenBeleuchtung($sdy, -$sdx))];
|
||||
}
|
||||
}
|
||||
}
|
||||
$polygone[] = ["punkte" => $deckPunkte, "farbe" => $f["dachfarbe"] ?? $farbe];
|
||||
$polygone[] = ["punkte" => $deckPunkte,
|
||||
"farbe" => aussenSchatten($f["dachfarbe"] ?? $farbe,
|
||||
PLAN_WAAGERECHT)];
|
||||
$deck = $dachEcken;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user