diff --git a/restricted/aussenplan.php b/restricted/aussenplan.php index bc8a243..74b5e4d 100644 --- a/restricted/aussenplan.php +++ b/restricted/aussenplan.php @@ -264,6 +264,27 @@ function aussenPunkt($einpassung, $x, $y, $z) $Y * $einpassung["massstab"] + $einpassung["dy"]]; } +/** + * Wie nah eine Flaeche am Betrachter liegt. Groesser heisst naeher. + * + * Bei dieser Projektion faellt genau eine Raumrichtung auf einen Bildpunkt + * zusammen; ihre Komponenten sind sin(Winkel), cos(Winkel) und + * Stauchung/Ueberhoehung. Ein Punkt darauf projiziert ist das Tiefenmass. + * + * Die projizierte Y-Koordinate taugt dafuer nicht: in ihr steckt auch die + * Hoehe, ein hoher Punkt saehe damit weiter hinten aus. + */ +function aussenTiefe($welt) +{ + $w = deg2rad(PLAN_WINKEL); + $summe = 0.0; + foreach ($welt as $p) { + $summe += $p[0] * sin($w) + $p[1] * cos($w) + + $p[2] * (PLAN_STAUCHUNG / PLAN_UEBERHOEHUNG); + } + return $summe / max(1, count($welt)); +} + /** Mittelwert einer Punktliste - gut genug als Ankerpunkt einer Fläche. */ function aussenMitte($punkte) { @@ -469,10 +490,12 @@ function aussenZeichnung() foreach ($ecken as $pkt) { $boden[] = aussenPunkt($einpassung, $pkt[0], $pkt[1], $z); } - $polygone[] = ["punkte" => $boden, "farbe" => aussenSchatten($farbe, 0.55)]; + $polygone[] = ["punkte" => $boden, "farbe" => aussenSchatten($farbe, 0.55), + "was" => "Boden"]; } // --- Waende ------------------------------------------------------ + $waende = []; if ($wand > 0) { foreach ($kanten as $k) { if (in_array($k["richtung"], $offen, true)) { @@ -513,50 +536,48 @@ function aussenZeichnung() $innenBis = [$bis[0] - $k["nx"] * $dicke, $bis[1] - $k["ny"] * $dicke]; $seiten = []; + $viereck = function ($a, $za, $b, $zb, $c, $zc, $d, $zd) { + return [[$a[0], $a[1], $za], [$b[0], $b[1], $zb], + [$c[0], $c[1], $zc], [$d[0], $d[1], $zd]]; + }; // Aussenseite - $seiten[] = [[ - aussenPunkt($einpassung, $von[0], $von[1], $z), - aussenPunkt($einpassung, $bis[0], $bis[1], $z), - aussenPunkt($einpassung, $bis[0], $bis[1], $zBis), - aussenPunkt($einpassung, $von[0], $von[1], $zVon), - ], 0.72]; + $seiten[] = [$viereck($von, $z, $bis, $z, $bis, $zBis, $von, $zVon), + 0.72, "Wand " . $k["richtung"] . " aussen"]; if ($dicke > 0) { // Innenseite - umgekehrter Umlauf, damit sie zaehlt, wenn // man durch die Oeffnung hineinsieht. - $seiten[] = [[ - aussenPunkt($einpassung, $innenBis[0], $innenBis[1], $z), - aussenPunkt($einpassung, $innenVon[0], $innenVon[1], $z), - aussenPunkt($einpassung, $innenVon[0], $innenVon[1], $zVon), - aussenPunkt($einpassung, $innenBis[0], $innenBis[1], $zBis), - ], 0.60]; + $seiten[] = [$viereck($innenBis, $z, $innenVon, $z, + $innenVon, $zVon, $innenBis, $zBis), + 0.60, "Wand " . $k["richtung"] . " innen"]; // Oberkante - $seiten[] = [[ - aussenPunkt($einpassung, $von[0], $von[1], $zVon), - aussenPunkt($einpassung, $bis[0], $bis[1], $zBis), - aussenPunkt($einpassung, $innenBis[0], $innenBis[1], $zBis), - aussenPunkt($einpassung, $innenVon[0], $innenVon[1], $zVon), - ], 0.86]; + $seiten[] = [$viereck($von, $zVon, $bis, $zBis, + $innenBis, $zBis, $innenVon, $zVon), + 0.86, "Wand " . $k["richtung"] . " Oberkante"]; // Die beiden Schnittkanten an den Enden der Wand - $seiten[] = [[ - aussenPunkt($einpassung, $innenVon[0], $innenVon[1], $z), - aussenPunkt($einpassung, $von[0], $von[1], $z), - aussenPunkt($einpassung, $von[0], $von[1], $zVon), - aussenPunkt($einpassung, $innenVon[0], $innenVon[1], $zVon), - ], 0.84]; - $seiten[] = [[ - aussenPunkt($einpassung, $bis[0], $bis[1], $z), - aussenPunkt($einpassung, $innenBis[0], $innenBis[1], $z), - aussenPunkt($einpassung, $innenBis[0], $innenBis[1], $zBis), - aussenPunkt($einpassung, $bis[0], $bis[1], $zBis), - ], 0.84]; + $seiten[] = [$viereck($innenVon, $z, $von, $z, $von, $zVon, $innenVon, $zVon), + 0.66, "Wand " . $k["richtung"] . " Schnitt A"]; + $seiten[] = [$viereck($bis, $z, $innenBis, $z, $innenBis, $zBis, $bis, $zBis), + 0.66, "Wand " . $k["richtung"] . " Schnitt B"]; } $etwasSichtbar = false; foreach ($seiten as $seite) { - if (aussenSichtbar($seite[0])) { - $polygone[] = ["punkte" => $seite[0], - "farbe" => aussenSchatten($farbe, $seite[1])]; - $etwasSichtbar = true; + $projiziert = []; + foreach ($seite[0] as $pkt) { + $projiziert[] = aussenPunkt($einpassung, $pkt[0], $pkt[1], $pkt[2]); } + if (!aussenSichtbar($projiziert)) { + continue; + } + // Erst sammeln - gemalt wird nach der Schleife, von hinten + // nach vorn. In Kantenreihenfolge gemalt uebermalte die + // Innenseite der hinteren Wand die Aussenseite der + // vorderen, und der Koerper sah aus wie ein Tisch, durch + // den man hindurchschaut. + $waende[] = ["tiefe" => aussenTiefe($seite[0]), + "punkte" => $projiziert, + "farbe" => aussenSchatten($farbe, $seite[1]), + "was" => ($f["raum"] ?? "?") . ": " . $seite[2]]; + $etwasSichtbar = true; } if (!$etwasSichtbar) { continue; @@ -570,16 +591,30 @@ function aussenZeichnung() $b = 0.8; $pa = [$von[0] + ($bis[0] - $von[0]) * $a, $von[1] + ($bis[1] - $von[1]) * $a]; $pb = [$von[0] + ($bis[0] - $von[0]) * $b, $von[1] + ($bis[1] - $von[1]) * $b]; - $polygone[] = ["punkte" => [ - aussenPunkt($einpassung, $pa[0], $pa[1], $z), - aussenPunkt($einpassung, $pb[0], $pb[1], $z), - aussenPunkt($einpassung, $pb[0], $pb[1], $z + $torHoch), - aussenPunkt($einpassung, $pa[0], $pa[1], $z + $torHoch), - ], "farbe" => aussenSchatten($farbe, 0.52)]; + $torWelt = [[$pa[0], $pa[1], $z], [$pb[0], $pb[1], $z], + [$pb[0], $pb[1], $z + $torHoch], [$pa[0], $pa[1], $z + $torHoch]]; + $torPunkte = []; + foreach ($torWelt as $pkt) { + $torPunkte[] = aussenPunkt($einpassung, $pkt[0], $pkt[1], $pkt[2]); + } + // Ein Haar naeher als seine Wand, damit es auf ihr liegt + // und nicht neben ihr einsortiert wird. + $waende[] = ["tiefe" => aussenTiefe($torWelt) + 0.001, + "punkte" => $torPunkte, + "farbe" => aussenSchatten($farbe, 0.52), + "was" => ($f["raum"] ?? "?") . ": Tor"]; } } } + // Von hinten nach vorn, innerhalb dieses Koerpers. + usort($waende, function ($a, $b) { + return $a["tiefe"] <=> $b["tiefe"]; + }); + foreach ($waende as $wandflaeche) { + $polygone[] = $wandflaeche; + } + // --- Dach -------------------------------------------------------- if ($dach && $dach["art"] === "sattel" && count($ecken) === 4) { // Der First laeuft entlang der laengeren Gebaeudeachse, wenn nichts