Eine schnelle und schmutzige Methode besteht darin, nur die Schatten der Gebäudedächer zu zeichnen, sie in Dunkelgrau zu rendern (vorzugsweise halbtransparent, wenn darunter liegende Grundschichten vorhanden sind) und die Gebäudepolygone darüber zu zeichnen. Die Dachschatten werden erhalten, indem die Gebäudepolygone um die durch die Gebäudehöhen bestimmten Abstände in die Richtung verschoben werden, die durch den Azimut und die Höhe der Lichtquelle (die als unendlich weit entfernt angesehen wird) festgelegt wird. (Eine Formel für den Übersetzungsbetrag wird unten angezeigt.)
Dies funktioniert in der Regel einwandfrei, außer bei niedrigen Höhen oder hohen Gebäuden (z. B. Wolkenkratzern): Sehen Sie, wie die Schatten der höheren, isolierten Gebäude auf der rechten Seite von den Gebäuden selbst getrennt sind.
Um die Schatten ordnungsgemäß mit den Gebäuden zu verbinden, müssen Sie die Schatten der Gebäudewände einbeziehen. Das ist nicht schwer zu tun. Der Schatten der Wand, der sich zwischen einem Punkt bei P und einem anderen Punkt bei Q erstreckt, ist das durch {P, Q, Q ', P'} umrissene Viereck, wobei Q 'der Schatten von Q und P' der Schatten von ist P. Ein polygonales Gebäude ist eine Ansammlung zusammenhängender Polygone, die durch geschlossene Folgen von Punkten (P (1), P (2), ..., P (n)) dargestellt werden. Bilden Sie für jedes dieser Polygone die Vereinigung der Schatten der Kanten (P (1), P (2)), (P (2), P (3)), ..., (P (n), P ( 1)). Dies ist mit einer Schlaufe über den Kanten einfach zu bewerkstelligen.
Für ein Licht mit einem Azimut von einem Grad (östlich von Norden) und eine Höhe von s Graden (vom Horizont), der Schatten eines Punkt P mit projizierten Koordinaten (x, y) und Höhe h (alle in den gleichen Einheiten ausgedrückt , wie Meter) liegt bei P '= (x - h sin (a) / tan (s), y - h cos (a) / tan (s)). Sie müssen sin (a) / tan (s) und cos (a) / tan (s) nur einmal für die gesamte Ebene berechnen, und für jedes Polygon müssen Sie diese Faktoren nur einmal mit der Höhe multiplizieren, um die Offsets für zu erhalten jeder Punktschatten im Polygon. (Der tatsächliche Rechenaufwand wird vom GIS getragen, nicht von Ihrem Code, da er die Gewerkschaften aller dieser Vierecke bildet.)
Hier ist ein Beispiel für den Effekt. (Der Azimut und die Höhe haben sich im Vergleich zur ersten Figur geringfügig geändert, aber die Baupolygone und -höhen - die variieren - sind dieselben wie zuvor.)
Blinddarm
Als Antwort auf eine Anfrage sehen Sie hier den Code, der zum Erstellen des zweiten Beispiels verwendet wurde. Obwohl fast niemand mehr diese Sprache (Avenue) verwendet, könnte sie als Pseudocode für die Erstellung einer Lösung in Ihrem Lieblings-GIS dienen. (Im Gegensatz zu den meisten anderen Pseudocodes wurde es jedoch getestet, indem es tatsächlich ausgeführt wurde. :-) Es ist so einfach, dass keine Erklärung erforderlich ist. Beachten Sie jedoch, dass die Indizierung mit 0 und nicht mit 1 beginnt und dass Polygonringe explizit geschlossen werden (der letzte Punkt in der Liste stimmt mit dem ersten Punkt überein).
' S
' Return the shadow of a shape.
' Field calculator example:
' av.run("S", {[shape], [height], 200, 35})
'======================================================================'
theShape = SELF.Get(0) ' A projected polygon
xHeight = SELF.Get(1) ' Expressed in the projected units
xAzimuth = SELF.Get(2).AsRadians ' Any angle (in degrees) east of north
xAltitude = SELF.Get(3).AsRadians ' Angle between 0 and 90 (vertical)
'
' Compute the shadow offsets.
'
xSpread = 1/xAltitude.Tan
x = -xHeight * xSpread * xAzimuth.Sin
y = -xHeight * xSpread * xAzimuth.Cos
xy = x@y
'
' Begin with the original shape.
'
p = theShape.Clone
'
' Adjoin the wall shadows.
'
for each lPts in theShape.AsList ' Loop over the rings
for each i in 1..(lPts.Count-1) ' Loop over edges in this ring
l = {lPts.Get(i-1), lPts.Get(i), lPts.Get(i)+xy, lPts.Get(i-1)+xy}
p = p.ReturnUnion(Polygon.Make({l}))
end
end
return p
' end of script