Une méthode rapide et sale consiste à dessiner les ombres des toits du bâtiment uniquement, à les rendre en gris foncé (de préférence semi-transparent s'il y a des couches de sol sous-jacentes) et à dessiner les polygones du bâtiment par-dessus. Les ombres du toit sont obtenues en traduisant les polygones du bâtiment par les distances déterminées par les hauteurs du bâtiment dans la direction établie par l'azimut et l'altitude de la source lumineuse (considérée comme infiniment éloignée). (Une formule pour le montant de la traduction apparaît ci-dessous.)
Cela a tendance à fonctionner correctement, sauf pour les basses altitudes ou les grands bâtiments (tels que les gratte-ciel): voyez comment les ombres des bâtiments isolés les plus hauts du côté droit sont séparées des bâtiments eux-mêmes.
Pour connecter correctement les ombres aux bâtiments, vous devez inclure les ombres des murs du bâtiment . Ce n'est pas difficile à faire. L'ombre du mur s'étendant entre un point situé en P et un autre point situé en Q sera le quadrilatère délimité par {P, Q, Q ', P'} où Q 'est l'ombre de Q et P' est l'ombre de P. Un bâtiment polygonal sera une collection de polygones connectés représentés par des séquences fermées de points (P (1), P (2), ..., P (n)). Pour chacun de ces polygones, formez l'union des ombres des bords (P (1), P (2)), (P (2), P (3)), ..., (P (n), P ( 1)). C'est simple à faire au moyen d'une boucle sur les bords.
Pour une lumière selon un azimut de un degré (est du nord) et une altitude de s degrés ( à partir de l'horizon), l'ombre d'un point P de coordonnées projetées (x, y) et de hauteur h (toutes exprimées dans les mêmes unités , comme les mètres) est situé à P '= (x - h sin (a) / tan (s), y - h cos (a) / tan (s)). Il suffit de calculer sin (a) / tan (s) et cos (a) / tan (s) une fois pour toute la couche, et pour chaque polygone, il suffit de multiplier ces facteurs par la hauteur une fois pour obtenir les décalages pour chaque ombre ponctuelle dans le polygone. (La véritable charge de travail informatique est supportée par le SIG, pas par votre code, car il forme les unions de tous ces quadrilatères.)
Voici un exemple de l'effet. (L'azimut et l'altitude ont légèrement changé par rapport à la première figure, mais les polygones et les hauteurs des bâtiments - qui varient - sont les mêmes qu'avant.)
appendice
En réponse à une demande, voici le code utilisé pour créer le deuxième exemple. Bien que presque personne n'utilise plus ce langage (Avenue), il pourrait bien servir de pseudocode pour créer une solution dans votre SIG préféré. (Contrairement à la plupart des pseudocodes, cependant, il a été testé en le faisant fonctionner. :-) C'est si simple qu'aucune explication ne devrait être nécessaire; sachez simplement que l'indexation commence par 0 et non par 1 et que les anneaux de polygones sont explicitement fermés (le dernier point de la liste coïncide avec le premier point).
' 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