Szybką i brudną metodą jest rysowanie cieni tylko dachów budynków, renderowanie ich w kolorze ciemnoszarym (najlepiej półprzezroczystym, jeśli znajdują się pod nimi warstwy gruntu) i rysowanie na nich wielokątów budynku. Cienie dachu są uzyskiwane przez przełożenie wielokątów budynku na odległości określone wysokościami budynków w kierunku ustalonym przez azymut i wysokość źródła światła (uważane za nieskończenie daleko). (Poniżej znajduje się wzór na ilość tłumaczeń.)
Zwykle działa to dobrze, z wyjątkiem niskich wysokości lub wysokich budynków (takich jak drapacze chmur): zobacz, jak cienie wyższych izolowanych budynków po prawej stronie są oddzielone od samych budynków.
Aby prawidłowo połączyć cienie z budynkami, musisz uwzględnić cienie ścian budynku . Nie jest to trudne. Cień ściany rozciągający się między punktem położonym w punkcie P a innym punktem położonym w punkcie Q będzie czworobokiem wyznaczonym przez {P, Q, Q ', P'}, gdzie Q 'jest cieniem Q, a P' jest cieniem P. Wieloboczny budynek będzie zbiorem połączonych wielokątów reprezentowanych przez zamknięte sekwencje punktów (P (1), P (2), ..., P (n)). Dla każdego takiego wielokąta utwórz połączenie cieni krawędzi (P (1), P (2)), (P (2), P (3)), ..., (P (n), P ( 1)). Można to zrobić za pomocą pętli na krawędziach.
Dla światła na azymut a ° (wschód od północy) i wysokości s stopni (od Horizon), cień punktu P z przewidywanymi współrzędnych (x, y), a wysokość h (wszystko wyrażone w takich samych jednostkach , takie jak metry) znajduje się w punkcie P '= (x - h sin (a) / tan (s), y - h cos (a) / tan (s)). Musisz obliczyć sin (a) / tan (s) i cos (a) / tan (s) tylko raz dla całej warstwy, a dla każdego wielokąta wystarczy tylko pomnożyć te czynniki przez wysokość, aby uzyskać przesunięcia dla każdy punkt cienia w wielokącie. (Rzeczywiste obciążenie obliczeniowe jest przenoszone przez GIS, a nie twój kod, ponieważ tworzy związki wszystkich tych czworoboków).
Oto przykład efektu. (Azymut i wysokość zmieniły się nieznacznie w porównaniu z pierwszą figurą, ale wielokąty i wysokości budynków - które się różnią - są takie same jak wcześniej.)
dodatek
W odpowiedzi na żądanie oto kod użyty do utworzenia drugiego przykładu. Chociaż prawie nikt już nie używa tego języka (Avenue), może on również służyć jako pseudokod do tworzenia rozwiązania w twoim ulubionym GIS. (W przeciwieństwie do większości pseudokodów, został on jednak przetestowany przez jego uruchomienie. :-) Jest to tak proste, że nie trzeba go tłumaczyć; pamiętaj tylko, że indeksowanie zaczyna się od 0, a nie 1, i że pierścienie wielokątów są jawnie zamknięte (ostatni punkt na liście pokrywa się z pierwszym punktem).
' 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