Un método rápido y sucio es dibujar solo las sombras de los techos de los edificios, renderizarlos en gris oscuro (preferiblemente semitransparente si hay capas de suelo subyacentes) y dibujar los polígonos del edificio sobre ellos. Las sombras del techo se obtienen traduciendo los polígonos del edificio por las distancias determinadas por las alturas del edificio en la dirección establecida por el acimut y la altitud de la fuente de luz (considerada infinitamente lejos). (Una fórmula para la cantidad de traducción aparece a continuación).
Esto tiende a funcionar bien, excepto en altitudes bajas o edificios altos (como rascacielos): vea cómo las sombras de los edificios aislados más altos en el lado derecho se separan de los edificios mismos.
Para conectar las sombras correctamente a los edificios, debe incluir las sombras de las paredes del edificio . Esto no es difícil de hacer. La sombra de la pared que se extiende entre un punto ubicado en P y otro punto ubicado en Q será el cuadrilátero delineado por {P, Q, Q ', P'} donde Q 'es la sombra de Q y P' es la sombra de P. Un edificio poligonal será una colección de polígonos conectados representados por secuencias cerradas de puntos (P (1), P (2), ..., P (n)). Para cada uno de estos polígonos, forme la unión de las sombras de los bordes (P (1), P (2)), (P (2), P (3)), ..., (P (n), P ( 1)). Esto es fácil de hacer mediante un bucle sobre los bordes.
Para una luz en un azimut de un grados (al este del norte) y una altitud de s grados (desde el horizonte), la sombra de un punto P con coordenadas proyectadas (x, y) y la altura h (expresados en las mismas unidades , como metros) se encuentra en P '= (x - h sin (a) / tan (s), y - h cos (a) / tan (s)). Solo tiene que calcular sin (a) / tan (s) y cos (a) / tan (s) una vez para toda la capa, y para cada polígono solo tiene que multiplicar esos factores por la altura una vez para obtener las compensaciones para cada punto de sombra en el polígono. (La carga de trabajo computacional real la lleva el SIG, no su código, ya que forma las uniones de todos estos cuadriláteros).
Aquí hay un ejemplo del efecto. (El acimut y la altitud han cambiado ligeramente en comparación con la primera figura, pero los polígonos y las alturas de los edificios, que varían, son los mismos que antes).
Apéndice
En respuesta a una solicitud, aquí está el código utilizado para crear el segundo ejemplo. Aunque ya casi nadie usa este lenguaje (Avenue), bien podría servir como pseudocódigo para crear una solución en su SIG favorito. (Sin embargo, a diferencia de la mayoría de los pseudocódigos, se ha probado ejecutándolo realmente. :-) Es tan simple que no se necesita ninguna explicación; solo tenga en cuenta que la indexación comienza con 0, no con 1, y que los anillos de polígono están explícitamente cerrados (el último punto de la lista coincide con el primer punto).
' 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