UNIVERSIDAD DE JAÉN Centro de Estudios de Postgrado

Trabajo Fin de Máster

TECNICAS GEOMÁTICAS Y MODELADO PROCEDURAL PARA LA GENERACIÓN DE MODELOS URBANOS EN 3D

Alumno/a: De la Torre Morales, Antonio

Tutores: Prof. D. Jorge Delgado García Prof. D. Juan Roberto Jiménez Pérez Dpto: Centro de estudios de postgrado

Centro de Estudios de Postgrado

Diciembre, 2015

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Universidad de Jaén Centro de Estudios de Postgrado

Don Jorge Delgado García y Don Juan Roberto Jiménez Pérez, tutores del Trabajo de Fin de Master titulado: Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos 3D, que presenta Antonio de la Torre Morales, autorizan su presentación para defensa y evaluación en el Centro de Estudios de Postgrado.

Jaén, Diciembre de 2015

El alumno: Los tutores:

Antonio de la Torre Morales Jorge Delgado García Juan Roberto Jiménez Pérez

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 2

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Resumen

En el presente trabajo de fin de máster se abordan diferentes técnicas geoespaciales que se emplean actualmente en la captura de información geográfica así como su empleo junto al modelado procedural para generar modelos urbanos inteligentes en 3D, los cuales tienen diversas aplicaciones y serán clave en el desarrollo de las "Smart Cities".

Abstract

This Master´s dissertation board different geospatial technologies that are used nowadays in the capture of geographical information as well as his employment together with the procedural modelling to generate urban intelligent models in 3D, which have diverse applications and they will be key in the development of the "Smart Cities”.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 3

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Índice 1. Introducción ...... 8 1.1. Justificación ...... 8 1.2. Objetivos ...... 10 1.3. Estructura ...... 11 1.4. Antecedentes ...... 12 2. Metodología ...... 17 2.1. Introducción ...... 17 2.2. Obtención de los datos ...... 18 2.2.1. Mediante fotogrametría ...... 18 2.2.2. Mediante LiDAR ...... 24 2.3. Preparación de los datos ...... 35 2.4. Generación del modelo. Modelado procedural ...... 41 2.5. Aplicación de los modelos urbanos 3D ...... 49 3. Aplicación de la Metodología ...... 53 3.1. Zona de estudio ...... 53 3.2. Instrumentación y software empleado ...... 54 3.3. Desarrollo metodológico ...... 55 3.3.1. Obtención de los datos ...... 55 3.3.2. Preparación de los datos ...... 59 3.3.3. Modelado de la ciudad en 3D ...... 75 3.3.4. Aplicación del Modelo. Análisis solar ...... 93 4. Conclusiones ...... 104 5. Bibliografía ...... 105 6. Anexos ...... 107 6.1. Código empleado para generar los edificios ...... 107 6.2. Código empleado para generar las calles ...... 108 6.3. Código empleado para generar los árboles ...... 178 6.4. Código empleado para generar el edificio nuevo ...... 191 7. Mapas ...... 195

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 4

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Índice de figuras

Figura 2-1. Método indirecto para obtener la ortofoto ...... 20 Figura 2-2. Proceso para llevar a cabo la rectificación...... 21 Figura 2-3. Escaneado de la superficie terrestre mediante lidar ...... 24 Figura 2-4. Tiempo de viaje de láser ...... 25 Figura 2-5. La amplitud del pulso recibido decrece ...... 25 Figura 2-6. Sistema de posicionamiento del Lidar ...... 26 Figura 2-7. Componentes del sistema lidar ...... 27 Figura 2-8. Recubrimientos en el vuelo lidar ...... 29 Figura 2-9. Pasadas del vuelo lidar ...... 29 Figura 2-10. Trayectoria seguida ...... 30 Figura 2-11. Formato del archivo LAS ...... 31 Figura 2-12. Clasificación estándar de los puntos ...... 31 Figura 2-13. Ajuste de pasadas ...... 32 Figura 2-14. Puntos de paso ...... 33 Figura 2-15. División en bloques ...... 33 Figura 2-16. Modelo digital de superficie ...... 34 Figura 2-17. Modelo digital del terreno ...... 35 Figura 2-18. Izq.: Ortoimagen convencional; Dcha.: Ortoimagen verdadera ...... 36 Figura 2-19. Proyección ortogonal ...... 37 Figura 2-20. Áreas ocultas en proyección ortogonal ...... 38 Figura 2-21. Izquierda.- Ortofoto convencional (existen zonas ocultas). Centro - Paso intermedio (se aprecia el efecto fantasma). Derecha - Orto verdadera ya corregida (áreas ocultas rellenas con información de ortos adyacentes)...... 39 Figura 2-22. Pasos para la generación un modelo urbano ...... 42 Figura 2-23. Reconstrucción del Eixample de Barcelona a partir de datos catastrales ...... 44 Figura 2-24. Modelo sintético de estructura urbana. Mapa de patrones con region radial, orgánica y regular. Generación del modelo correspondiente...... 45 Figura 2-25. Estructura urbana tipo Manhattan ...... 46 Figura 2-26. Estructura urbana tipo Barcelona ...... 46 Figura 2-27. Grafo que representa un conjunto de reglas procedurales y el resultado final del edificio ...... 48 Figura 2-28. Edificio obtenido a partir de 3 edificios procedurales diferentes...... 48 Figura 2-29. Modelo urbano procedural con nivel de detalle utilizando un criterio de distancia a partir de la esfera roja ...... 49 Figura 2-30. Modelización de una fuente de emisión de ruido usando datos CityGML en 3D ...... 50 Figura 2-31. Mapa de ruido generado a partir de datos CityGML ...... 51 Figura 2-32. Atlas económico de Berlín ...... 52 Figura 2-33. Atlas solar de Berlín ...... 53 Figura 3-1. Zona elegida a modelar ...... 54 Figura 3-2. Web del IGN ...... 56 Figura 3-3. Ortofoto PNOA ...... 57 Figura 3-4. Datos Lidar ...... 58

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 5

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-5. MDT del IGN ...... 58 Figura 3-6. Sede electrónica del catastro ...... 59 Figura 3-7. Herramienta clip ...... 60 Figura 3-8. parámetros usados con la herramienta clip ...... 61 Figura 3-9. Elementos, relaciones y tablas del esquema CIM ...... 62 Figura 3-10. Cargando los elementos en el esquema ...... 63 Figura 3-11. Atributos de la capa Building dentro del esquema ...... 63 Figura 3-12. Nube de puntos lidar obtenida del IGN ...... 66 Figura 3-13. Filtros para datos lidar en ArcGIS ...... 66 Figura 3-14. Puntos pertenecientes al terreno ...... 67 Figura 3-15. Herramienta para obtener el modelo digital del terreno ...... 67 Figura 3-16. Parámetros empleados para obtener el MDT ...... 68 Figura 3-17. MDT obtenido a partir de datos LiDAR ...... 69 Figura 3-18. Filtrado de puntos para obtener un MDS ...... 69 Figura 3-19. Parámetros empleados para obtener el MDS ...... 70 Figura 3-20. MDS obtenido ...... 71 Figura 3-21. Eliminación de errores ...... 72 Figura 3-22. Obtención del modelo de superficie normalizado ...... 73 Figura 3-23. Modelo de superficie normalizado obtenido ...... 73 Figura 3-24. Parámetros para calcular la altura de los edificios ...... 74 Figura 3-25. Altura de los edificios (Total height) ...... 74 Figura 3-26. Herramienta para recortar el terreno ...... 75 Figura 3-27. Nuevo proyecto CityEngine ...... 75 Figura 3-28. Creación de una nueva escena ...... 76 Figura 3-29. Configuración de la escena ...... 76 Figura 3-30. Parámetros de intensidad solar ...... 77 Figura 3-31. Importación del terreno...... 78 Figura 3-32. Terreno importado ...... 78 Figura 3-33. Importación del modelo 3DCIM ...... 79 Figura 3-34. Capas no alineadas ...... 80 Figura 3-35. Alineación de la red de calles ...... 81 Figura 3-36. Alineación del terreno ...... 81 Figura 3-37. Parámetros para alinear el terreno ...... 82 Figura 3-38. Escena con todas las capas alineadas ...... 82 Figura 3-39. Creación de una nueva regla CGA ...... 83 Figura 3-40. Subidivisiones del edificio ...... 84 Figura 3-41. Seleccionando todos los objetos dentro de una misma capa...... 85 Figura 3-42. Asignando el fichero .cga ...... 86 Figura 3-43. Escena finalizada ...... 87 Figura 3-44. Parámetros de las intersecciones ...... 88 Figura 3-45. Creación de marcadores ...... 89 Figura 3-46. Exportando la escena web ...... 89 Figura 3-47. Capas exportadas a la escena web ...... 90 Figura 3-48. Compartiendo la escena web ...... 91 Figura 3-49. Escena web ...... 92 Figura 3-50. Edificio nuevo generado mediante métodos procedurales ...... 92 Figura 3-51. Edificio España y Torre de Madrid ...... 93 Figura 3-52. Limpiando las formas ...... 94

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 6

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-53. Tejados extraídos ...... 95 Figura 3-54. Exportar como geodatabase...... 95 Figura 3-55. Extracción de los muros ...... 96 Figura 3-56. Datos de radiación global ...... 97 Figura 3-57. Parámetros del fichero de radiación global ...... 98 Figura 3-58. Coordenadas para los datos de radiación ...... 98 Figura 3-59. Valores D y T obtenidos ...... 99 Figura 3-60. Parámetros introducidos en la calibración atmosférica ...... 99 Figura 3-61. Parámetros de calibración atmosférica ...... 100 Figura 3-62. Valores D y T ...... 100 Figura 3-63. Herramienta de radiación solar ...... 101 Figura 3-64. Raster obtenido con los datos de radiación ...... 101 Figura 3-65. Herramienta radiación en los tejados ...... 102 Figura 3-66. Potencial solar ...... 103 Figura 3-67. Idoneidad solar ...... 103

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 7

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

1. Introducción

1.1. Justificación

El presente documento se corresponde a la asignatura Trabajo de Fin de Máster del Máster en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio impartido por la Universidad de Jaén. De acuerdo con el RD 1393/2007, de 29 de octubre, por el que se establece la ordenación de las enseñanzas universitarias oficiales, los títulos oficiales de Máster deben concluir con la elaboración y defensa pública de un Trabajo Fin de Máster, que tendrá entre 6 y 30 créditos (art.15.3), en el caso concreto del título cursado la dedicación establecida para este es de 12 créditos.

Mi motivación al realizar este trabajo se debe al interés que tengo en un tema de vital importancia para nuestra sociedad como son las distintas formas de representar la realidad. Son numerosas las ciudades y empresas que demandan modelos virtuales en 3D que representen fielmente su entorno para diferentes áreas de aplicación como la planificación urbana, telecomunicaciones móviles, gestión de desastres, catastro 3D, el turismo, navegación, gestión de instalaciones y simulaciones ambientales. Además, en la aplicación de la directiva europea sobre el ruido ambiental los modelos de ciudades en 3D juegan un papel importante.

En los últimos años la mayoría de los modelos virtuales en 3D han sido definidos como modelos puramente gráficos o visuales, descuidando los aspectos semánticos y topológicos. Por lo tanto estos modelos se podían usar casi solamente para fines de visualización, pero no para consultas temáticas, tareas de análisis o minería de datos espacial y era necesario un nuevo enfoque para satisfacer las necesidades de información de numerosos campos de aplicación. La inclusión de toda esa información en un único modelo virtual de la ciudad puede será clave para el desarrollo de las “Smart Cities”.

La cartografía urbana, sin duda, representa un elemento básico en el presente y en el futuro del sector geomático. Es necesario tener en cuenta que un 72% de la población europea vive en zonas urbanas o intermedias mientras que tan solo un 28% vive en zonas rurales (Eurostat 5 de Octubre de 2015), siendo además las áreas en las que se concentra una mayor actividad económica, e incluso cambios más rápidos en la fisonomía y configuración del territorio. Este continuo cambio y crecimiento de la

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 8

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D población urbana implica un desafío para los gestores y las administraciones públicas para proporcionar los servicios e infraestructuras que se demandan. El nuevo concepto de ciudad inteligente (Smart City) implica la necesidad de que las decisiones vengan avaladas por información objetiva que permitan una gestión sostenible de los recursos y de las demandas de la población. Es evidente, que la tendencia actual marca que asegurar que nuestras ciudades puedan soportar las demandas de la población, debemos volverlas más inteligentes a través de un mejor empleo de los recursos disponibles.

En este sentido se están desarrollando diversos proyectos en el sentido de considerar a nuestras ciudades como elementos cambiantes, e incluso como elementos vivos, ya que comparten las propias etapas que caracterizan a los seres vivos (crecimiento, madurez y muerte –o decadencia-). Un ejemplo, claro de estas iniciativas es el proyecto “European Smart City”, orientado al desarrollo de técnicas integrales de la gestión de las ciudades, en base a las necesidades planteadas (tanto presentes como futuras), los recursos disponibles y la información del propio territorio (que debe incluir, logícamente, información de tipo geomático, pero también otros elementos sociales, económicos, poblacionales. etc.).

La misión de una Smart City es mejorar el cómo nos movemos a través de entornos cada vez más complejos y asegurar que nuestro entorno urbano es seguro y confortable para los actuales y futuros ciudadanos. El desarrollo de estas ciudades inteligentes también promete alcanzar nuevas oportunidades económicas y beneficios sociales.

La raíz del pensamiento de la Smart City es ver la ciudad como un repositorio de datos e información centrada en una ubicación geográfica específica. La geografía enriquece el paisaje proporcionando un sendero a datos históricos, económicos y sociales. Ciertamente, casi cualquier tipo de datos puede ser asignado a una ubicación, y es la riqueza de tales datos integrados lo que convierte a una ciudad en inteligente, más que la simple suma de cada una de sus partes.

Los avances en informática y la creciente accesibilidad de las nuevas aplicaciones nos permiten recoger y visualizar una gran cantidad de información a través de las tecnologías móviles. A su vez esto nos permite entender nuestro entorno

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 9

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D urbano con más detalle. La capacidad para llevar a cabo análisis de simulación multi- dimensional usando datos procedentes de los productores de datos tradicionales (gobierno, investigación e industria) y por los mismos ciudadanos está permitiendo nuevas relaciones y percepciones que han de ser identificadas. También la habilidad para presentar información geolocalizada a los ciudadanos y la difusión de datos en 2D y 3D a través de aplicaciones móviles y web ofrece nuevas y maneras de participar, cambiar u optimizar el funcionamiento de nuestras ciudades.

La última generación de modelos de información urbana 3D interoperables (UIM Urban Information Model), creada a partir de información geoespacial precisa a escala urbana, pueden ser usados incluso para crear servicios web inteligentes basados en información geométrica, semántica, morfológica y estructural.

Expuesto lo anterior, se puede decir que los modelos de información urbanos 3D serán claves para desarrollar simulaciones para ilustrar como las ciudades inteligentes pueden funcionar. Estas simulaciones servirán para asegurarse de que todo funciona de forma correcta y como medio para probar los servicios delante de su público objetivo, convirtiéndose en una herramienta esencial, para las administraciones públicas, las empresas y para los ciudadanos.

1.2. Objetivos

A lo largo de este Trabajo de Fin de Máster se va a intentar incidir en la construcción de modelos tridimensionales de ciudades que incorporen validez geométrica y que puedan ser utilizados y colaborar al desarrollo de las “Smart Cities” y en la la toma de decisiones.

Se pretende abordar las distintas técnicas que se emplean para obtener estos modelos, así como mostrar diversas aplicaciones que tienen hoy en día. Se describirá además el proceso que se lleva a cabo de principio a fin para obtener un modelo de estas características mediante un ejemplo práctico empleando software compatible con el estándar CityGML, y utilizando el modelado procedural para generar los diferentes edificios y elementos de la ciudad a partir de la información que actualmente ponen a disposición de los ciudadanos las diferentes administraciones, poniendo de manifiesto la importancia de la difusión de la información geomática como generadora de valor añadido a la misma. Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 10

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Por último se le dará alguna aplicación al modelo obtenido que sirva como ejemplo del potencial que tienen, obteniendo algún producto que pueda ser difundido a través de la red o mediante algún otro medio.

1.3. Estructura

Tal y como se muestra en la figura 1, la memoria de este Trabajo Fin de Máster se estructura en los siguientes apartados:

 Una Introducción donde se describen la motivación que ha llevado a realizar este trabajo así como los objetivos que se persiguen y algunos antecedentes donde se describe cómo ha ido evolucionando el modelado 3D de ciudades hasta hoy, así como la propia estructura de esta memoria.  Una segunda parte donde se describe la metodología, es decir, las diferentes técnicas que se emplean para obtener los datos necesarios que permitan representar un entorno urbano mediante un modelo 3D.  Un apartado llamado aplicación de la metodología donde se describe como se ha llevado a cabo la aplicación práctica de las diferentes metodologías y los productos y resultados que se han obtenido. Aquí se describe el software empleado y el trabajo que se ha llevado a cabo en la zona de estudio propuesta.  Unas conclusiones donde se analice el trabajo llevado a cabo que incluye un análisis de grado de cumplimiento de los objetivos planteados para este Trabajo Fin de Máster.  Un apartado final en el que se incluye información gráfica complementaria y mapas derivados de la aplicación tras el análisis del modelo.  Por último, se incluyen varios Anexos en donde se proporciona al lector información complementaria sobre los trabajos desarrollados así como otra información que se considera de interés para el mismo.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 11

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Introducción

Metodología

Aplicación de la metodología

Conclusiones

Anexos

Mapas

1.4. Antecedentes

Hasta hace pocos años los modelos 3D de ámbitos urbanos eran puramente visuales y no presentaban valor añadido alguno más allá de la mera simulación. Estos se caracterizaban por:

 Ser meras representaciones  Ser modelos puramente gráficos  Carecer de una componente topológica y semántica  Uso restringido. Empleados en arquitectura básicamente

Sin embargo hoy en día y debido a aplicaciones tan populares como Google Earth/Google Maps que permiten la visualización 3D de distintas ciudades y/o edificios y a la rápida evolución de los sistemas de información geográfica desde entornos de trabajo 2D a 3D, surge la necesidad de disponer de modelos urbanos 3D que cuenten no solo con un componente geométrico sino que además estén enriquecidos con un amplio componente semántico acorde a las necesidades de información que la sociedad actual demanda. Surge la necesidad de poder emplear estos modelos en análisis geoespaciales, existiendo un gran número de aplicaciones en urbanismo, ordenación del territorio, mapas de ruido, estudios de eficiencia energética, videojuegos, gestión de emergencias…

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 12

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

A medida que se han ido incrementando tanto las plataformas tecnológicas que permitan generar, mantener y gestionar geoinformación 3D como el número de modelos 3D que distintos usuarios tanto privados como públicos han venido demandando, se han desarrollado distintos estándares internacionales con el objeto de cubrir la necesidad de contar con un modelo de información común y abierto que permita la representación 3D de objetos urbanos.

Uno de ellos es el conocido como CityGML, adoptado por el Open Geospatial Consortium (OGC) como estándar oficial desde el año 2008. Dicho modelo define detalladamente tanto las clases de objetos que participarán en un modelo urbano como las relaciones a establecer entre ellos y que configuraran tanto sus propiedades geométricas como topológicas, semánticas y de apariencia.

Además se caracteriza por contemplar 5 niveles de detalle con lo cual es posible recrear un modelo desde un entorno básico 2D a un entorno 3D de gran complejidad. Y dado que se trata de un formato basado en XML, en concreto desarrollado bajo el estándar Geography Markup Language 3 (GML3), es completamente compatible con cualquiera de los servicios web OGC actualmente en uso (WFS,WPS,WVS, W3DS, …). Por todo ello CityGML se ha convertido en el estándar de referencia en el modelado de entornos urbanos 3D dado su enorme potencial en este campo y el gran número de proyectos y aplicaciones en los que es posible su utilización.

A continuación se detalla la cronología seguida en el desarrollo del estándar CityGML desde sus inicios hasta el día de hoy:

 Año 2002: Comienza el desarrollo del estándar CityGML por parte de los miembros del denominado “Special Interest Group 3D (SIG 3D)” perteneciente a la iniciativa “Geodata Infraestructure North-Rhine Westphalia (GDI NRW)” radicada en Alemania. Dicho grupo SIG 3D es una plataforma libre y de carácter internacional compuesta por más de 70 compañías, administraciones municipales e institutos de investigación que trabajan en el desarrollo y explotación comercial de modelos 3D interoperables así como en su geovisualización.  Año 2004: El estándar CityGML pasa a ser debatido en el seno de los organismos internacionales como es el caso tanto del “European Spatial

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 13

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Data Research (EuroSDR)” como el grupo de trabajo “3D Information Management (3DIM) Working Group” del “Open Geospatial Consortium (OGC)”.  Año 2006: Se desarrolla la versión beta CityGML 1.0 aprobándose por el comité técnico del OGC en la especificación CityGML como documento de debate. Durante este año se aborda su discusión desde distintos grupos de trabajo del OGC como es el caso por ejemplo del “CAD/GIS Interoperability Working Group”.  Año 2007: CityGML es evaluado y chequeado de forma exhaustiva y con resultados muy positivos por parte del “OGC Web Services Testbed No. 4 (OWS-4)” lo que da lugar que el comité técnico del OGC considere este estándar por primera como miembro oficial del OGC.  Año 2008: El 20 de Agosto los miembros del OGC aprueban la versión 1.0.0 del CityGML como estándar oficial del OGC.  Año 2009: Se comienza a trabajar en las futuras versiones del estándar CityGML (1.1 y 2.0).  Año 2010: El OGC pone en marcha de forma oficial la revisión del estándar CityGML con vistas a la aprobación de una futura nueva versión.  Año 2011: El grupo de trabajo del OGC destinado a promocionar y evaluar el estándar CityGML da a conocer el borrador de la versión 1.1 con el fin de que pueda ser revisado por el público en general y éste pueda aportar las sugerencias que estime oportunas.  Año 2012: Se decide desechar la versión 1.1 prevista inicialmente y realizar un cambio más significativo que dará lugar a la aparición de la versión 2.0.0, aprobándose esta el 14 de Marzo como estándar oficial del OGC.

En cuanto a los niveles de detalles, son los siguientes: LoD 0: Representación 2.5D del terreno mediante el empleo de un modelo digital de elevaciones. Nivel de detalle suficiente para la realización de modelos a escalas globales o regionales.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 14

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

LoD 1: nivel de detalle a escala de ciudad en el que los edificios son representados únicamente mediante bloques.

LoD 2: representación a escala de ciudad donde los edificios tienen mayor detalle, adquiriendo sus fachadas diferentes texturas y distinguiendo claramente los tejados y techos del resto de estructuras propias del edificio. Se

definen algunas estructuras externas como escaleras o balcones. LoD 3: se define el exterior de los edificios con mayor lujo de detalles desde un punto de vista arquitectónico.

LoD 4: completa al nivel anterior centrándose en el interior de los edificios configurando la distribución de pisos y habitaciones, escaleras, puertas…

En cuanto a las técnicas empleadas para modelizar ciudades, destacan 2 que han ido evolucionando y ofreciendo buenos resultados en la línea de la automatización de modelos urbanos. La primera se basa en el uso exclusivo de imágenes, tanto para la reconstrucción del modelo geométrico como para el modelo de texturas. La segunda emplea la tecnología LIDAR para la reconstrucción de formas y puede usar tanto la misma tecnología como la fotografía para la reconstrucción de texturas.

1. 3DUM con fotogrametría aérea y terrestre.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 15

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Hasta ahora la generación de un modelo urbano a partir de fotografías requería de mucha intervención manual, tanto en la fase de aerotriangulación como en la de modelado, siendo imprescindible combinar los resultados de imágenes aéreas con imágenes terrestres.

Los procedimientos algorítmicos descritos en los últimos años se ciñen a la mejora de algún aspecto particular dentro del amplio espectro de problemas que la automatización de la extracción de un modelo tridimensional conlleva: calibración de la cámara, registro, extracción de estructuras, estimación de texturas etc.

Se han ido desarrollando soluciones parciales, que imponen ciertas restricciones en el uso o resultados. Algunos algoritmos asumen configuraciones especiales para las cámaras o imágenes mientras que otros proponen sistemas que parten de un modelo 3D aproximado que se refina mediante imágenes obtenidas por una cámara.

Estos procesos han ido automatizándose gracias a los algoritmos que buscan de forma automática puntos homólogos en las imágenes, de forma que actualmente se puede obtener cartografía urbana en un proceso semiautomático. Asimismo, en los últimos años se está registrando una importante tendencia en el uso de cámaras múltiples oblicuas que incorporan la posibilidad de realizar tomas inclinadas, a objeto de poder capturas las propias fachadas de los edificios a fin de enriquecer los modelos y poder extraer, bien de forma automática o manual, las texturas de dichas imágenes con calidad métrica.

2. 3DUM con LIDAR

Sus principales ventajas con respecto a la fotografía son: determinación directa, precisa y rápida de las distancias (y no indirecta en base a los resultados de una etapa de correlación de imágenes) y, en segundo lugar, puede trabajar de noche puesto que se trata de un sensor activo.

Es especialmente adecuado en zonas de alta densidad urbana. Ahora bien, es necesario tener en cuenta que la elaboración de un modelo urbano requiere el tratamiento de información almacenada en grandes volúmenes de nubes de puntos tridimensionales, en las que habitualmente su calidad radiométrica se limita a la

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 16

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D reflectancia del objeto (salvo procedimientos de integración de información proporcionada por cámaras auxiliares en el rango del visible). Esto implica la necesidad de llevar a cabo procesos de filtrado y clasificación de la información, así como la posterior extracción de los elementos que se deseen incorporar en el propio modelo (conversión a modelos cartográficos vectoriales, con problemas asociados de establecimiento de aristas de los edificios, a partir de nubes de datos distribuidas de forma irregular).

Ambas técnicas, requieren de una planificación de vuelo, apoyo en campo y una gran inversión de recursos. Actualmente existe una alternativa que consiste en el empleo de datos abiertos que se pueden encontrar fácilmente en la red, de acuerdo con lo planteado en la propia iniciativa INSPIRE sobre reutilización de la información geográfica capturada con fines generales. En este sentido, uno de los objetivos planteados en el proyecto es analizar la potencialidad de la información suministrada para poder caracterizar elementos básicos en la modelización, como, por ejemplo, las huellas de los edificios o red de calles, y a partir de ellos, obtener el modelo mediante técnicas de modelado procedural, empleando software que utilice el estándar de cityGML. Esta opción se plantea como una alternativa de gran interés, para diversas aplicaciones, ya que suprime los problemas, las necesidades de infraestructuras y equipamiento específico y costes y tiempos de ejecución ligados a las misiones de vuelo fotogramétrico, sea de imagen o de LiDAR.

2. Metodología

2.1. Introducción

A la hora de modelar una ciudad lo principal es definir el ámbito sobre el cuál se trabajará en función de la aplicación que se pretenda dar al modelo, y que datos serán necesarios para ello. Algunos datos que suelen emplearse típicamente son:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 17

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

 Ortofoto  MDT, MDS  LiDAR  Huellas de los edificios  Árboles  Calles  Elementos puntuales y lineales del mobiliario urbano tales como aceras, o señales de tráfico.

El proceso general a seguir es el siguiente:

Visualización Obtención de Preparación Obtención y Analísis del los datos de los datos del modelo modelo

Figura 2. Esquema general de generación de un modelo 3D de ciudad

2.2. Obtención de los datos

Para obtener un conjuntos de datos que puedan ser empleados en la generación de un modelo 3D urbano, se pueden emplear diversas metodologías basadas en fotogrametría o LiDAR. Estas se describen brevemente a continuación.

2.2.1. Mediante fotogrametría

Concepto de fotogrametría

La fotogrametría es el arte, ciencia, y tecnología de obtener información fidedigna a través de imágenes y otros sistemas de sensores sobre la Tierra y su entorno, así como de otros objetos físicos o procesos a través de la captura, medida, análisis y representación.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 18

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Como todas las técnicas relacionadas con la imagen, la fotogrametría ha evolucionado de forma drástica desde las imágenes analógicas a las digitales. En el campo de dicha técnica, se ha pasado en unos años desde las soluciones opticomecánicas de tipo totalmente analógico a las analíticas, que significaban la entrada de la informática (hardware + software) combinada con imágenes analógicas pero la revolución real apareció de la mano de la imagen digital.

Las principales ventajas de las técnicas digitales son, por un lado la automatización de los procesos –ya que desaparece la componente óptico-mecánica + electrónica que son sustituidos por software– y por la posibilidad de identificar puntos homólogos en las imágenes, es decir de medir automáticamente, casi sin intervención humana, mediante los restituidores fotogramétricos digitales. Potencia, por tanto las herramientas matemáticas de la fotogrametría analítica y de los procesos digitales de imágenes, abriendo la técnica a la generación de diferentes tipos de cartografías y representaciones tanto en 2D como en 3D.

Obtención de la ortoimagen

Mediante la Fotogrametría se pueden obtener ortoimágenes, las cuales son un producto de gran utilidad puesto que combina la calidad métrica de un mapa (proyección ortográfica) con la calidad semántica de una imagen, corrigiendo las distorsiones que presentan las imágenes originales como consecuencia de su toma (fundamentalmente, desplazamiento debido al relieve y desplazamiento por inclinación). Estas ortoimágenes (o mejor dicho, el mosaico de las mismas que da lugar a un documento cartográfico continuo de imagen) puede usarse como capa base a la hora de representar el terreno en un modelo 3D de ciudad, así como asignar textura a los elementos que aparecen sobre el terreno (tejados, calles, etc.).

Para obtenerla se aplica un proceso de rectificación diferencial para el cual es necesario disponer de un modelo digital de elevación (MDE), debiendo estar este referido a un sistema de proyección de coordenadas que será en el que se obtenga la imagen rectificada.

Con la rectificación diferencial se persigue asignar a cada elemento de la matriz del modelo digital el nivel digital correspondiente. Para determinar ese nivel digital es

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 19

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D necesario transformar las coordenadas terreno de los puntos X, Y, Z en fotocoordenadas x, y mediante la expresión de colinealidad:

푚 ∗ (푋 − 푋 ) + 푚 ∗ (푌 − 푌 ) + 푚 ∗ (푍 − 푍 ) 푥´ = −푐 ∗ 11 0 12 0 13 0 푚31 ∗ (푋 − 푋0) + 푚32 ∗ (푌 − 푌0) + 푚33 ∗ (푍 − 푍0)

푚 ∗ (푋 − 푋 ) + 푚 ∗ (푌 − 푌 ) + 푚 ∗ (푍 − 푍 ) 푦´ = −푐 ∗ 21 0 22 0 23 0 푚31 ∗ (푋 − 푋0) + 푚32 ∗ (푌 − 푌0) + 푚33 ∗ (푍 − 푍0)

Figura 2-1. Método indirecto para obtener la ortofoto

Para llevar a cabo la rectificación se sigue el siguiente proceso:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 20

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 2-2. Proceso para llevar a cabo la rectificación

El proceso fotogramétrico llevado a cabo para obtener una ortoimagen sería el siguiente:

Planificación del Orientación del vuelo. Red de bloque mediante Creación del MDE Ortorrectificación puntos de apoyo ajuste simultáneo

Planificación del vuelo. Red de puntos de apoyo

La escala es el factor clave para planificar el vuelo puesto que controla el coste final del proyecto (que variará en función del número total de modelos necesarios para cubrir una determinada zona).

Han de ser tenidas en cuenta por supuesto las condiciones ambientales:

 Nubes altas y cerradas para conseguir iluminación uniforme  Ángulo de inclinación solar por encima de 30º  Fecha ideal: Marzo-Abril o Mayo-Octubre

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 21

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

La escala determinará la altura de vuelo y por tanto el tamaño del fotograma en el terreno. En función del pliego de condiciones y del GSD requerido se procede a calcular el número de pasadas y fotogramas necesarios para llevar a cabo el vuelo.

Los puntos de apoyo han de ser distribuidos uniformemente por el terreno, adquiriendo sus coordenadas X, Y, Z antes de realizar el vuelo. Estos deben ser puntos de buena calidad que sean fácilmente identificables en los fotogramas posteriormente.

Tomadas las imágenes, se realiza una corrección radiométrica, así como un control de calidad de los puntos de apoyo y las imágenes digitales.

Orientación del bloque mediante ajuste simultáneo

Se obtienen las expresiones que relacionan el sistema de coordenadas imagen y el sistema de coordenadas terreno, mediante el proceso de orientación (interna y externa).

Se ajusta el bloque mediante mínimos cuadrados utilizando constreñimientos con pesos.

La orientación se basa en el empleo de aerotriangulación y ajuste simultáneo de bloque mediante ajuste de haces.

Creación del MDE

Se captura automáticamente mediante procedimientos de matching. Este se edita utilizando la superposición con el modelo estereoscópico y se almacena posteriormente.

El aspecto clave aquí es el espaciado, que dependerá del terreno y de la relación de escala. Se trata de un aspecto que se ha modificado en los últimos tiempos como consecuencia de la aparición de los nuevos procedimientos de correlación de

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 22

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D imágenes y el incremento de potencia en los sistemas de generación y procesamiento de los modelos. Así, frente a espaciados tradicionalmente empleados en la década de los 1990 de 10 a 15 veces el GSD de la imagen, en la actualidad se pueden obtener modelos (o al menos, conjuntos de puntos medidos de forma automática sobre la imagen) con un espaciado equivalente al del propio GSD de la misma. Esto permite una importante mejora en la caracterización de la morfología del territorio, en especial, en entornos, como es el caso de las ciudades donde la presencia de elementos antrópicos, lleva a que existen importantes discontinuidades.

Ortorrectificación

Se procede a la rectificación diferencial utilizando el MDE y los parámetros de orientación obtenidos anteriormente.

El resultado es un mosaico de ortoimágenes.

Ajuste radiométrico

Es necesario dado que las fotografías aéreas presentan frecuentemente falta de homogeneidad tanto a nivel local, como global, debido a los cambios de iluminación entre los momentos de toma de las imágenes.

Generación del mosaico

Se realiza de manera automática. La única preocupación es conseguir un producto con una buena apariencia final. Para ello es fundamental conseguir un buen empalme, tanto geométrico como radiométrico.

A la hora de seleccionar las imágenes más apropiadas se suele emplear alguno de los siguientes criterios:

 Cercanía al nadir de la imagen  GSD de la imagen  Inclinación del rayo óptico sobre el terreno  Variación radiométrica

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 23

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

2.2.2. Mediante LiDAR

Concepto de lidar

Se trata de un sistema que integra a su vez a diferentes sensores, que permite la medida rápida de puntos del terreno (XYZ) a partir del tiempo de vuelo de un pulso láser emitido, del que se conoce su ángulo de inclinación, así como la posición y orientación de la plataforma desde la cual el mismo fue emitido.

Figura 2-3. Escaneado de la superficie terrestre mediante lidar

Así el sensor láser emite un pulso de alta energía, enviado a la escena que lo refleja y vuelve a ser registrado por el sensor. Al ser un sensor activo es posible trabajar tanto de día como de noche (incluso es mejor de noche puesto que no hay interferencias con el sol). También es posible medir áreas con poca textura e incluso en zonas de sombra.

Trabaja a partir de las medidas del tiempo de vuelo (TOF-Time of Flight) y también registran la intensidad.

La medida de la distancia es de tipo polar, midiendo distancia y ángulo desde la fuente al objeto a medir.

La mayoría de ALS trabajan en infrarrojo por lo que están afectados por la presencia de nubes, nieve, lluvia… No es por tanto dependiente de las condiciones climáticas, a diferencia de los sensores radar.

Medida de la distancia

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 24

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

El principio del sistema LiDAR es similiar al empleado en la medida electrónica de distancias (EDM), donde un láser (en formato de pulso o de onda continua) se dispara desde un emisor y posteriormente registra la energía reflejada.

Mediante el cálculo del tiempo de vuelo (ToF) es posible calcular la distancia entre el sensor y el objeto.

El objeto puede ser un elemento artificial (un prisma por ejemplo) o elementos del propio terreno.

Figura 2-4. Tiempo de viaje de láser

Figura 2-5. La amplitud del pulso recibido decrece

푇 푅 = 퐿 ∗ 푐 2

푐 ∆푅 = ∗ ∆푅 2

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 25

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

푐 푅 = ∗ 푇 푚푎푥 2 퐿푚푎푥

Donde:

R = distancia recorrida

TL= tiempo de vuelo

c = velocidad de la luz

Obtención de coordenadas terreno

Las coordenadas terreno (XYZ) se determinan mediante:

1. La determinación precisa de la posición del sensor en el espacio mediante el empleo de DGPS. 2. La determinación de su orientación mediante un sistema inercial IMU. 3. La determinación de la inclinación del rayo láser. 4. La distancia entre el sensor y el objeto mediante el ToF.

Figura 2-6. Sistema de posicionamiento del Lidar

Una vez realizada la medición se obtiene una nube de puntos XYZ (no una representación ráster).

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 26

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Cada pulso láser emitido puede dar lugar a la medida de varios objetos del terreno (vegetación y suelo por ejemplo) gracias al tratamiento de los ecos (o del pulso continuo waveform).

Componentes del sistema

Los sistemas LiDAR se encuentran normalmente formados por:

 Una unidad de medida: formada por un transmisor láser y un receptor.  Un mecanismo deflector del rayo: espejo, polígono…  Sistema de posicionamiento GPS/INS (es necesario conocer los vectores y ángulos de desajuste entre el GPS/INS y la unidad láser). El GPS es de doble frecuencia y trabaja en modo diferencial con las estaciones de referencia cercanas.  Opcionalmente puede tener sensores de imagen para la generación de ortoimágenes o para la depuración de datos.  Plataformas: Avionetas, helicópteros, UAV…

Figura 2-7. Componentes del sistema lidar

Planificación del vuelo

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 27

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

La planificación se realiza teniendo en cuenta en todo momento el pliego de condiciones técnicas facilitado por el cliente que encarga el vuelo. Estas especificaciones técnicas suelen ser:

 Máximo FOV permitido  Frecuencia de escaneado mínima  Frecuencia de pulso  Densidad promedio de puntos de primer retorno por metro cuadrado  Sensor calibrado con una antigüedad menor a 12 meses  Recubrimiento transversal  Longitud máxima de las pasadas  Pasadas transversales de ajuste altimétrico  Precisión general altimétrica  Discrepancia altimétrica entre pasadas  Distancia a estaciones de referencia

Esta fase de planificación consiste en obtener las características del vuelo así como el modo de operar del sensor para cumplir con las especificaciones indicadas en el pliego.

Se ha de tener en cuenta:

 La orografía del terreno a volar  Las características del sistema utilizado  La climatología  El pliego de condiciones técnicas  La posibilidad de realizar un vuelo fotogramétrico simultáneo  Es aconsejable realizar también un vuelo de calibración

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 28

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 2-8. Recubrimientos en el vuelo lidar

Figura 2-9. Pasadas del vuelo lidar

Procesado de los datos

Una vez ejecutado el vuelo, para obtener correctamente la nube de puntos final, se tendrá que realizar un cálculo de la trayectoria del vuelo así como de la orientación del sensor en cada instante de tiempo, que permita posteriormente darle coordenadas absolutas a los puntos capturados.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 29

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Una vez extraídos los datos del sistema inercial, y convertidos a formato legible por el software de cálculo, se analiza la trayectoria diferencial de GPS obtenida, teniendo en cuenta:

 El número de satélites recibidos en la observación. Asegurándonos un mínimo de dos bases de referencia, no se deberían procesar datos cuando el número de satélites recibidos sea inferior a 5 durante el tiempo de observación.  La precisión en coordenadas XYZ de cada uno de los puntos de la trayectoria.

El cálculo de la trayectoria de vuelo concluye con un suavizado de la misma a partir de los datos procedentes de la IMU (sistema inercial), que convertirán el cálculo DGPS en un cálculo más preciso y riguroso.

Obtener el máximo de precisión en el cálculo de la trayectoria DGPS es el concepto más importante en todo el proceso de obtención de datos LiDAR.

La precisión a obtener se cuantifica en función del número de satélites obtenidos durante la observación y la fidelidad de las coordenadas de posición de las estaciones base.

Figura 2-10. Trayectoria seguida

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 30

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Realizado el cálculo de trayectorias GPS/INS, y con la nube de puntos en bruto, se obtiene la nube de puntos final en formato .LAS.

Este formato se trata de un estándar para trabajar con datos LiDAR, permitiendo el intercambio de ficheros que contienen información de una nube de puntos tridimensional. Es un archivo binario que mantiene toda la información procedente del sistema LiDAR, conservando la misma la propia naturaleza de los datos y del sistema de captura.

Figura 2-11. Formato del archivo LAS

Figura 2-12. Clasificación estándar de los puntos

Una vez obtenidas las nubes de puntos correspondientes a cada pasada del vuelo realizada, los datos han de ser procesados y preparados para la entrega y la futura extracción de información.

Este procesado podría consistir en:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 31

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

 Reorientación y ajuste entre pasadas por errores superiores a los esperados  Obtención de bloques según pliego de condiciones técnicas.  Paso de alturas elipsoidales a cotas ortométricas.  Clasificación automática de la nube de puntos.  Edición de la clasificación automática con ortoimágenes o pares estereoscópicos.  Obtención de productos derivados (curvados, MDT malla, etc..).  Extracción de información específica (Edificios, líneas eléctricas, documentación forestal, etc.).

Figura 2-13. Ajuste de pasadas

En el ajuste de pasadas, el funcionamiento es similar al ajuste de modelos independientes con parámetros de autocalibración.

 Modelización de desplazamientos, derivas y otros errores sistemáticos  Medida de puntos de paso  Medida de puntos de control  Ajuste de pasadas de forma que: los puntos de paso homólogos se transforman en el mismo punto terreno  los errores en los puntos de control son mínimos

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 32

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 2-14. Puntos de paso

Puesto que trabajar con todas y cada una de las pasadas es difícil debido a la gran cantidad de información que contiene cada una, lo que se hace es trabajar por bloques dividiendo toda la información en pequeños modelos con el fin de trabajar con la información de forma más precisa y rápida.

Figura 2-15. División en bloques

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 33

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Ya obtenidas las nubes de puntos, es necesario clasificarlas, diferenciando primeramente entre aquellos puntos que pertenecen al terreno y los objetos situados sobre éste. Posteriormente se clasificarían los distintos objetos en edificios, árboles, vehículos, tendidos eléctrico etc.

En primer lugar este proceso de clasificación debe basarse en métodos automáticos. Sin embargo, es complicado que esta clasificación sea exitosa al 100% en todo el terreno debido a la variabilidad, características y orografía de la escena.

Esto obliga a realizar un proceso semiautomático puesto que establecer un procedimiento y parámetros de clasificación automática para todas las zonas resulta imposible.

Este proceso semiautomático se apoya en la edición manual y puede estar ayudado por el uso de información adicional como puede ser el uso de ortoimágenes de la zona (debiendo ser coetáneas a la información LiDAR).

Obtención de productos y extracción de información

Clasificada la nube de puntos, se obtienen el MDT y MDS.

Figura 2-16. Modelo digital de superficie

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 34

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 2-17. Modelo digital del terreno 2.3. Preparación de los datos

Edición cartográfica de la ortoimagen para obtener las huella de los edificios (True-Ortho)

A partir de la ortoimagen se pueden digitalizar edificios y otros elementos fácilmente, obteniendo de esta forma las huellas de los edificios, calles, árboles y cualquier tipo de elemento que se pueda encontrar dentro de una ciudad. Sin embargo, para ello es necesario que todos los elementos que aparecen en la imagen estén adecuadamente rectificados, es decir, que para su rectificación diferencial se haya utilizado un modelos digital de superficies que incluyan dichos elementos. En la práctica, el producto habitual es el conocido como ground-ortho, es decir, una ortofotografía que ha sido generada a partir de un modelo digital del terreno, en el que sólo se considera los elementos naturales del terreno, estando el resto afectados por los desplazamientos debido al relieve (en dirección radial con respecto al nadir). Este hecho plantea algunos problemas para su uso en la generación de modelos 3D de ciudades como:

1. Desplazamientos y ocultamientos que hacen difícil sobre imponer información vectorial para propósitos de actualización de cartografía. 2. La ortorrectificación es parcialmente imprecisa geométricamente y/o incompleta (los edificios se distorsionan y se mueven de su localización verdadera debido a que no están modelados en el MDT).

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 35

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 2-18. Izq.: Ortoimagen convencional; Dcha.: Ortoimagen verdadera

Usando modelos digitales de superficie (MDS) y considerando áreas ocultas es posible generar ortoimagen verdaderas que no tengan los problemas mencionados anteriormente. Esto no quita que puedan surgir otros problemas:

a. Las ocultaciones que ocurren en las imágenes simples se tienen que rellenar con la combinación de la información situada en varias ortos adyacentes. Pero a menudo no todas las áreas se pueden completar por falta de recubrimientos. b. Los tejados tienen que ser modelados de la forma correcta, ya que de otra forma están distorsionados en las ortoimágenes o se muestran con bordes dentados. Modelar todo tipo de tejados con precisión y en detalle, puede ser complicado si el cálculo es automático o se dispone de poco tiempo.

La generación de ortoimágenes verdaderas tienen que considerar por tanto la proyección ortogonal con un MDS, la detección de áreas ocultas y el relleno de las mismas se hará tomando las partes de imagen perdidas de las ortos colindantes.

Lo importante por tanto es contar con un buen MDS para que los objetos sean proyectados a su verdadera posición geométrica. En la siguiente imagen se puede ver el esquema de la ortoproyección con un MDS, que es una proyección ortogonal.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 36

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 2-19. Proyección ortogonal

El problema es que las áreas ocultas por los objetos humanos no son visibles en la imagen. En la siguiente figura se observa como el tejado del edificio cubre también el área de ocultación en la imagen aérea original.

Los edificios también pueden obtenerse a partir de los datos LiDAR de primer retorno. Se sabe que los tejados son superficies planas por lo que identificando estos tejados, también se identifica la huella del edificio. Si estas áreas no son detectadas por el software de rectificación la ortoproyección la rellenará exactamente con contenido de la imagen, pero de la misma imagen. Esto crea el llamado “efecto fantasma”.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 37

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 2-20. Áreas ocultas en proyección ortogonal

Combinando información de la imagen original con otra obtenida de varias imágenes adyacentes, es posible rellenar áreas ocultas.

De esa forma, a partir de un MDS y utilizando imágenes con recubrimiento desde diferentes vistas (por ejemplo, un bloque de imágenes aéreas) se pueden analizar en el proceso de ortoproyección las posibles zonas ocultas y obtener la información necesaria a partir de otras imágenes disponibles. Este proceso es una tarea compleja ya que deben tenerse en cuenta, no sólo los criterios geométricos (posición de toma de la imagen, inclinación del rayo, etc.) sino también otros elementos radiométricos a fin de establecer las correspondientes líneas de mosaico (sean lines) incorporando procedimientos de suavizado de dichas líneas y de compensación radiométrica de las ortoimágenes generadas a ambos lados de la misma. De otra forma el mosaico carecería de la continuidad geométrica y radiométrica requerida.

Esta ortoimagen que incorpora como fuente de información del terreno, un modelo digital de superficie, y que en su proceso de generación incluye la detección de áreas ocultas, escogiendo la información de otras imágenes disponibles, es conocida como ortoimagen verdadera (true ortho). La denominación como “verdadera” la recibe porque los objetos son verdaderamente proyectados en la dirección paralela y perpendicular sobre el plano de la ortoimagen.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 38

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

De esta forma, en la siguiente figura se puede observar que los edificios se representan con una proyección perfectamente ortogonal (no se ven sus fachadas ni están distorsionados ni dejan áreas ocultas).

Figura 2-21. Izquierda.- Ortofoto convencional (existen zonas ocultas). Centro - Paso intermedio (se aprecia el efecto fantasma). Derecha - Orto verdadera ya corregida (áreas ocultas rellenas con información de ortos adyacentes).

Debido al MDS, además de obtener la ortoimagen verdadera, también se puede restituir directamente sobre el modelo de forma que se digitalicen los edificios, árboles y cualquier elemento que sea de interés para modelizar las ciudades.

Obtención de MDT y MDS

Puesto que el MDS se genera a partir de los datos brutos, se describe a continuación como se obtiene el MDT.

Para obtener el modelo digital del terreno es necesario aplicar una serie de filtros a los datos LiDAR, puesto que en la captura de puntos no se lleva a cabo. Para ello se deben clasificar los puntos en terreno y no terreno. Este problema se plantea como sigue:

 Dado un conjunto de puntos

푃{푝푖(푥, 푦, 푧, 푐), … }

퐷표푛푑푒: 푥, 푦 , 푧 푠표푛 푙푎푠 푐표표푟푑푒푛푎푑푎푠 푒푛 푒푙 푒푠푝푎푐푖표 3퐷

푐 푢푛푎 푒푡푖푞푢푒푡푎 푑푒 푐푙푎푠푖푓푖푐푎푐푖ó푛 푖푛푑푖푣푖푑푢푎푙

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 39

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

 Se ha de buscar una función de clasificación

푓: 푥, 푦, 푧 → 푐

퐷표푛푑푒: 푝푖 ∈ 푃

푐 ∈ 퐶 {terreno, no terreno}

Para esta clasificación es muy útil emplear todos los puntos e información disponibles. Al disponer de zonas donde se solapan dos o más pasadas aumenta la probabilidad de penetración en la vegetación. También aumenta la redundancia y permite rellenar zonas de sombra. La intensidad e información de ecos también es información muy útil.

La obtención de un MDT empleando LiDAR debe estar basada en los puntos correspondientes al último eco, aunque determinadas circunstancias hacen que esta afirmación no pueda considerarse de manera tajante:

 La reflexión de los rayos provoca que la posición del último eco se capture erróneamente por debajo del terreno.  Cambios bruscos del terreno que producen varios ecos para un mismo haz.  El último eco puede corresponderse a veces con vegetación o edificios ya que el láser no puede atravesarlos.

Son varios los diferentes filtros que se pueden aplicar para clasificar los puntos, funcionando bien la mayoría en zonas con baja complejidad (terreno suave, pequeños edificios, vegetación aislada y escasa) y siempre que haya una densidad de puntos adecuada. Destacan los siguientes:

 Filtrado morfológico  Filtrado basado en densificación progresiva  Filtrado basado en la superficie  Filtrado basado en procesos de agrupación y segmentación  Otros métodos de filtrado, que generalmente combinan los anteriores

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 40

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

El comportamiento de estos filtros es sensiblemente diferente en paisajes más complejos, identificando zonas problemáticas para todos los filtrados (terreno en pendiente, bordes, pasos subterráneos…).

Se considera que los filtros basados en densificación progresiva y los filtros basados en superficie obtienen en la mayoría de los casos los mejores resultados.

Tras aplicar el filtro deseado para obtener los puntos del terreno, se genera una malla a partir de estos puntos que representa el terreno sobre el cual se desarrolla nuestra urbe.

2.4. Generación del modelo. Modelado procedural

El modelado procedural se ha impuesto, a lo largo de la última década como una herramienta indispensable para la reconstrucción, representación y visualización de ciudades 3D, y por lo tanto en una herramienta que puede convertirse en clave también para el mundo SIG. Actualmente el modelado urbano se utiliza en aplicaciones como: reconstrucción de mapas y ciudades para herramientas de navegación, contenido digital de ciudades para videojuegos o películas, modelos de simulación para respuestas de emergencias y rutas de evacuación, así como planificación urbana.

Los datos de entrada para este tipo de modelado, desde el punto de vista de las aplicaciones SIG, pueden provenir de diversas fuentes como son los archivos de Open Street Map (OSM). A partir de estos se puede obtener la red de calles y manzanas de una ciudad, para luego dividirlos automáticamente en parcelas a partir de las cuales se generan los volúmenes de edificios que serán procesados a continuación. Otro tipo de datos son los datos catastrales, que contienen información volumétrica de cada edificio de la zona estudiada. En ambos casos, se aplican algoritmos procedurales que procesan una serie de reglas de manera iterativa que definen la estructura de las fachadas de los edificios.

Estas reglas se pueden hacer manualmente mediante herramientas visuales o extraerse a partir de información de los edificios reales, como por ejemplo fotografía capturada desde el terreno o con una cámara oblicua (p.ej. Microsoft Osprey), datos

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 41

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D de un sistema de cartografía móvil (mobile mapping system) o láser escáner terrestre (TLS). Una vez todos los edificios han sido procesados y su geometría generada, los datos resultantes pueden utilizarse para su visualización directa, o para utilizarlos en cálculos como los requeridos en los modelos de física urbana. Un problema a tener en cuenta es la gran capacidad del modelado procedural para generar grandes cantidades de geometría a partir de una entrada pequeña puede resultar en la generación de una gran y excesiva cantidad de geometría. Para solucionarlo, pueden emplearse métodos que controlen el nivel de detalle según las necesidades específicas de cada problema.

El proceso de generación de un modelo urbano se puede resumir como muestra la figura, donde se indica la secuencia de pasos y estructuras necesarias. El primer paso consiste en transformar los datos cartográficos de entrada en una red estructurada de calles, que delimitaran las manzanas o bloques. Estas manzanas son divididas en parcelas, en las cuales se generan los modelos volumétricos de la edificación. Finalmente, el modelado procedural añade los detalles mediante la aplicación de reglas.

Figura 2-22. Pasos para la generación un modelo urbano

ENTRADA DE DATOS

Es importante tener en cuenta que la calidad y fidelidad del modelo 3D resultante, estará muy influenciada por la calidad de la información contenida en las bases de datos cartográficas de entrada. Mientras más información contengan estos datos, y cuanto más precisa sea, menos algoritmos deberán de utilizarse, mejorando así la calidad y fidelidad del modelo 3D resultante.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 42

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

OpenStreetMap

Se trata de una fuente de SIG libre, siendo uno de los inputs más usuales en este tipo de procesamiento. Los archivos OSM de OpenStreetMap siguen el estándar XML para la representación de datos. Para su correcta interpretación es necesario escribir un algoritmo de lectura (parser) que tenga en cuenta los diferentes tipos de datos que estos archivos pueden contener, conservando aquellos que sean relevantes de cara al modelo que se pretende generar. Si por ejemplo solo se quiere un modelo donde aparezcan los edificios, la capa de parada de autobús se puede desechar. En cambio, si se busca una representación completa de la estructura urbana, es probable que si se incluya este tipo de información, añadiendo probablemente un modelo 3D que represente una parada de autobús, pero se ignoren otros elementos como áreas comerciales o de parking por ejemplo. Eso implica un primer nivel de procesamiento donde se filtran los datos que interesan para construir el modelo.

La estructura de estos archivos OSM es sencilla de procesar: se trata de una lista con todos los nodos del mapa, seguida de una lista con todos los caminos del mapa, donde un “camino” puede ser desde un edificio hasta una calle. Estos caminos son polilíneas que no poseen nodos, sino que guardan referencias a los mismos. Esta estructura es ventajosa para la representación visual pero es ineficiente para otro tipo de cálculos como el cálculo de rutas o reconstrucción 3D. Es por esto que los datos deben procesarse en estructuras secundarias. Para el caso de cálculo de rutas lo más eficiente sería guardar para cada nodo la lista de calles que lo cruzan. Para el caso de la reconstrucción 3D es necesario encontrar todos los ciclos mínimos del mapa, que representan las áreas más pequeñas rodeadas por calles: las manzanas. Por lo tanto y debido a esto, de cara a la reconstrucción 3D, el pre-proceso de un mapa culmina con el cálculo de las manzanas, que son luego utilizadas en otras etapas del proceso.

Datos catastrales

Son una importante fuente de información geográfica, sin embargo esta información no siempre está bien estructurada, pudiéndonos encontrar un archivo SIG

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 43

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D con datos claramente incorrectos o introducidos con una codificación incorrecta lo que puede producir un problema para su uso en reconstrucciones 3D. La solución propuesta se basa en un algoritmo de reestructuración 2D semiautomático, que corrige errores y ambigüedades que se presentan comúnmente en datos catastrales corruptos. Es un problema complejo ya que es necesario para identificar elementos imples del archivo de entrada y su conectividad y la estructura del mundo real. La salida del algoritmo suele ser datos urbanos restructurados en una jerarquía de bloques y edificios, de los cuales se puede obtener un modelo 3D realista mediante la extrusión de cada edificio.

Figura 2-23. Reconstrucción del Eixample de Barcelona a partir de datos catastrales

Para la construcción de este modelo hace falta además utilizar el número del piso para cada edificio dentro de los datos catastrales, reconstruyéndolo con un valor estándar para la altura de las plantas. Dichos valores se obtienen como un promedio de un estilo arquitectónico dado, dentro del contexto de una ciudad.

Otros tipos de entradas

En caso de no disponer de información precisa, se puede utilizar una síntesis basada en parámetros de entrada. Para estos casos se suelen utilizar mapas que guíen la reconstrucción (mapas de población, mapas zonales…) y que provean de posibles indicaciones sobre la estructura urbana asociada.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 44

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Un tipo de descripción muy popular consiste en utilizar un sistema basado en regiones, cada una asociada a los diferentes patrones que típicamente se pueden observar en una ciudad: patrón regular (grid), radial u orgánico. A partir de esta información, el sistema procede a crear un conjunto de avenidas mayores, calles y manzanas para continuar con la creación de la ciudad en 3D. La siguiente figura muestra un ejemplo de generación de estructura urbana empleando este sistema.

Figura 2-24. Modelo sintético de estructura urbana. Mapa de patrones con region radial, orgánica y regular. Generación del modelo correspondiente.

GENERACIÓN DE BLOQUES Y PARCELAS

Una vez que se ha creado la red de avenidas y calles, y se determinan las regiones edificadas, los bloques quedan completamente identificados. El siguiente paso consiste en crear las parcelas. En la mayoría de casos es difícil acceder con precisión a la distribución de las parcelas de acuerdo con los lotes, por lo que se utilizan algoritmos de subdivisión automática. Existen para ello diferentes algoritmos que buscan reflejar las divisiones que se pueden encontrar de forma natural en las grandes ciudades. Dos ejemplos son la subdivisión recursiva, que busca recrear ciudades como Nueva York o Buenos Aires; y la subdivisión llamada de tipo Barcelona o París, que simula la típica estructura de una manzana en estas ciudades, donde normalmente existe un patio interior que debe ser modelado para la correcta representación de estas ciudades.

Generalmente para modelar ciudades como Nueva York o Seattle, se utiliza un algoritmo que subdivide iterativamente las manzanas de forma regular, siempre cortando de forma perpendicular a la dirección más larga de la manzana. Esto resulta en la típica estructura rectangular de distribución de edificios de las ciudades americanas, tal y como se muestra en la figura adjunta.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 45

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 2-25. Estructura urbana tipo Manhattan

Por otro lado, en otras ciudades como, por ejemplo, París o Barcelona, pueden observarse otro tipo de manzanas que pueden obtenerse por un proceso de contracción del entorno de la ciudad hasta una tolerancia pre-establecida, siempre asegurando que no haya errores de auto-intersección de las formas. De esta manera el patio interior suele tener una forma muy similar a la de la manzana, un patrón frecuentemente observable en ciudades europeas. La figura 2-24 muestra el resultado de una reconstrucción de este tipo en la ciudad de Barcelona.

Figura 2-26. Estructura urbana tipo Barcelona

GENERACIÓN DE EDIFICIOS PROCEDURALES

A partir de la información de las alturas correspondientes se pueden generar de manera sencilla los volúmenes de las edificaciones mediante operaciones clásicas de extrusión. Lo que se obtiene son los comúnmente llamados mass-models. Si se disponen de imágenes ortográficas de las fachadas, se pueden emplear para obtener un modelo texturizado, que en muchas ocasiones es el tipo de modelo que se emplea

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 46

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D para la visualización (ver figura anterior). Sin embargo este modelo carece de detalles geométricos.

Para la generación completa de edificios, se suelen emplear reglas gramaticales. La aplicación de las reglas se basa en su evaluación secuencial, tomando para cada iteración las formas geométricas resultantes de la iteración anterior, siendo la iteración inicial la que recibe el modelo volumétrico. Los principales comando que se pueden emplear son:

 Subdiv, que realiza una subdivisión de la forma actual en múltiples formas.  Repeat, que realiza subdivisiones de manera repetida de una forma geométrica (se puede emplear por ejemplo para ir creando plantas con una determinada altura dentro de un edificio hasta completar la altura máxima de este último).  Component Split, que puede crear nuevos componentes (por ejemplo caras de un poliedro o aristas) a partir de una forma geométrica. Es útil para dividir los edificios en fachadas y tejados por ejemplo.  Insert, que reemplaza geometría predefinida en el predecesor correspondiente.

El proceso de producción de un determinado conjunto de reglas se puede considerar como un gráfico dirigido acíclico (DAG), donde cada nodo representa una operación aplicada a su entrada de geometría, siendo los nodos de hoja los detalles finales de la geometría a remplazar. La siguiente figura muestra un ejemplo de edificio procedural representado como un grafo:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 47

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 2-27. Grafo que representa un conjunto de reglas procedurales y el resultado final del edificio

Una representación de grafos presenta la ventaja de que permite trabajar con una interfaz visual más intuitiva, en contraste con la edición clásica textual de la codificación de reglas.

Otra de las características es el uso de técnicas corriente de edición, como pueden ser las típicas de copiar y pegar, aplicadas en este caso a los métodos procedurales. El usuario puede generar un edificio nuevo o cambiar componentes de uno ya existente, a partir de la reutilización de reglas ya configuradas que pueden representar un estilo arquitectónico particular. En la siguiente figura se muestra un ejemplo de un edificio generado a partir de 3 estilos completamente diferentes:

Figura 2-28. Edificio obtenido a partir de 3 edificios procedurales diferentes.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 48

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

RETOS ACTUALES

A pesar de que las técnicas procedurales permiten generar de manera eficiente grandes modelos urbanos con buena cantidad de detalles, en función de la aplicación que se le desee dar la modelo es aconsejable definir el nivel de detalle del mismo, y los elementos geométricos que se incorporan. Así, normalmente se incorporan simplificaciones, ya que para la mayor parte de las aplicaciones no es necesario el nivel de detalle proporcionado por los sensores de captura de información actuales, permitiendo un manejo más ágil de los modelos de grandes dimensiones.

Una solución clásica del modelado para los grandes modelos es introducir técnicas de nivel de detalle, que utilizan parámetros de calidad para reducir la complejidad. Los criterios empleados para simplificar pueden estar basados en la distancia a puntos de interés del modelo o a estructuras semánticas de los edificios de los que resulte de interés conservar. De esta forma se controla de forma automática la generación de geometría, evitando una sobrecarga de datos.

Figura 2-29. Modelo urbano procedural con nivel de detalle utilizando un criterio de distancia a partir de la esfera roja 2.5. Aplicación de los modelos urbanos 3D

Los modelos urbanos hasta ahora descritos resultan ser de gran ayuda en diversos ámbitos como son el planeamiento urbano, el diseño de infraestructuras y edificios, la gestión de emergencias, estudios de eficiencia energética o la realización de mapas de ruidos entre otros.

A continuación se muestran distintas iniciativas llevadas a cabo por diferentes organismos y administraciones públicas que sirven como ejemplo para ilustrar las

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 49

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D múltiples aplicaciones que los modelos urbanos en tres dimensiones son capaces de aportar cuando se construyen desde la perspectiva integradora, actuando como una representación realista con una mayor capacidad de análisis.

 Análisis de la contaminación por ruido en el estado de North Rhine – Westphalia (Alemania). La directiva de Ruido Ambiental de la Unión Europea 2002/49/EG obliga a los estados miembros a determinar cada 5 años la emisiones sonaras de las principales carreteras y vías férreas, aeropuertos, lugares de actividad industrial y aglomeraciones urbanas, además de documentas los resultados a mediante mapas de ruido. Esta directiva plantea unos altos requisitos, como tener un gran número de datos geográficos a nivel estatal, asó como datos georreferenciados y temáticos en 3 dimensiones (terrenos, edificios, ferrocarriles, carreteras). Para proporcionar esta considerable cantidad de datos 3D a nivel estatal, el estado de North Rhine-Westphalia (NRW) sigue un concepto de implementación moderno, el uso sostenible y ampliación de la infraestructura de datos espacial GDI NRW. NRW proporciona por primera vez datos geoespaciales en 3D a nivel estatal como elementos en el estándar CityGML de OGC web features services (modelos de edificios en 3D con un nivel de detalle LoD1, carreteras en 3D y datos de ferrocarril) y un modelo digital del terreno con un paso de malla de 10 m a través de OGC Web Coverage Service. http://www.ikg.uni- bonn.de/uploads/tx_ikgpublication/071105_ec_gi_gis_fullpaper_czerwins ki.pdf

Figura 2-30. Modelización de una fuente de emisión de ruido usando datos CityGML en 3D

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 50

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 2-31. Mapa de ruido generado a partir de datos CityGML

 Creación de un modelo 3D de la ciudad de Berlín (Alemania) con información semántica asociada correspondiente tanto a datos catastrales como al potencial solar de los tejados de los edificios modelados (posibilidad de instalar paneles fotovoltaicos, producción de electricidad estimada, reducción de emisiones de CO2, inversión a realizar,…)

http://www.businesslocationcenter.de/en/berlin-economic-atlas

Desde esta página se puede explorar Berlín tanto en 2 como en 3 dimensiones. Berlín es la primera ciudad en Alemania de la que cualquier usuario de Internet puede obtener un modelo realístico de gran escala. A través de este esquema de atlas económico, el usuario puede examinar mapas, mostrar edificios en 3D y obtener información detallada sobre el entorno urbano de Berlín.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 51

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 2-32. Atlas económico de Berlín

Para crear el modelo, unos 540000 edificios en un área en torno a 890 km2 fueron medidos mediante fotogrametría aérea, siendo sus tejados capturados mediante LIDAR. Adicionalmente también se crearon unos 80 modelos detallados de edificios emblemáticos, algunos de los cuales pueden visitarse incluso en su interior (Olympic Stadium, Sony Center…).

Junto con esta información de carácter geométrico, el modelo ha sido enriquecido al incorporarle información sobre la economía de Berlín y su infraestructura. Es importante tener en cuenta que este modelo ha sido creado con objetivo no comercial, sino de gestión de la ciudad, y para posibilitar el desarrollo de nuevas aplicaciones que aporten valor añadido.

http://www.businesslocationcenter.de/en/berlin-economic-atlas/the- project/project-examples/solar-atlas

Un ejemplo de aplicación lo constituye, por ejemplo, el atlas solar en el que se muestra el potencial solar de cada edificio en la ciudad en imágenes claras en 2D y 3D. Propietarios e inversores pueden utilizarlo para saber si el tejado de un edificio es adecuado para una instalación solar y si la inversión será amortizada. Este atlas proporciona información clave a través de una ojeada como puede ser la energía potencial de salida, reducciones en emisiones de CO2, y costes de inversión.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 52

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 2-33. Atlas solar de Berlín

3. Aplicación de la Metodología

3.1. Zona de estudio

La zona elegida para ser modelizada en 3D se trata de la Plaza de España y sus alrededores, encontrándose situada en Madrid en las siguientes coordenadas UTM:

X=439589.500 m Y=4474971.320 m

A continuación se muestra una imagen de Google Earth donde puede ubicarse la zona de trabajo, la cual está marcada mediante un polígono.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 53

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-1. Zona elegida a modelar

Destacan en los alrededores, por su altura, dos edificios de hormigón, la Torre de Madrid (1957) y el Edificio de España (1953). De esta plaza salen las calles de Gran Vía, Princesa y la Cuesta de San Vicente. Se encuentra también junto a la calle de Bailén, lo que la sitúa junto al Palacio Real de Madrid.

3.2. Instrumentación y software empleado

En este apartado se describen los instrumentos y programas empleados para realizar el presente trabajo.

A) Instrumentación

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 54

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

 Ordenador portátil Acer V3-572G-70ES

- 8Gb de Ram - Intel Core i7-4510U 2.0 GHz - NVIDIA GeForce 840M

B) Software  ArcGIS: Es sin duda el referente internacional en el ámbito de los Sistemas de Información Geográfica. Se trata de un software comercial desarrollado y distribuido por ESRI. Sirve para administrar datos, crear mapas y llevar a cabo análisis espaciales. Permite el tratamiento de todo tipo de información geográfica, ya sean imágenes, archivos vectoriales o raster, o nubes de puntos. El software permite el obtener una versión de prueba gratuita con limitaciones de uso en cuanto al tiempo, pero con funcionalidad completa.  CityEngine: desarrollado también por ESRI, se caracteriza por el empleo de reglas procedurales para la generación de entornos urbanos. Con él se puede utilizar información geográfica en 2D para generar modelos urbanos en 3D. Puede obtenerse una versión de prueba desde su página web, la cuál ha sido empleada para realizar este Trabajo de Fin de Máster.

3.3. Desarrollo metodológico

3.3.1. Obtención de los datos

Como ya se ha explicado en el apartado de metodología, se pueden emplear técnicas geoespaciales como la Fotogrametría y LiDAR para obtener los datos necesarios para modelizar una ciudad. El coste de planificar y llevar a cabo un vuelo

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 55

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D es excesivo para el fin que se persigue con este Trabajo de Fin de Máster por lo que se ha decidido recurrir a datos que se encuentren disponibles para su descarga en la red.

Estos datos pueden obtenerse desde diferentes fuentes. En la página web del IGN se pueden obtener todo tipo de datos que se encuentran accesibles al público previo registro para poder acceder a su centro de descargas. También se encuentran disponibles sus metadatos, de manera que podamos saber en qué fecha se obtuvieron y de qué forma, además de hacernos una idea de la precisión que tienen estos.

Figura 3-2. Web del IGN

En concreto se han obtenido de esta página los siguientes datos:

 Ortofoto PNOA de máxima actualidad: en formato ECW, y sistema geodésico de referencia ETRS89 y proyección UTM 30 N. Su unidad de distribución es y descarga es la hoja del MTN50 (Mapa Topográfico Nacional 1:50000), resultado de componer un mosaico con las ortofotos Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 56

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

correspondientes a cada hoja del MTN50. La hoja correspondiente a la zona elegida es la 0559. En el archivo xml de metadados podemos ver algunos datos interesantes como:

- Fecha de toma: 09-03-2015 - Resolución espacial: 0.25 m - Ortofotos con las que se ha formado el mosaico

Figura 3-3. Ortofoto PNOA

 LiDAR: en formato LAZ (formato de compresión de ficheros LAS). Se distribuye en ficheros digitales con información altimétrica de 2x2 km de extensión. Las nubes de puntos han sido capturadas mediante vuelos con sensor LiDAR con una densidad de 0,5 puntos/m2, y posteriormente clasificadas de manera automática y coloreadas mediante RGB obtenido a partir de ortofotos del PNOA con tamaño de pixel de 25 o 50 cm. Los archivos descargados se encuentran en el sistema de referencia ETRS89 y en la proyección UTM 30 N. Las alturas de los puntos son ortométricas. A partir del filtrado de la nube de puntos LiDAR clasificada se puede obtener un modelo digital del terreno.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 57

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-4. Datos Lidar

 MDT05: en formato ASCII. Se trata de un modelo digital del terreno con paso de malla de 5 metros y con la misma distribución de hojas que el MTN50. El sistema de referencia de estos datos es el ETRS89, proyección UTM huso 30 N. Según la hoja de que se trate, este MDT se ha obtenido de una de las dos siguientes formas: por estereocorrelación automática de vuelos fotogramétricos del PNOA con resolución de 25 a 50cm/pixel, revisada e interpolada con líneas de ruptura donde fuera viable, o bien por interpolación a partir de la clase terreno de vuelos LiDAR del PNOA.

Figura 3-5. MDT del IGN

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 58

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

La sede electrónica del catastro dispone de un servicio de descarga de cartografía vectorial en formato shape, a través del cual se puede acceder a la siguiente información dentro de una población:

 Elementos puntuales (árboles, señales…)  Elementos lineales  Huellas de los edificios  Calles

Para acceder a esta información es necesario un certificado o DNI electrónico.

Figura 3-6. Sede electrónica del catastro

3.3.2. Preparación de los datos

Antes de empezar a trabajar con CityEngine es necesario preparar los datos. Para ello hay que crear una geodatabase, la cual es una colección de datos geográficos de varios tipos y sirve como marco de administración y almacenamiento de datos nativo para ArcGIS. Proporciona un sistema de almacenamiento de datos escalable y un sistema de administración con mejor integridad, carga, recuperación y seguridad de datos.

CityEngine se basa en 3 ingredientes: la geometría de los elementos, los atributos de los elementos, y reglas procedurales. Mientras más detalle tenga cada

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 59

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D elemento, mayor será la complejidad y precisión con respecto al mundo real del contenido 3D generado.

Este programa utiliza el fichero de base de datos geoespacial de Esri como su formato de almacenamiento nativo. Esto significa que se puede emplear cualquier dato de tipo vector geo-espacial, tal como parcelas, huellas de edificios, y redes de calles. El modelo 3D de ciudades provee un esquema personalizado para la base de datos geo-espacial que coge elementos existentes en 2D y usa superficies derivadas de LiDAR de forma que se convierten en 3D para poder realizar visualizaciones y análisis.

En primer lugar, el proceso se inicia con la creación de un proyecto nuevo en ArcMap y se ha creado una base geo-espacial nueva, renombrándola como “PuertadeEspaña” y estableciéndola como la base geo-espacial por defecto. Esta localización es usada en caso de añadir nuevos datos y para guardar los datos resultantes creados tras la edición y operaciones de geoprocesamiento. La base de datos geo-espacial por defecto se sincroniza con el espacio de trabajo actual, de modo que todas las salidas de las herramientas y modelos que se empleen son guardadas en esta localización por defecto.

Para agilizar el procesado de los datos, se puede dibujar una pequeña zona de interés mediante un polígono, recortando el resto de capas de manera que se ajusten a esta zona. La herramienta clip es válida para esta tarea y se encuentra en la caja de herramientas de análisis tal y como se ve en la imagen:

Figura 3-7. Herramienta clip

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 60

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Como elemento de recorte se puede introducir una capa con un polígono que dibujado que recubra toda la zona de interés.

Figura 3-8. parámetros usados con la herramienta clip

Se ha empleado la herramienta clip con todas las demás capas (ortoimagenes, árboles, calles, parcelas, huellas de edificios…) para ajustarse a la zona de interés.

El siguiente paso es importar el esquema CIM (City Information Model), que creará todas las clases de elementos, relaciones y tablas. Este fichero CIM es el estándar con el que trabaja CityEngine y está basado en CityGML. Puede exportarse posteriormente a CityGML sin problema.

Se ha creado una nueva base de datos geo-espacial, llamándola “Madrid_final”. Haciendo clic derecho sobre ella, se pulsa en importar y se selecciona “XML workspace document”, seleccionando importar el esquema 3DCITYINFOMODEL.xml solamente. Este fichero XML puede obtenerse en la página web de CityEngine.

En la ventana de catálogo se pueden observar las nuevas clases de elementos, relación y tablas creadas:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 61

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-9. Elementos, relaciones y tablas del esquema CIM

Esta base de datos geo-espacial almacena elementos y sus relaciones para modelizar datos de ciudad a múltiples escalas y dentro de 3 principales temas:

 Entorno de construcción: huellas de los edificios, modelos de edificios, elementos interiores, instalaciones…  Entorno legal: propiedad del suelo  Entorno natural: usos del suelo

Este modelo de información de ciudad 3D es compatible como CityGML, siendo fácil de rellenar con nuestros datos.

Para rellenar este modelo, hay que cargar los datos elegidos en cada clase de elementos de la base de datos Madrid_final, haciendo clic con el botón derecho sobre ellas y pulsando “Load data”.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 62

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-10. Cargando los elementos en el esquema

En la siguiente tabla aparecen los atributos del esquema 3DCIM. Algunos de estos son rellenados automáticamente con los atributos de nuestra capa. Los señalados como “none” podemos indicarlos nosotros mismos.

Figura 3-11. Atributos de la capa Building dentro del esquema

Dependiendo de los datos, unos campos estarán rellenados y otros no. Estos campos listados dentro del 3DCIM están ahí para crear ciertos productos. Es posible también que nuestros contengan más información que la que presenta el esquema. En ese caso habría que añadir aquellos campos que fueran necesarios al esquema antes de importar nuestros propios datos.

Este proceso ha de llevarse a cabo con las capas de árboles, calles y edificios.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 63

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Una componente esencial de cualquier mapa 3D es un modelo detallado del terreno. Este provee de una “textura” para el escenario de la ciudad, pero también determina el emplazamiento vertical de todos los datos GIS basados en el terreno: edificios, cobertura del suelo, mobiliario urbano, y otras instalaciones. Para obtener el nivel de precisión requerido para un modelado del terreno realístico, es necesario tener datos LiDAR clasificados de alta resolución.

Para el propósito de modelar el terreno y extraer elementos, hay 3 tipos de superficies básicas usadas en los modelos 3D de ciudad. Estas superficies raster se crean basándose en diferentes clasificaciones del retorno en los datos LiDAR.

1. Modelo Digital del Terreno (MDT). Se trata de una superficie raster que representa la elevación del terreno desnudo, sin estructuras ni vegetación. Se utiliza como superficie de elevación base en las escenas 3D. Se utiliza el retorno del suelo de los puntos (último retorno) en su creación. 2. Modelo Digital de Superficie (MDS). Es una superficie raster que representa la elevación de todas las estructuras y elementos naturales en el terreno. Es el mismo tipo de superficie que obtendríamos si “envolviéramos” el paisaje. Se usan los puntos de primer retorno en su obtención. 3. Modelo Digital de Superficie Normalizado (MDSn). Esta superficie se usa para modelar la altura de las estructuras y vegetación sobre la superficie del terreno. Es la diferencia entre el MDT y el MDS.

푀퐷푆푛 = 푀퐷푆 − 푀퐷푇

Como ya se ha comentado anteriormente, estas superficies pueden extraerse fácilmente a partir de los datos lidar. Para ello se sigue el siguiente proceso:

Crear el Crear el MDT a partir MDS a partir Obtener la Importar los de los de puntos de elevación de datos LiDAR puntos de primer los edificios ultimo retorno retorno

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 64

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Importar los datos LiDAR es una tecnología de sensor remoto relativamente nueva que nos permite recoger muestras muy densas de puntos de elementos en 3D. Esta ha evolucionado hasta convertirse en una fuente común de datos en los sistemas de información geográfica. Estas enormes colecciones de puntos del mundo real son típicamente almacenadas en ficheros LAS. Cada punto LiDAR puede tener atributos adicionales como intensidad, códigos de clase, y valores de color RGB de los que se puede hacer uso en diferente software

LAS es el formato nativo que emplea ArcGIS. Puesto que los ficheros LiDAR descargados del IGN se encuentran en formato LAZ, es necesario descomprimir estos primero. Para ello se puede emplearse el programa LASTOOLS, en concreto la herramienta laszip.exe.

Una vez descomprimidos pueden ser importados en ArcGIS sin ningún problema, siendo buena idea crear un fichero LASd que recoja todos los ficheros LAS que interese utilizar en uno solo para mayor comodidad.

La nube de puntos se muestra tal y como se ve en la imagen:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 65

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-12. Nube de puntos lidar obtenida del IGN

Para trabajar con estos datos en ArcMap es necesario activar primero las extensiones 3D Analyst y Spatial Analyst, así como activar la barra de herramientas LAS Dataset.

Dentro de la barra herramientas se pueden aplicar diversos filtros:

Figura 3-13. Filtros para datos lidar en ArcGIS

Aplicando un filtro para seleccionar los puntos perteneciente al terreno nos queda lo siguiente:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 66

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-14. Puntos pertenecientes al terreno

Con estos puntos se puede obtener el modelo digital del terreno empleando la siguiente herramienta de conversión:

Figura 3-15. Herramienta para obtener el modelo digital del terreno

Se han establecido los siguientes parámetros:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 67

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-16. Parámetros empleados para obtener el MDT

En el campo valor se indica que atributo de los datos LiDAR será utilizado para generar el raster. En este caso nos interesa la elevación, aunque también podrían utilizarse con otros fines la intensidad o el valor RGB.

En cuanto al tipo de interpolación se opta por la triangulación. Esta interpolación consiste en determinar el valor de cada celda del raster de salida. El método de triangulación utiliza una aproximación basada en TIN permitiendo acelerar el tiempo de procesado mediante la reducción de los datos usando la técnica de la ventana de muestreo. En este caso se opta por interpolar con el vecino más próximo.

En la siguiente imagen se muestra el MDT obtenido:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 68

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-17. MDT obtenido a partir de datos LiDAR

Para crear el modelo de superficie solamente hay que cambiar el tipo de filtrado de los puntos LiDAR iniciales, seleccionando aquellos que son de primer retorno:

Figura 3-18. Filtrado de puntos para obtener un MDS

Los parámetros utilizados en la herramienta LAS Dataset to Raster son algo diferentes en esta ocasión:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 69

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-19. Parámetros empleados para obtener el MDS

El enfoque binning proporciona un método de asignación para la determinación de cada celda de salida utilizando los puntos que caen dentro de su alcance, junto con un método relleno de huecos para determinar el valor de las celdas que no contienen ningún punto.

Con estos parámetros se busca el punto de máxima elevación dentro de cada celda, y si rellenan los huecos interpolando con el vecino más próximo.

El MDS obtenido se muestra a continuación, pudiendo apreciarse claramente las zonas edificadas.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 70

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-20. MDS obtenido

Al crear el MDS, puede haber algunos elementos creados debido a problemas del sensor y otros errores en el procesado. Idealmente los datos LiDAR no contienen este tipo de errores. En caso de haberlos, la herramienta “Focal statistics” puede quitar valores de elevación erróneos.

Los parámetros empleados son los siguientes:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 71

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-21. Eliminación de errores

Esta herramienta calcula una estadística de valores dentro de una vecindad especificada alrededor de la celda de entrada. Se ha empleado un rectángulo de dimensiones 3x3, un buscando el mínimo valor.

Tras estos pasos seguidos se obtiene el modelo de la superficie desnuda y de los elementos sobre la superficie. El siguiente paso es crear una superficie normalizada con las alturas absolutas de los elementos sobre el terreno estableciendo la elevación de este último a un estándar de cero. Para hacer esto hay que sustraer el MDT del MDS.

La herramienta “minus” es la que nos permite hacer esto, seleccionando el MDS como superficie 1 y el MDT como superficie 2.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 72

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-22. Obtención del modelo de superficie normalizado

El resultado obtenido es:

Figura 3-23. Modelo de superficie normalizado obtenido

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 73

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

A partir de este MDSn, se pueden determinar las alturas de los edificios. Para ello se ha creado una herramienta que utiliza las huellas de los edificios para determinar su altura basándose en el modelo digital de superficie normalizado.

Figura 3-24. Parámetros para calcular la altura de los edificios

Al abrir ahora la tabla de atributos de la capa Building, se puede observar que el campo altura total ha sido rellenado.

Figura 3-25. Altura de los edificios (Total height)

Realizado este último paso, los datos ya están listos para ser importados en CityEngine.

Este programa puede leer los siguientes formatos: .tif, .jpeg, .png, y .img. Para importar el terreno hay que convertir el MDT a formato TIFF y ajustarlo al área de interés. Este MDT será utilizado como mapa de alturas al crear el terreno en

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 74

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

CityEngine. También se puede hacer lo mismo con la ortofoto descargada desde el IGN y usarla como textura para el terreno.

Para ello se puede utilizar la versión raster de la herramienta clip:

Data Management tools > Raster > Raster Processing

Figura 3-26. Herramienta para recortar el terreno

De esta manera se obtienen el MDT y la ortofoto en formato tif.

3.3.3. Modelado de la ciudad en 3D

Para modelizar nuestra ciudad en 3D a partir datos geográficos se ha utilizado el programa CityEngine. La principal componente de este programa es el proyecto. Cada proyecto contiene un conjunto de carpetas que contienen todos los datos, reglas, modelos y otra información.

Lo primera tarea a realizar por tanto con el programa es crear un nuevo proyecto. En este caso Madrid_Puerta de España:

File > New > CityEngine Project

Figura 3-27. Nuevo proyecto CityEngine

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 75

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Creado el proyecto, el siguiente paso es crear una nueva escena

Figura 3-28. Creación de una nueva escena

Se le asignará un nombre y por supuesto el sistema de coordenadas de los datos empleados.

Figura 3-29. Configuración de la escena

En esta nueva escena se pueden cambiar tanto la cámara como los parámetros de intensidad solar y ambiental.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 76

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-30. Parámetros de intensidad solar

Para añadir el terreno a la escena a partir de los datos que han sido preparados anteriormente, se añade el MDT y la ortoimagen recortadas a la carpeta maps del proyecto. Arrastrando el fichero MDT a la ventana de vista de escena aparece la siguiente ventana donde se asigna la ortoimagen como textura para el terreno. Como se puede observar el fichero esta georreferenciado.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 77

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-31. Importación del terreno

Añadido el fichero, la ventana de vista queda de la siguiente manera:

Figura 3-32. Terreno importado

A continuación, el siguiente paso sería añadir la información geográfica que anteriormente fue guardada en una base de datos siguiendo el esquema 3DCIM. Para ello se guarda la base de datos en la carpeta “Data” del proyecto, y se arrastra esta hasta la ventana de vista. Aparece un menú para importar los datos donde se pueden seleccionar las capas a importar:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 78

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-33. Importación del modelo 3DCIM

Siendo las capas de edificios, árboles y calles las que interesan para crear el modelo urbano. Al importar los datos se observa un problema, y es que las capas no están alineadas puesto que los datos importados no tienen información de elevación.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 79

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-34. Capas no alineadas

Para solucionar esto es necesario alinear las capas al terreno. La capa de calles se alinea mediante la opción Align graph to terrain, eligiendo como mapa de alturas el MDT importado anteriormente.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 80

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-35. Alineación de la red de calles

Hecho esto, se puede emplear la herramienta “Cleanup Graph” para limpiar la red de vectores de calles de posibles errores, arreglando las intersecciones.

Para alinear los árboles se emplea la opción “Align shapes to terrain”, y se dejan los parámetros igual que en el caso anterior. Los edificios se alinean con la misma herramienta que los árboles, pero indicando en la función de alineación que las formas sean trasladadas a la media.

Por último se emplea la función “Align terrain to shapes” de forma que los objetos se impriman correctamente en el terreno, o el terreno se adapte a los objetos. Para ello se seleccionan las 3 capas.

Figura 3-36. Alineación del terreno

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 81

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-37. Parámetros para alinear el terreno

Finalmente todas las capas quedan alineadas

Figura 3-38. Escena con todas las capas alineadas

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 82

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Cuando el modelo 3D está correctamente importado, es el momento de empezar a aplicar reglas procedurales para generar los edificios, calles y vegetación.

Estas reglas pueden ser importadas desde otros proyectos o crearse desde cero. En el caso de los edificios se ha creado una nueva regla.

Figura 3-39. Creación de una nueva regla CGA

Normalmente los atributos de los edificios son definidos al principio del fichero de regla (aunque pueden ponerse en cualquier parte). Estos atributos son usados a través de todo el conjunto de reglas del fichero y pueden modificarse además fuera de este desde el inspector. Atributos típicos pueden ser la altura total del edificio y la altura de cada planta. attr totalHeight = 10 attr floorheight = rand(4,5)

La primera regla suele llamarse lot, y se emplea para extruir la huella del edificio. Lot--> extrude(totalHeight) Mass

A continuación lo ideal es dividir el modelo extruido en sus distintas fachadas aplicando la componente Split. Mass --> # divide el edificio en tejado y caras laterales comp(f){top : Roof | side : Facade}

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 83

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

El resultado de aplicar esta regla es un edificio dividido en diferentes caras. También se podría introducir una fachada frontal que fuera diferente de las laterales, y donde hubiera una entrada.

Las fachadas y tejado también pueden modelarse. Para modelar una fachada se procede de la siguiente forma: primero, la fachada puede descomponerse en pisos. A continuación, los pisos pueden ser divididos en compartimentos (subdivisiones del piso que pueden corresponderse con habitaciones por ejemplo). Un compartimento típico puede consistir en un muro y ventanas.

Figura 3-40. Subidivisiones del edificio

Habría que definir a continuación las reglas “floor” y “Tile”. Para simplificar, se puede utilizar una textura que se repita a lo largo de toda la fachada en función del número de pisos. Facade --> setupProjection(0, scope.xy, 8*actualTileWidth, 8*actualFloorHeight) texture(randomFacadeTexture) projectUV(0)

Las texturas se declaran al comienzo del fichero, en este caso mediante una constante que coge una textura aleatoria dentro de una carpeta donde tenemos todas.

const randomFacadeTexture = fileRandom("*facade_textures/f*.tif")

Por último se añade la regla del tejado. Con esta regla se pretende asignar a los tejados una textura desde la ortofoto.

Roof --> Rooftex

Rooftex --> setupProjection(0, world.xz, mapdimension_x, mapdimension_z) set(material.colormap, "Orto_JPG.jpg")

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 84

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D projectUV(0) translateUV(0, -mapoffset_x/mapdimension_x, -mapoffset_z/mapdimension_z) scaleUV(0,1,-1)

Este fichero puede consultarse en el apartado de anexos, así como las reglas empleadas para generar las calles y los árboles.

Una vez creadas o importadas estas reglas, solo hay que asignarlas. Para ello se han de seleccionar todos los elementos de una misma capa para a continuación asignarles el fichero .cga.

Figura 3-41. Seleccionando todos los objetos dentro de una misma capa

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 85

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-42. Asignando el fichero .cga

Una vez asignados todos los ficheros de reglas, el resultado obtenido es el siguiente:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 86

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-43. Escena finalizada

Un modelo 3D de ciudad que conforma una base de datos con numerosos atributos como el nombre de la calle, o el tipo de acceso o pavimento. Se pueden cambiar diversos parámetros gracias a los ficheros de reglas generados como son el número de farolas en las calles, o el tipo de intersección (glorietas, cruces…).

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 87

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-44. Parámetros de las intersecciones

Creación de la escena web

Esta representación visual en 3D puede compartirse a través de la red mediante una escena web, la cual se trata de un formato optimizado que puede visualizarse a través de CityEngine o de ArcGIS Online.

Se pueden mostrar fácilmente localizaciones específicas en la escena que queremos que el observador vea mediante la creación de marcadores.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 88

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-45. Creación de marcadores

Cuando el observador observe la escena web irá desplazándose de un marcador a otro, o libremente si lo desea.

Para crear la escena se seleccionan todos los objetos y se exportan al formato escena web de CityEngine.

Figura 3-46. Exportando la escena web

Se puede observar como el modelo puede exportarse en otros formatos muy conocidos como Wavefront OBJ o Autodesk FBX. El modelo exportado en estos formatos se incluye en el cd proporcionado con el presente trabajo.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 89

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-47. Capas exportadas a la escena web

Ya creada la escena web, esta puede compartirse a través de ArcGIS Online, siendo necesario tener una cuenta registrada donde subir el contenido creado con el programa.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 90

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-48. Compartiendo la escena web

La escena web obtenida puede visualizarse mediante el siguiente enlace:

http://arcg.is/1lPmrXz

En ella pueden consultarse los atributos que posee cada elemento de la escena así como activar o desactivar las diferentes capas.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 91

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-49. Escena web

Puede observarse como quedaría el nuevo edificio de oficinas (el edificio blanco) que se ha modelado a través de código en CityEngine, y podría llegar a realizarse incluso un estudio de sombras para ver la sombra que proyecta sobre el parque (importante para saber cuanta luz recibe la vegetación) o un análisis de visibilidad para ver como afecta al resto de edificios de alrededor.

Figura 3-50. Edificio nuevo generado mediante métodos procedurales

También pueden observarse algunos edificios emblemáticos como la Torre de Madrid o el Edificio España.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 92

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-51. Edificio España y Torre de Madrid

3.3.4. Aplicación del Modelo. Análisis solar

Una de las aplicaciones que se le pueden dar al modelo obtenido, es el análisis solar en edificios. Para ello es necesario separar los tejados en una capa aparte de las paredes. Partiendo del proyecto anterior se puede asignar una nueva regla procedural a los edificios donde se haga esta separación.

El primer paso es seleccionar todos los edificios y limpiar las formas para corregir posibles errores. Seguidamente se usa la función Shapes > Separate Faces de manera que los bloques queden divididos en caras.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 93

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-52. Limpiando las formas

Tras esto se ha creado una nueva regla procedural la cual se ha asignado a los edificios: attr GetTheRoofs = true attr totalHeight = 10

GetRoofs --> extrude(totalHeight) alignScopeToAxes() comp(f){ vertical: Rest | all : Roofs}

Roofs --> case GetTheRoofs: texture("") color(1,1,0) Roofs. else:

NIL

Al pulsar el botón de ocultar/mostrar formas solo quedan visibles los tejados en color amarillo.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 94

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-53. Tejados extraídos

Estos tejados pueden ser exportados a una nueva base de datos, la cual se utilizará posteriormente en ArcGIS para hacer el análisis. File > export models

Figura 3-54. Exportar como geodatabase

Los muros también pueden ser extraídos. Activando las formas de nuevo y cambiando el parámetro GetRoofs de verdadero a falso.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 95

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-55. Extracción de los muros

Estos muros son exportados al igual que los tejados como una capa individual.

Ahora que ya están separados los muros de los tejados, el siguiente paso es calcular la radiación solar. Para llevar a cabo este análisis, son necesarios los parámetros de proporción dispersa (D) (fracción de radiación solar recibida indirectamente a través de su dispersión en las nubes) y transmitividad (fracción de radiación solar directa que pasa a través de la atmósfera). Debido a la complejidad de la variación atmosférica, se emplean valores estimados basados en tendencias históricas para una región. El proceso explicado a continuación se basa en métodos desarrollados por el Dr.James M. Dyer, Profesor de Geografía en la Universidad de Ohio.

Para calibrar estos parámetros atmosféricos se siguen los siguientes pasos:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 96

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Obtener estimaciones de radiación

Crear entradas para la herramienta de radiación solar en nuestra zona de estudio

Determinar los valores de proporción difusa y transmitividad

Ejecutar la herramienta de raciación solar

Las estimaciones de radiación se pueden obtener desde diversas fuentes, habiendo elegido en este caso la siguiente página web: http://www.soda- is.com/eng/services/services_radiation_free_eng.php

En esta página se encuentra disponibles varios datos de manera gratuita. En este ejemplo se han elegido los datos HC1month de la columna plano horizontal (radiación global).

Figura 3-56. Datos de radiación global

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 97

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Estos ficheros contienen los siguientes parámetros:

Figura 3-57. Parámetros del fichero de radiación global

Los últimos datos disponibles datan del año 2005, y se han introducido las coordenadas de la zona de trabajo.

Figura 3-58. Coordenadas para los datos de radiación

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 98

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Se obtiene un fichero que puede ser abierto con Excel para consultar los datos. Lo interesante para este caso es la columna Monthly sum donde se encuentran los valores GHI. Estos valores se han introducido en una hoja de excell que calcula los mejores valores D y T:

Figura 3-59. Valores D y T obtenidos

Tras realizar esta operación, es necesario crear un elemento de tipo punto para el lugar donde se realizará el análisis de radiación solar. Esto se realiza con la herramienta ArcCatalog, haciendo click derecho sobre la base de datos creada New > Feature Class, y estableciendo el tipo de elemento como punto y el sistema de referencia como ETRS89 UTM zona 30 N.

Dentro de esta capa se crea un nuevo punto introduciendo las coordenadas latitud y longitud de la zona elegida en grados decimales.

A continuación se pueden calcular las condiciones atmosféricas mediante una herramienta previamente creada en Arcgis, introduciendo el punto de radiación solar y el MDT.

Figura 3-60. Parámetros introducidos en la calibración atmosférica

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 99

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Se obtiene un fichero .dbf. Al abrirlo en Excel aparecen los valores calculados por la herramienta, los cuáles han de pegarse en la hoja Excel anterior de la siguiente manera:

Figura 3-61. Parámetros de calibración atmosférica

Al final de la hoja de cálculo los valores D y T son calculados automáticamente para cada mes:

Figura 3-62. Valores D y T

Estos datos se leen de la siguiente forma: D4T6 = proporción difusa de 0.4 y transmitividad de 0.6.

Después de calcular estos valores, es cuando se ejecuta la herramienta de radiación solar, donde se introducen los edificios y los árboles, así como el MDT. Se puede observar cómo se han introducido los valores D y T correspondientes a cada mes.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 100

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-63. Herramienta de radiación solar

Se obtiene el siguiente resultado en el cual se observa que los valores de radiación más altos (color anaranjado) están asignados a la parte alta de los edificios y las copas de los árboles, mientras que los valores bajos (color azul) son asignados a las zonas de sombra.

Figura 3-64. Raster obtenido con los datos de radiación

Estos valores obtenidos en la representación raster, se asignarán a continuación a los tejados.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 101

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Para ello se emplea la herramienta SolarRadiationRoofZones usando los siguientes parámetros, donde se introducen el fichero raster de radiación generado anteriormente así como los tejados y muros extraídos en CityEngine.

Figura 3-65. Herramienta radiación en los tejados

Los nuevos edificios 3D generados tienen los valores de radiación asignados. El modelo añade los siguientes nuevos campos a los edificios:

 Radiación solar: son los valores promedio anuales de la radiación solar para cada techo (en kilovatios-hora por metro cuadrado por día o kWh/m2/día).  Idoneidad solar: idoneidad de cada techo para la generación de energía solar (en kilovatios-hora por metro cuadrado por día o kWh/m2/día). o Idoneidad >= 1.72 kWh/m2/dia o No idoneidad < 1.72 kWh/m2/dia  Potencial solar: potencial de generación solar basado en la radiación entrante para cada techo (en kilovatios-hora por metro cuadrado por día o kWh/m2/día). o Excelente: > 2.11 kWh/m2/dia o Bueno: 1.72 - 2.11 kWh/m2/dia o Pobre: 1.42 – 1.72 kWh/m2/dia o No idoneidad: < 1.42 kWh/m2/dia

El resultado es el siguiente:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 102

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Figura 3-66. Potencial solar

Figura 3-67. Idoneidad solar

Estos datos de radiación obtenidos pueden utilizarse para realizar mapas o incluirse directamente en una nueva capa para ser integrados en nuestro modelo urbano 3D. Esta última opción sería la ideal, contribuyendo a la creación de un modelo inteligente de la ciudad donde los inversores o compradores podrían ver si merece la pena realizar una inversión en paneles solares, o cuántos de estos pueden colocar según la superficie del tejado.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 103

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

4. Conclusiones

La información geoespacial se encuentra bastante accesible hoy en día y puede aprovecharse en nuestro beneficio. Con datos abiertos y disponibles en la red se ha conseguido obtener un modelo urbano 3D con un nivel de detalle LoD 2 según el estándar CityGML. Este último no ha sido empleado en este trabajo puesto que CityEngine tiene el suyo propio (3DCIM) el cual está basado y es totalmente compatible con CityGML.

Este nivel de detalle puede incrementarse añadiendo texturas reales a los edificios, y detalles como balcones o las formas de los tejados. Mayor detalle conllevará más tiempo de trabajo y es por ello que hay que tener en cuenta cual es el fin del modelo a generar. Para planificar no es necesario tener un detalle excesivo, en cambio si quieren utilizar estos modelos con fines más visuales, como la industria cinematógrafica por ejemplo puede que sea necesario obtener un nivel de detalle mayor.

Para obtener este nivel de detalle sería interesante emplear otras técnicas geomáticas como son el láser escáner, de forma que se puedan obtener los edificios tal y como son en la realidad, lo cual también conllevaría un mayor tiempo de procesamiento para el ordenador y para el técnico encargado de llevar a cabo el trabajo.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 104

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Una solución posible es establecer niveles de detalle según la cercanía a un punto, o por zonas. También se pueden modelizar con mayor detalle solo los edificios más emblemáticos cuando se tengan fines visuales.

Las aplicaciones de estos modelos son muy variadas tal y como se ha visto, por lo que ideal sería tener un modelo en 4D donde se puedan consultar diferentes capas de información, las cuales vayan actualizándose continuamente en el tiempo.

En cuanto a la difusión de estos modelos, se pretende que estén disponibles para todo el mundo a través de servicios web, de manera que los ciudadanos puedan beneficiarse de esto, contribuyendo de esta forma al desarrollo de unas ciudades más inteligentes donde la información sea accesible para todo el mundo.

5. Bibliografía

AMELIBIA HERNANDO, I. (2013) CityGML: modelado urbano 3D. Jornadas Ibericas de Infraestructuras de Datos Espaciales IV.

BALSAVIAS, E.P. (2000). Geometric transformations and registration of images, orthoimage generation and mosaicing. Institude of Geodesy and Photogrammetry, ETHZ Zurich.

BESUIEVSKY, G.; PATOW, G. (2014) GIS & Modelado Procedural. Grupo de Geometría y Gráficos, Universitat de Girona.

CZERWINSKI, A.; SANDMANN, S.; STÖCKER-MEIER, E.; PLÜMER, L. (2007) Sustanaible SDI for EU noise mapping in NRW – best practice for INSPIRE. International Journal for Spatial Data Infrastructure Research.

DÖLLNER, J.; BAUMANN, K.; BUCHHOLZ, H. (2006) Virtual 3D City Models as Foundation of Complex Urban Information Spaces. University of Potsdam, Hasso- Plattner-Institut.

ERAN SADEK SAID B. MD SADEK; SAYED JAMALUDIN B. S. ALI & MOHD. ROSDI B. MD. KADZIM. The Design and Development of a Virtual 3D City Model.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 105

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Department of Surveying Science and Geomatics Faculty of Architecture, Planning and Surveying

FORD, M.; CADZOW, S.; WILSON, D.; PARSLOW, P.; PRANDI, F.; DE AMACIS, R. (2013). Using 3D Urban Models to Aid Simulation, Analysis and Visualisation of Data for Smart City Web Services (i-SCOPE). Proceedings of the Workshop "Environmental Information Systems and Services - Infrastructures and Platforms 2013 - with Citizens Observatories, Linked Open Data and SEIS/SDI Best Practices" co-located with the International Symposium on Environmental Software Systems 2013.

GRÖGER G.; H. KOLVE T.; NAGEL C.; HÄFELE K.H. (2012). OGC City Geographic Markup Language (CityGML) Encoding Standard. Open Geospatial Consortium.

PALÀ, V.; CORBERA, J. (2003). Necesidades y técnicas de obtención de un modelo urbano 3D verdadero: una solución y soporte para la navegación y localización en ciudades. Institut Cartogràfic de Catalunya. Instituto de Navegación de España.

PÉREZ GARCÍA, J.L.; DELGADO GARCÍA, J. (2014). Apuntes de la asignatura de Sistemas Lidar y MMS. Máster en Tecnologías Geoespaciales aplicadas a la gestión inteligente del territorio (No publicado).Universidad de Jaén.

PÉREZ GARCÍA, J.L.; DELGADO GARCÍA, J. (2014). Apuntes de la asignatura de Tratamiento, Análisis e Integración de MDT y MDS. Máster en Tecnologías Geosespaciales aplicadas a la Gestión Inteligente del Territorio (No publicado). Universidad de Jaén.

PÉREZ GARCÍA, J.L.; DELGADO GARCÍA, J.; CARDENAL ESCARCENA, F.J. (2013). Apuntes de fotogrametría y teledetección 3. Grado en Ingeniería Geomática y Topografía. (No publicado) Universidad de Jaén.

PRIETO, I.; IZAKARA, J.L.; EGUSKIZA, A. (2013). Modelo de Información Multiescala Urbana 3D para la gestión integral sostenible de la ciudad.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 106

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

SANTOS PÉREZ, L.J. (2005). Ortofoto verdadera (True-Ortho) y Lídar, el posible futuro de la cartografía catastral urbana. D.G. del Catastro. Madrid.

SEGURA SÁNCHEZ, R.J.; JIMÉNEZ PÉREZ, J.R. (2014). Apuntes de la asignatura de Realidad Virtual y Aumentada. Modelización 3D. Máster en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio. (No publicado) Universidad de Jaén.

PÁGINAS WEB

3D Cities [http://desktop.arcgis.com/en/3d/3d-cities/]

Introducción a City Engine [https://desktop.arcgis.com/en/cityengine/latest/tutorials/introduction-to-the- cityengine-tutorials.htm]

6. Anexos

6.1. Código empleado para generar los edificios

/** * File: imagen_satelite_tejados.cga * Created: 21 Oct 2015 10:49:20 GMT * Author: antonio */ version "2015.1" attr totalHeight = 10 attr floorheight = rand(4,5) actualFloorHeight = case scope.sy >= floorheight : scope.sy/rint(scope.sy/floorheight) else : scope.sy actualTileWidth = case scope.sx >= 2 : scope.sx/rint(scope.sx/4) else : scope.sx const randomFacadeTexture = fileRandom("*facade_textures/f*.tif")

# dimension of the satellite map const mapdimension_x = 593 #change this to satellite image details const mapdimension_z = 502 #change this to satellite image details # offset of the satellite map const mapoffset_x = 439338.2501 #change this to satellite image details

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 107

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D const mapoffset_z = -4475346.250 #change this to satellite image details Lot--> extrude(totalHeight) Mass Mass --> # split building mass into roof and side faces comp(f){top : Roof | side : Facade}

Facade --> setupProjection(0, scope.xy, 8*actualTileWidth, 8*actualFloorHeight) texture(randomFacadeTexture) projectUV(0)

Roof --> Rooftex

Rooftex --> setupProjection(0, world.xz, mapdimension_x, mapdimension_z) set(material.colormap, "Orto_JPG.jpg") #change this projectUV(0) translateUV(0, -mapoffset_x/mapdimension_x, -mapoffset_z/mapdimension_z) scaleUV(0,1,-1)

6.2. Código empleado para generar las calles

/** * File: Complete Street.cga * Created: 1/26/2015 Jan 2015 * Author: Esri Redlands (based on work by Esri R&D Center Zurich) */

# Differences to Street Construction Simple: # This ruleset can also generate stop markings and crosswalks (by using the # objects attributes) and generates more detailed roundabouts # Differences to Street Construction Standard: # More informed by MUTCD/AASHTO/NACTO Street Guidelines, but used approximations. # Can create Bus lanes, bike lanes (of different colors), parking lanes (with parklets), # medians (with alternative planting configurations), boulevards(double medians), and even # highways with HOV lanes, bridge supports, and shoulders (in center type and bicycle buffer). # #Sources for Reports and Descriptions: #1.http://www.fhwa.dot.gov/publications/research/safety/09039/03.cfm #2.http://mutcd.fhwa.dot.gov/index.htm #3.http://www.qcode.us/codes/southpasadena/view.php?topic=36-3-36_310- 36_310_080 #4.http://nacto.org/usdg/ #5.http://nacto.org/cities-for-cycling/design-guide/ #6.https://bookstore.transportation.org/collection_detail.aspx?ID=110 #7.http://transweb.sjsu.edu/project/1005.html #8.http://onlinepubs.trb.org/onlinepubs/nchrp/nchrp_rpt_504.pdf

#Useful Numbers:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 108

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

#13 feet ==3.9624 Meters #12 feet ==3.6576 Meters #11 feet ==3.3528 Meters #10 feet ==3.048 Meters #9 feet ==2.7432 Meters #8 feet ==2.1336 Meters #7 feet ==1.8288 Meters #6 feet ==1.524 Meters #4 feet ==1.2192 Meters #3 feet ==.9144 Meters #2 feet ==.6096 Meters #1 feet ==.3048 Meters #1/2 feet ==.1524 Meters #1 inch ==.0254 Meters version "2014.1"

################################################### # Control Attributes-INSPECTOR #

@Group("DISPLAY OPTIONS",0) @Order(1)@Description("When true, textures are on display, when false textures are removed. If true it deletes an unused UVset (see comments for details).") attr Display_Textures = true @Group("DISPLAY OPTIONS") @Order(2) @Description("Visually colors the entire street model based on the attributes of a street. Usage thematic looks best when textures are turned off.") @Range("Thematics Off", "Solid Color", "Peak Runoff/Permeability","Bike Stress","Pedestrian Stress","Auto Stress","Transit Stress","Usage") attr Display_Thematics = "Thematics Off" @Group("DISPLAY OPTIONS") @Order(3) @Description("When the Solid Color thematic is used for highlighting certain streets, this chooses the color that is utilized by the thematic.") attr Solid_Color = "#FFFFFF" @Group("DISPLAY OPTIONS") @Order(4)@Description("When this attribute is true, any time there is unallocated drainage space that is wider than 1/3 the current lane width (usually 3-4 feet), it will flag them as red. It helps find errant streets.") attr Flag_Empty_Space = false @Group("DISPLAY OPTIONS") @Range("High","Low") @Order(5)@Description("This attribute controls the level of detail of the selected textures and OBJs. Typically a lower LOD will decrease the polygon count and texture image resolution.") attr LOD_Setting ="High" texturingOn = Display_Textures # Shorthand. thematicsOn = Display_Thematics != "Thematics Off" coloringOn = !thematicsOn && texturingOn # Shorthand. const peakRunoffDisplayOn = Display_Thematics == "Peak Runoff/Permeability" const Low_LOD = case LOD_Setting=="Low":"Low" else:"" const High_LOD = case LOD_Setting=="High":"High" else:""

@Order(1)@Group("ROAD LAYOUT","Basic Components",1) @Range(0,1) @Description("Represents the fraction of the lanes allocated to the *Right Lanes*. If 1 or 0, they become 1 way streets.") attr Lane_Distribution = _getInitialLaneDistribution @Order(2)@Range(2.7,3.9624)@Description("Determines the widths of the main travel lanes. Typically, Freeways are about 12 feet (3.6 m), Arterials 11- 12 feet (3.3-3.6 m), Collectors 10-12 feet (3.0-3.6 m), and Local roads 9- 12 feet (2.7-3.6 m).")

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 109

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D attr Lane_Width = (laneWidth-.2) @Order(3) @Range("yellow","white","none") @Description("Choses color for the centerline if there is a center line. This attribute does nothing to other center types.") attr Centerline_Color = _getInitialCenterline @Order(4) @Range("right-hand","left-hand")@Description("Orients the road for right vs. left traffic. Please note that some aspects of the rule do not *flip* when this is changed such as the median.") attr Traffic_Direction = "right-hand" @Order(5) @Range(0,80) @Description("A descriptive attribute that feeds into reporting. If >= 40 mph, Design Speed is calculated as Speed_Limit +7.5, if less than 40, design speed is assumed equal to the Speed_Limit (see comments for details). 1 MPH==1.6093 KPH.") attr Speed_Limit_in_MPH = _InititalSpeedLimit

@Group("ROAD LAYOUT","Stop Markings",2) @Order(1) @Range("none","line only","with stop marking","arrows on all lanes","arrows on side lanes","arrows for right turn") @Description("The initial stop markings do not take into account the topology of the intersection i.e. they need to be set manually") attr Stop_Begin = _getInitialStop(connectionStart,nLanesLeft+_Lt_Transit_Lane_Count) @Order(2) @Range("none","line only","with stop marking","arrows on all lanes","arrows on side lanes","arrows for right turn") @Description("The initial stop markings do not take into account the topology of the intersection i.e. they need to be set manually") attr Stop_End = _getInitialStop(connectionEnd, _Distribute_Right_Lanes+_Rt_Transit_Lane_Count)

@Group("ROAD LAYOUT","Crosswalk Markings",3) @Order(1) @Range("none","continental","ladder","transverse","dashed","solid","custom" ,"ladder custom") @Description("NACTO-High•-visibility ladder, zebra, and continental crosswalk markings are preferable to standard parallel or dashed pavement markings. These are more visible to approaching vehicles and have been shown to improve yielding behavior.") # TODO "solid","dashed","ladder" attr Crosswalk_Begin = _getInitialCrosswalk(connectionStart) @Order(2) @Range("none","continental","ladder","transverse","dashed","solid","custom" ,"ladder custom")@Description("NACTO-High•-visibility ladder, zebra, and continental crosswalk markings are preferable to standard parallel or dashed pavement markings. These are more visible to approaching vehicles and have been shown to improve yielding behavior.") attr Crosswalk_End = _getInitialCrosswalk(connectionEnd) @Order(3) @Range(0,10) @Description("Crosswalk to Stop Bar Distance. If the Crosswalk UV is clipping geometry, adjust this to set it back more on angled streets. If used, stop and yield lines should be placed a minimum of 4 ft (1.2 m) from the Crosswalk-MUTCD. NACTO suggests a minimum of 8 ft (2.44 m) in urban areas.") attr Begin_Crosswalk_To_Stop_Bar= _getInitialGap(connectionStart) @Order(4) @Range(0,10) @Description("Crosswalk to Stop Bar Distance. If the Crosswalk UV is clipping geometry, adjust this to set it back more on angled streets. If used, stop and yield lines should be placed a minimum of 4 ft (1.2 m) from the Crosswalk-MUTCD. NACTO suggests a minimum of 8 ft (2.44 m) in urban areas.") attr End_Crosswalk_To_Stop_Bar = _getInitialGap(connectionEnd) @Order(5) @Range("white","yellow") @Description("Determines the color of painted crosswalks.")

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 110

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D attr Crosswalk_Color = "white" @Order(6) @File("tif","jpg","png","tiff","gif","jpeg","psp","jsl","sgi","tga","bmp"," dds")@Description("Creates a 2 m by 2 m tile of the image selected on the crosswalk. Keep in mind that if another painted tile is chosen, the paint area will not appear in reporting. Defer to Crosswalk Area Reports.") attr Custom_Crosswalk_Texture = SidewalkFolder+"/Paver Brick Red Basket Weave.jpg" @Order(7) @Range(0,10)@Description("This attribrute overrides the default Crosswalk Width. NACTO- Stripe the crosswalk as wide as or wider than the walkway it connects to.") attr Crosswalk_Width = _crosswalkWidth

@Group("ROAD LAYOUT","On-Street Parking",5) @Order(1)@Range("None","Parallel","Angled Nose In","Angled Back In") @Description("Will create parking of that type with default lengths and widths. Keep in mind, adjusting the length/width will make it lock onto that value. To reset it to automatic default, set the Attribute Connection Editor back to rule-defined value.") attr Right_Parking_Type = "None" @Order(2)@Range(0,5)@Description("Good default is 8 feet (2.4384 m) with a minimum of 7 feet (2.1336 m) for low turn over locations for parallel parking. Angled parking varies on angle, but a 30-45 degree depth suggestion is 19 feet (5.7912 m). Design guideance on width varies with conditions. ") attr Right_Parking_Width = _ParkingWidth("Right") @Order(3)@Range(0,10)@Description("For Parallel Parking 6.1 to 7.5 meters long is suggested, for Angled Parking 2.4 to 3 m is suggested.") attr Right_Parking_Length = _ParkingLength("Right") @Order(4)@Range("None","Parallel","Angled Nose In","Angled Back In")@Description("Will create parking of that type with default lengths and widths. Keep in mind, adjusting the length/width will make it lock onto that value. To reset it to automatic default, set the Attribute Connection Editor back to rule-defined value.") attr Left_Parking_Type = "None" @Order(5)@Range(0,5) @Description("Good default is 8 feet (2.4384 m) with a minimum of 7 feet (2.1336 m) for low turn over locations for parallel parking. Angled parking varies on angle, but a 30-45 degree depth suggestion is 19 feet (5.7912 m). Design guideance on width varies with conditions.") attr Left_Parking_Width = _ParkingWidth("Left") @Order(6)@Range(0,10)@Description("For Parallel Parking 6.1 to 7.5 meters long is suggested, for Angled Parking 2.4 to 3 m is suggested.") attr Left_Parking_Length = _ParkingLength("Left") @Order(7)@Range(0,100) @Description("Will create Parklets in Parking spaces, it is best if the parking spaces are contiguous to the sidewalk. The default OBJ does not have bollards or curb stops suggested by NACTO.") attr Parklet_Percentage = 0 @Order(8)@Range(0,10) @Hidden @Description("This hidden attribute controls the spacing the parking areas have before the current directions stopbar.") attr Front_Parking_Spacing = 0 @Order(9)@Range(0,10) @Hidden @Description("This hidden attribute controls the spacing the parking areas have after the crosswalk at the start of the street in the current direction.") attr Rear_Parking_Spacing = 0

@Group("CENTER SECTION LAYOUT","Basic Attributes", 2) @Order(1) @Range("None","Median", "Boulevard", "Barrier","Barrier & Shoulder","Center Turn Lane")@Description("This attribute is key to picking

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 111

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D a center type. If none, it is a centerline, but each choice creates different center section layouts.") attr Center_Type = "None" @Order(2) @Range(0,40) @Description("Is the combined center section width regardless of type. Does nothing for the barrier selection.") attr Center_Width = 0 @Order(3) @Range(0,4) @Description("Is the width of the walkways created by Median. They will override the planting width, and keep in mind there are two walkways for :Walk:Plant.") attr WalkWay_Width = 0 @Order(4) @Range("Walk:Plant:Walk","Walk:Plant","Plant:Walk","Plant:Walk:Plant") @Description("Lays out the median/boulevard walkway configurations. In the case of Plant:Walk:Plant-the walkway rule is used twice so adjust walkway width accordingly.") attr Planting_and_Walkway_Layout ="Walk:Plant:Walk" @Order(5) @Range(0,10)@Description("In the case of a boulevard, this is the combined width for the lanes and center between the walkways. Each lane set gets half allocated space. Keep in mind this means there is forced symmetry in lanes.") attr Boulevard_Inside_Width = 7.1 @Order(6) @Range("Normal Lanes","Bus Lanes", "Open Space","Cycle Path") @Description("Determines the general configurations of the inside of the boulevard. Normal lanes will be equal to the general Lane_Width, and any left over is filled with drainage filler.") attr Boulevard_Configuration = "Normal Lanes" @Order(7) @Range("Center Line","Median","Curb Buffer","Chain Link Fence", "Gate Fence","Tubular Markers")@Description("Will create the exact center of the lanes in the boulevard. To remove it set the width ==0.") attr Boulevard_Center_Type = "Center Line" @Order(8)@Range(0,10)@Description("Determines the width of the center of the Boulevard lanes.") attr Boulevard_Center_Width = case Boulevard_Configuration=="Normal Lanes": PaintLineWidth*4 else: 0

@Group("CENTER SECTION LAYOUT","Median Plantings",3)@Order(1) @Description("Chooses the grass texture for the planting locations within the Median.")@Range ("None","Random", "Standard Grass", "Lawn 1", "Lawn 2", "Park", "Bermuda 1", "Bermuda 2", "Bermuda Dark", "Bluegrass 1", "Bluegrass 2", "Grass Short", "Grass Thick", "St Augustine 1", "St Augustine 2", "Light Rye") @Order(2) attr Median_Ground_Cover = "Standard Grass" #@Range("Random", "Conifer", "Desert", "Eudicot", "Monocot") @Order(4)@Range(0,10) @Description("Is the approximate length of the green space accomodating trees, it can be used to space out trees more without walkway spacing.") attr Median_Planting_Length = 4 @Order(5) @Range(0,15) @Description("Creates a walkway spacing between created trees.") attr Median_Tree_Spacing = 3 @Order(6)@Description("Determines the of the tree/plant selected for Tree 1. Random picks from 5 common tree types and is a good default.")@Range("Random","Alder Buckthorn","Amazon Sword Plant","American Chestnut","American Sycamore","Apricot","Australian Pine","Baldcypress","Balsam Fir","Bamboo","Banana Tree","Basswood","Bay Laurel","Black Locust","Blue Gum Eucalyptus","Boxwood","Cabbage Palm Fern","California Bay","California Incense Cedar","California Palm","California Redwood","California Walnut","Coconut Palm","Common Hawthorn","Common Whitebeam","Conker Tree","Date Palm","Desert Willow","Douglas Fir","European Beech","European Larch","Ficus","Field Elm","Flannelbush","Flowering Dogwood","Giant Sequoia","Hedgehog

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 112

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Agave","Japanese Angelica Tree","Lacy Tree Philodendron","Leyland Cypress","Lily of the Valley","Lodgepole Pine","Mediterranean Buckthorn","Mexican Palmetto","Mountain Mahogany","Northern Red Oak","Norway Maple","Norway Spruce","Orange Tree","Orchid","Oval-leaved Privet","Palm Lily","Palo Verde","Paper Birch","Parlour Palm","Prickly Pear ","Red Alder","Red Hickory","Rhododendron Azaleas","Rose","Ruffle Palm","Saguaro Cactus","Sassafras","Scots Pine","Sea Islands Yucca","Shadbush","Snake Plant","Southern Magnolia","Spanish Broom","Strawberry Tree","Sugar Maple","Sunflower","Sweetgum","Umbrella Acacia","Western Juniper","White Ash","White Oak","White Poplar","White Willow","Witch Hazel","","______","GENERICS","","Generic Dead Tree","Generic Stump","Generic Unknown","","______","PROXIES","","Algarrobo","Ameri can Elderberry","American Pepper","American Silverberry","Athel Tamarisk","Avocado","Black Tupelo","Buttonbush","Canada Buffaloberry","Chinaberry Tree","Chinese Tallow Tree","Common Hackberry","Common Holly","Common Persimmon","Desert Bitterbrush","European Hornbeam","Giant Chinquapin","Honey Locust","Hophornbeam","Huckleberry Shrub","Japanese Hemlock","Japanese Nutmeg","Judas Tree","Lawson Cypress","Loblolly Bay","Mexican Buckeye","Necklacepod","Northern Bilberry","Northern White Cedar","Octopus Tree","Osage Orange","Paper Bark Tree","Pawpaw","Persian Silk Tree","Princess Tree","Smooth Sumac","Sourwood","Southern Wax Myrtle","Tanoak","Tree of Heaven","Turkish Hazel","Western Soapberry","White Mulberry","Yellow Poplar","Yew") attr Median_Tree_1_Type = "Random" @Order(7) @Range(0,1) @Description("Reduces the probability of Tree 1 appearing in a typical designated location.") attr Median_Tree_1_Percentage = 1 @Order(8)@Description("Determines the species of the tree/plant selected for secondary tree for more variation. If this is not None, Tree 2 will appear if Tree 1 does not fire with the current percentage. This does mean that you cannot drop tree density if you alternate trees.")@Range("None","Random","Alder Buckthorn","Amazon Sword Plant","American Chestnut","American Sycamore","Apricot","Australian Pine","Baldcypress","Balsam Fir","Bamboo","Banana Tree","Basswood","Bay Laurel","Black Locust","Blue Gum Eucalyptus","Boxwood","Cabbage Palm Fern","California Bay","California Incense Cedar","California Palm","California Redwood","California Walnut","Coconut Palm","Common Hawthorn","Common Whitebeam","Conker Tree","Date Palm","Desert Willow","Douglas Fir","European Beech","European Larch","Ficus","Field Elm","Flannelbush","Flowering Dogwood","Giant Sequoia","Hedgehog Agave","Japanese Angelica Tree","Lacy Tree Philodendron","Leyland Cypress","Lily of the Valley","Lodgepole Pine","Mediterranean Buckthorn","Mexican Palmetto","Mountain Mahogany","Northern Red Oak","Norway Maple","Norway Spruce","Orange Tree","Orchid","Oval-leaved Privet","Palm Lily","Palo Verde","Paper Birch","Parlour Palm","Prickly Pear Cactus","Red Alder","Red Hickory","Rhododendron Azaleas","Rose","Ruffle Palm","Saguaro Cactus","Sassafras","Scots Pine","Sea Islands Yucca","Shadbush","Snake Plant","Southern Magnolia","Spanish Broom","Strawberry Tree","Sugar Maple","Sunflower","Sweetgum","Umbrella Acacia","Western Juniper","White Ash","White Oak","White Poplar","White Willow","Witch Hazel","","______","GENERICS","","Generic Dead Tree","Generic Stump","Generic Unknown","","______","PROXIES","","Algarrobo","Ameri can Elderberry","American Pepper","American Silverberry","Athel Tamarisk","Avocado","Black Tupelo","Buttonbush","Canada Buffaloberry","Chinaberry Tree","Chinese Tallow Tree","Common Hackberry","Common Holly","Common Persimmon","Desert Bitterbrush","European Hornbeam","Giant Chinquapin","Honey Locust","Hophornbeam","Huckleberry

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 113

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Shrub","Japanese Hemlock","Japanese Nutmeg","Judas Tree","Lawson Cypress","Loblolly Bay","Mexican Buckeye","Necklacepod","Northern Bilberry","Northern White Cedar","Octopus Tree","Osage Orange","Paper Bark Tree","Pawpaw","Persian Silk Tree","Princess Tree","Smooth Sumac","Sourwood","Southern Wax Myrtle","Tanoak","Tree of Heaven","Turkish Hazel","Western Soapberry","White Mulberry","Yellow Poplar","Yew") attr Median_Tree_2_Type = "None" @Group("CENTER SECTION LAYOUT","Basic Components", 4) @Order(5)@Range("None","Both","Right","Left") @Description("Determines whether an object is placed and what side of the street or walkways relevant objects are placed.") attr Median_Bus_Stop ="None" @Order(6) @Range("Far-side", "Mid-Block", "Near-side")@Description("Locates bus stop in the appropriate location. Far-side is right after the last intersection, Mid-Block is in the middle of the street, and Near-side is near to the next intersection.") attr Median_Bus_Stop_Location = "Far-side" @Order(7)@Description("Will create 2 bike racks near a bus stop.") attr Median_Bike_Rack = false @Order(8)@Description("Will create a WayFinder near a bus stop.") attr Median_Way_Finder = false @Order(9)@Range("None","Both","Right","Left") @Description("Creates benches on the edges of the walkways of the Median.") attr Median_Benches ="None" @Order(10)@Range(0,50) @Description("Determines the spacing between each Bench. No shape is created in the sections in between objects.") attr Median_Bench_Spacing =10 @Order(11)@Range("None","Both","Right","Left")@Description("Determines whether an object is placed and what side of the street or walkways relevant objects are placed.") attr Median_Street_Lamps ="Both" @Order(12)@Range(0,50) @Description("Determines the spacing between each Street Lamp. No shape is created in the sections in between objects.") attr Median_Street_Lamp_Spacing =10

@Group("MULTIMODAL LANES LAYOUT", "Bus and HOV Lanes",4)@Order(1)@Range("None","Bus Lane","HOV Lane")@Description("The controls for the bus lane also control the HOV lane. They are grouped together because they are both considered :High Capacity Lanes:") attr Transit_Lane ="None" @Order(2)@Range("Right", "Left", "Both")@Description("Determines side of street preferential lanes are allocated.") attr Transit_Lane_Sides =_Initital_Transit_Lane_Sides # If the street is oneway, will make initial bus lane side change accordingly @Order(3) @Range(3,5) @Description("Determines the lane width of transit lanes that are not Dedicated Median Bus Lanes. NACTO suggested width is 11 feet (3.3528 m) minimum for Curb side and Median bus lanes, but allows for 10 feet (3.048 m) on Off-set bus lanes.") attr Transit_Lane_Width = 3.3528 @Order(3)@Range("Sidewalk Side","Right Most Lane","Left Most Lane")@Description("Inserts a transit lane at the location specified. Keep in mind this is an insertion not a lane reallocation.") attr Transit_Lane_Position ="Right Most Lane" @Order(4)@Range(1,304.8)@Description("MUTCD- Preferential Lanes: Markings spaced as close as 80 feet(~24.5 m) apart might be appropriate on city streets, while markings spaced as far as 1,000 feet (304.8 m) apart might be appropriate for freeways.") attr Transit_Symbol_Spacing =24.5 @Order(6)@Range("red","black") @Description("NACTO-Red colored paint should be applied to emphasize the lane and to deter drivers from using it. Red

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 114

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D paint has higher installation and maintenance costs, but has been shown to deter both unauthorized driving and parking in the bus lane.") attr Bus_Lane_Color ="red" @Order(7)@Range("Both","Right", "Left", "None")@Description("Controls the white lines on the sides of preferential lanes.") attr Transit_Paint_Line_Sides = "Both"

@Group("MULTIMODAL LANES LAYOUT", "Bike Lanes",5)@Order(2)@Range(0,6) @Description("Desirable bike lane width adjacent to a curbface is 6 feet (1.8288m), but rideable surface adjacent to a steet edge is 4 feet (1.2192m) with minimum of 3 feet (0.9144m). In areas where illegal parking is an issue, at least 5 feet (1.524m) is suggested.") attr Right_Bike_Lane_Width =0 @Order(2)@Range(0,6)@Description("Desirable bike lane width adjacent to a curbface is 6 feet (1.8288m), but rideable surface adjacent to a steet edge is 4 feet (1.2192m) with minimum of 3 feet (0.9144m). In areas where illegal parking is an issue, at least 5 feet (1.524m) is suggested.") attr Left_Bike_Lane_Width =0 @Order(3)@Range("One-way","Two-way")@Description("The oneway option uses the full lanewidth for each lane, while the two-way option will allocate half of the width to each sub-lane.") attr Bike_Lane_Type ="One-way" @Order(4)@Range(0,6)@Description("Bicycle Buffers have desired minimums of about 3 feet, but should be at least 18 inches wide because it is impractical to mark a zone narrower than that.") attr Right_Buffer_Width = 0 @Order(5)@Range(0,6)@Description("Bicycle Buffers have desired minimums of about 3 feet, but should be at least 18 inches wide because it is impractical to mark a zone narrower than that.") attr Left_Buffer_Width = 0 @Order(6)@Description("If on/true, buffer is closer to the through lane, and bicycle lane is protected from through traffic.") attr Buffer_Protection = true @Order(7)@Description("If on/true, parking lane is closer to the through lane, and bicycle lane is protected from through traffic. Keep in mind how the door zone influences bicycle lane placement.") attr Parking_Protection = true @Order(8)@Range("Painted Stripes","Curb Buffer","Curb Buffer with Plantings","Curb Buffer with Trees","Solid White","Cycle Track With Planters","Cycle Track With Tubular Markers","Asphalt","Shoulder")@Description("This attribute controls the bicycle buffer type and form, but also can become plain asphalt or a shoulder.") attr Buffer_Type ="Painted Stripes" @Order(9)@Range(0,10)@Description("Controls the buffers spacing of objects such as tubular markers, planters, and tree/plantings (Trees/ match Sidewalk Plantings if selected).") attr Buffer_Object_Spacing =_Default_Buffer_Object_Spacing @Order(10)@Range(1,304.8)@Description("MUTCD- Preferential Lanes: Markings spaced as close as 80 feet (~24.5 m) apart might be appropriate on city streets, while markings spaced as far as 1,000 feet (304.8 m) apart might be appropriate for freeways.") attr Bike_Symbol_Spacing = 24.5 @Order(11)@Range(0,20) @Description("Creates conflict spacing made up by asphalt gaps in the bike lane for approaching interesections.") attr Bike_Conflict_Spacing = 0 @Order(12)@Range("green","black","red","blue") @Description("Determines the color of the bike lane and bike box. Paint reporting costs adjust based on color choices.") attr Bike_Lane_Color ="green"

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 115

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

@Order(13)@Range("Both","Right", "Left", "None")@Description("Controls the white lines on the sides of preferential lanes.") attr Bike_Paint_Line_Sides ="Both" @Order(14)@Range("Rare","Moderate","Frequent")@Description("Is a descriptive attribute relating to the probability that a bike lane might be blocked due to unloading or double parking that feeds into Thematic") attr Level_of_Blockage ="Rare"

@Group("MULTIMODAL LANES LAYOUT","Bike Box",6) @Order(1) @Description("Right Side Bike Box: NACTO-A bike box is a designated area at the head of a traffic lane at a signalized intersection that provides bicyclists with a safe and visible way to get ahead of queuing traffic during the red signal phase. Works best if bike lane is adjacent to sidewalk.") attr Right_Bike_Box = false @Order(2) @Description("Left Side Bike Box: NACTO-A bike box is a designated area at the head of a traffic lane at a signalized intersection that provides bicyclists with a safe and visible way to get ahead of queuing traffic during the red signal phase. Works best if bike lane is adjacent to sidewalk.") attr Left_Bike_Box = false @Order(3)@Range(1,10) @Description("Is the best fit spacing between the bicycle symbols on the bike box. Can be increased to reduce the number of symbols created.") attr Bike_Box_Symbol_Spacing = 5 @Order(4)@Range(0,5.3768)@Description("NACTO-A box formed by transverse lines shall be used to hold queuing bicyclists, typically 10-16 feet deep (3.048-4.8768 M). Deeper boxes show less encroachment by motor vehicles.") attr Bike_Box_Length =4.26 @Order(12)@Range("green","black","red","blue") @Description("By default, the Bike Box will match the color of the bike lane, but this attribute can be adjusted to override that choice. Paint reporting costs adjust based on color choices.") attr Bike_Box_Color_Override = Bike_Lane_Color

@Group("SIDEWALK LAYOUT","Sidewalk Attributes",7)@Description("Provides a file picker for the texture choice. This attribute also controls the curb buffer and median walkway textures.") @Order(2)@File ("tif","jpg","png","tiff","gif","jpeg","psp","jsl","sgi","tga","bmp","dds") attr Sidewalk_Texture = Default_Pavement @Order(3) @Range(0.1,10)@Description("Adjust the scale of the sidewalk texture.This attribute also controls the curb buffer and median walkway textures.") attr Sidewalk_Texture_Scale = 1 @Order(4) @Range(0,360)@Description("Adjust the angle of the sidewalk texture. This attribute also controls the curb buffer and median walkway textures.") attr Sidewalk_Texture_Rotation = 0 @Order(5) @Range(0,0.4)@Description("Determines the height of the sidewalk. Default is 4 inches tall. This attribute also controls the curb buffer and median walkway textures.") attr Sidewalk_Height = 0.102 # height of sidewalk of curbs(4 inch is standard thickness) curb depth is 1.5 times sidewalk height

@Group("SIDEWALK LAYOUT", "Sidewalk Plantings",8) @Description("Chooses the grass texture for the planting locations on the Sidewalk or Center Island. Bus Stops and trees will not generate if this is set to None.")@Range ("None","Random", "Standard Grass", "Lawn 1", "Lawn 2", "Park", "Bermuda 1", "Bermuda 2", "Bermuda Dark", "Bluegrass 1",

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 116

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

"Bluegrass 2", "Grass Short", "Grass Thick", "St Augustine 1", "St Augustine 2", "Light Rye") @Order(2) attr Sidewalk_Ground_Cover = "None" @Order(2)@Range(0,10)@Description("Controls the width of sidewalk planting space, and the setback of the bus stop.") attr Sidewalk_Planting_Width = 1.5 @Order(3)@Range(0,10) @Description("Is the approximate length of the green space accomodating trees, it can be used to space out trees more without walkway spacing.") attr Sidewalk_Planting_Length = 5 @Order(4)@Range(0,20)@Description("Creates a walkway spacing between created trees. Keep in mind that the benches are placed in this spacing and must be an appropriate size to accomodate them.") attr Sidewalk_Planting_Spacing = 5 @Order(6)@Description("Determines the species of the tree/plant selected for Tree 1. Random picks from 5 common tree types and is a good default.")@Range("Random","Alder Buckthorn","Amazon Sword Plant","American Chestnut","American Sycamore","Apricot","Australian Pine","Baldcypress","Balsam Fir","Bamboo","Banana Tree","Basswood","Bay Laurel","Black Locust","Blue Gum Eucalyptus","Boxwood","Cabbage Palm Fern","California Bay","California Incense Cedar","California Palm","California Redwood","California Walnut","Coconut Palm","Common Hawthorn","Common Whitebeam","Conker Tree","Date Palm","Desert Willow","Douglas Fir","European Beech","European Larch","Ficus","Field Elm","Flannelbush","Flowering Dogwood","Giant Sequoia","Hedgehog Agave","Japanese Angelica Tree","Lacy Tree Philodendron","Leyland Cypress","Lily of the Valley","Lodgepole Pine","Mediterranean Buckthorn","Mexican Palmetto","Mountain Mahogany","Northern Red Oak","Norway Maple","Norway Spruce","Orange Tree","Orchid","Oval-leaved Privet","Palm Lily","Palo Verde","Paper Birch","Parlour Palm","Prickly Pear Cactus","Red Alder","Red Hickory","Rhododendron Azaleas","Rose","Ruffle Palm","Saguaro Cactus","Sassafras","Scots Pine","Sea Islands Yucca","Shadbush","Snake Plant","Southern Magnolia","Spanish Broom","Strawberry Tree","Sugar Maple","Sunflower","Sweetgum","Umbrella Acacia","Western Juniper","White Ash","White Oak","White Poplar","White Willow","Witch Hazel","","______","GENERICS","","Generic Dead Tree","Generic Stump","Generic Unknown","","______","PROXIES","","Algarrobo","Ameri can Elderberry","American Pepper","American Silverberry","Athel Tamarisk","Avocado","Black Tupelo","Buttonbush","Canada Buffaloberry","Chinaberry Tree","Chinese Tallow Tree","Common Hackberry","Common Holly","Common Persimmon","Desert Bitterbrush","European Hornbeam","Giant Chinquapin","Honey Locust","Hophornbeam","Huckleberry Shrub","Japanese Hemlock","Japanese Nutmeg","Judas Tree","Lawson Cypress","Loblolly Bay","Mexican Buckeye","Necklacepod","Northern Bilberry","Northern White Cedar","Octopus Tree","Osage Orange","Paper Bark Tree","Pawpaw","Persian Silk Tree","Princess Tree","Smooth Sumac","Sourwood","Southern Wax Myrtle","Tanoak","Tree of Heaven","Turkish Hazel","Western Soapberry","White Mulberry","Yellow Poplar","Yew") attr Sidewalk_Tree_1_Type = "Random" @Order(7) @Range(0,1)@Description("Reduces the probability of Tree 1 appearing in a typical designated location, but also controls the Tree quantity at round abouts.") attr Sidewalk_Tree_1_Percentage = 1 @Order(8)@Description("Determines the species of the tree/plant selected for secondary tree for more variation. If this is not None, Tree 2 will appear if Tree 1 does not fire with the current percentage. This does mean that you cannot drop tree density if you alternate trees.")@Range("None","Random","Alder Buckthorn","Amazon Sword Plant","American Chestnut","American Sycamore","Apricot","Australian

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 117

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Pine","Baldcypress","Balsam Fir","Bamboo","Banana Tree","Basswood","Bay Laurel","Black Locust","Blue Gum Eucalyptus","Boxwood","Cabbage Palm Fern","California Bay","California Incense Cedar","California Palm","California Redwood","California Walnut","Coconut Palm","Common Hawthorn","Common Whitebeam","Conker Tree","Date Palm","Desert Willow","Douglas Fir","European Beech","European Larch","Ficus","Field Elm","Flannelbush","Flowering Dogwood","Giant Sequoia","Hedgehog Agave","Japanese Angelica Tree","Lacy Tree Philodendron","Leyland Cypress","Lily of the Valley","Lodgepole Pine","Mediterranean Buckthorn","Mexican Palmetto","Mountain Mahogany","Northern Red Oak","Norway Maple","Norway Spruce","Orange Tree","Orchid","Oval-leaved Privet","Palm Lily","Palo Verde","Paper Birch","Parlour Palm","Prickly Pear Cactus","Red Alder","Red Hickory","Rhododendron Azaleas","Rose","Ruffle Palm","Saguaro Cactus","Sassafras","Scots Pine","Sea Islands Yucca","Shadbush","Snake Plant","Southern Magnolia","Spanish Broom","Strawberry Tree","Sugar Maple","Sunflower","Sweetgum","Umbrella Acacia","Western Juniper","White Ash","White Oak","White Poplar","White Willow","Witch Hazel","","______","GENERICS","","Generic Dead Tree","Generic Stump","Generic Unknown","","______","PROXIES","","Algarrobo","Ameri can Elderberry","American Pepper","American Silverberry","Athel Tamarisk","Avocado","Black Tupelo","Buttonbush","Canada Buffaloberry","Chinaberry Tree","Chinese Tallow Tree","Common Hackberry","Common Holly","Common Persimmon","Desert Bitterbrush","European Hornbeam","Giant Chinquapin","Honey Locust","Hophornbeam","Huckleberry Shrub","Japanese Hemlock","Japanese Nutmeg","Judas Tree","Lawson Cypress","Loblolly Bay","Mexican Buckeye","Necklacepod","Northern Bilberry","Northern White Cedar","Octopus Tree","Osage Orange","Paper Bark Tree","Pawpaw","Persian Silk Tree","Princess Tree","Smooth Sumac","Sourwood","Southern Wax Myrtle","Tanoak","Tree of Heaven","Turkish Hazel","Western Soapberry","White Mulberry","Yellow Poplar","Yew") attr Sidewalk_Tree_2_Type = "None"

@Group("SIDEWALK LAYOUT","Sidewalk Components",9)@Order(1) @Order(1)@Range("None","Both","Right","Left")@Description("Determines whether an object is placed and what side of the street or walkways relevant objects are placed.") attr Sidewalk_Bus_Stop ="None" @Order(2) @Range("Far-side", "Mid-Block", "Near-side")@Description("Locates bus stop in the appropriate location. Far-side is right after the last intersection, Mid-Block is in the middle of the street, and Near-side is near to the next intersection.") attr Sidewalk_Bus_Stop_Location = "Far-side" @Order(3) @Range(-4,4)@Description("As it stands, the Bus Stop will be as far back as the Planting Width, if more adjustment is required, this attribute can be used to set back the Bus Stop further back or move it closer to the curb.") attr Sidewalk_Bus_Stop_Setback = 1 @Order(4)@Range("None","Both","Right","Left")@Description("Will place benches in between the spacing between Trees on the sidewalk side chosen.") attr Sidewalk_Benches ="None" @Order(5)@Range("None","Both","Right","Left")@Description("Determines whether an object is placed and what side of the street or walkways relevant objects are placed.") attr Parking_Meters ="None" @Order(6)@Range(0,20) @Description("Determines the spacing between each parking meter. No shape is created in the sections in between objects.") attr Parking_Meters_Spacing = 6.1

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 118

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

@Order(7) @Range(0,20) @Description("This attribute provides a way to adjust the starting location for parking meters so that they align with on- street parking.") attr Parking_Meter_Setback = 9 #pushes or pulls parking meters away @Order(8)@Range("None","Both","Right","Left")@Description("Determines whether an object is placed and what side of the street or walkways relevant objects are placed.") attr Sidewalk_Street_Lamps ="None" @Order(9)@Range(0,50) @Description("Determines the spacing between each Street Lamp. No shape is created in the sections in between objects.") attr Sidewalk_Street_Lamp_Spacing =10 @Order(10)@Range("None","Both","Right","Left")@Description("Determines whether an object is placed and what side of the street or walkways relevant objects are placed.") attr Traffic_Lights = "None" @Order(11) @Description("Will create a WayFinder near a bus stop.") attr Sidewalk_Way_Finder =false @Order(12) @Description("Will create 2 bike racks near a bus stop.") attr Sidewalk_Bike_Rack =false

@Group("POPULATION",80) @Range(0,300) @Order(1) @Description("Determines the number of vehicles per KM of road length loaded onto main throughways.") attr Vehicles_Per_KM = 0 @Range(0,1) @Order(2)@Description("Determines the approximate percentage of vehicles that are buses on main throughways.") attr Mixed_Traffic_Bus_Percentage = Default_Mix_Bus @Range(0,1) @Order(3)@Description("Determines the approximate percentage of vehicles that are taxis on main throughways.") attr Taxi_Percentage = 0.2 @Range(0,300) @Order(4)@Description("Determines the number of buses per KM of road length loaded onto bus lanes only.") attr Bus_Lane_Buses_Per_KM = 0 @Order(5) @Range(0,1) @Description("Higher the percentage, the higher the number of people loaded onto sidewalks.") attr People_Percentage = 0 @Order(6) @Range(0,100)@Description("Determines the number of bicyclists per KM of road length loaded onto bike lanes only.") attr Bicycles_Per_KM = 0 @Order(7)@Range(0,1) @Description("Higher the percentage, the higher the parking occupancy.") attr Parked_Car_Percentage = 0.3 @Order(8)@Hidden @Range(0,360) @Description("When parking is angled, this determines the angle of the vehicles placed in each right side angled parking spot.") attr Right_Parked_Car_Angle = _Right_Car_Angle @Order(9)@Hidden @Range(0,360)@Description("When parking is angled, this determines the angle of the vehicles placed in each left side angled parking spot.") attr Left_Parked_Car_Angle = _Left_Car_Angle

@Group("CUSTOM OBJECTS",90) @Order(1)@File("dae","dxf","gdb","kml","kmz","obj","osm","shp")@Description ("Make sure object/3D files are aligned so that UP is aligned to the Y Axis. Keep in mind objs were inserted assuming a standard alignment.") attr Street_Lamp_Object =Default_Lamp @Order(2)@File("dae","dxf","gdb","kml","kmz","obj","osm","shp")@Description ("Make sure object/3D files are aligned so that UP is aligned to the Y Axis. Keep in mind objs were inserted assuming a standard alignment.")

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 119

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D attr Parking_Meter_Object =Default_Parking_Meter @Order(3)@File("dae","dxf","gdb","kml","kmz","obj","osm","shp")@Description ("Make sure object/3D files are aligned so that UP is aligned to the Y Axis. Keep in mind objs were inserted assuming a standard alignment.") attr Traffic_Light_Object =Default_Traffic_Light @Order(4)@File("dae","dxf","gdb","kml","kmz","obj","osm","shp")@Description ("Make sure object/3D files are aligned so that UP is aligned to the Y Axis. Keep in mind objs were inserted assuming a standard alignment.") attr Wayfinder_Object =Default_WayFinder @Order(4)@File("dae","dxf","gdb","kml","kmz","obj","osm","shp")@Description ("Make sure object/3D files are aligned so that UP is aligned to the Y Axis. Keep in mind objs were inserted assuming a standard alignment.") attr Bench_Object =Default_Bench @Order(5)@File("dae","dxf","gdb","kml","kmz","obj","osm","shp")@Description ("Make sure object/3D files are aligned so that UP is aligned to the Y Axis. Keep in mind objs were inserted assuming a standard alignment.") attr Bike_Rack_Object =Default_Bike_Rack @Order(6)@File("dae","dxf","gdb","kml","kmz","obj","osm","shp")@Description ("Make sure object/3D files are aligned so that UP is aligned to the Y Axis. Keep in mind objs were inserted assuming a standard alignment.") attr Parklet_Object =Default_Parklet @Order(6)@File("dae","dxf","gdb","kml","kmz","obj","osm","shp")@Description ("Make sure object/3D files are aligned so that UP is aligned to the Y Axis. Keep in mind objs were inserted assuming a standard alignment.") attr Bus_Stop_Object =Default_BusStop @Group("REPORTING ATTRIBUTES","Paint Reports",100) #Default values taken from NACTO Urban Bike Design Guide, 2nd edition see comments for details. Costs can become dated due to inflation, change as needed.-DJW #Paint- pigment and binder, low durability (6 months-2 years based on conditions), low traffic ##Material cost: $.06 Sq. Ft. raw material/ $1.20-$1.60 Sq.Ft. installed. #Epoxy- epoxy/resin, moderate durability impacted by pavement quality( 3-5 years), moderate traffic ##Material cost: $1-$3 Sq. Ft. raw material/ $8-$11 Sq.Ft. installed. #MMA- acrylic based resin, moderate durability impacted by pavement quality (3-6 years), moderate traffic ##Material cost: $3-$4 Sq. Ft. raw material/ $8-$11 Sq.Ft. installed. #Thermoplastic- polymer resin, pigment, beads, filler- moderate-high durability (5 years or longer) ##Material cost: $3-$6 Sq. Ft. raw material/ $10-$14 Sq.Ft. installed. #Colored Pavement- bituminous pitch, sand/gravel/pigment-very durable, last as long as typical asphalt depending on conditions ##Material cost: Pigmented asphalt typically costs 30-50% more than non colored structural asphalt, thin overlay applications have varying costs. @Order(1)@Range(0,20)@Description("Useful Installed costs/sq.ft.: Paint $1.6, Epoxy/MMA: $8-11, Thermoplastic $10-14, Colored pavement: Varies. See comments for details-(Cntr+F NACTO Urban Bike Design Guide). Costs can become dated due to inflation, change as needed.") attr Green_Paint_Cost_Per_Square_FT = 1.6 @Order(2)@Range(0,20)@Description("Useful Installed costs/sq.ft.: Paint $1.6, Epoxy/MMA: $8-11, Thermoplastic $10-14, Colored pavement: Varies. See comments for details-(Cntr+F NACTO Urban Bike Design Guide). Costs can become dated due to inflation, change as needed.") attr White_Paint_Cost_Per_Square_FT = 1.6 @Order(3)@Range(0,20)@Description("Useful Installed costs/sq.ft.: Paint $1.6, Epoxy/MMA: $8-11, Thermoplastic $10-14, Colored pavement: Varies. See comments for details-(Cntr+F NACTO Urban Bike Design Guide). Costs can become dated due to inflation, change as needed.") attr Yellow_Paint_Cost_Per_Square_FT =1.6

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 120

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

@Order(4)@Range(0,20)@Description("Useful Installed costs/sq.ft.: Paint $1.6, Epoxy/MMA: $8-11, Thermoplastic $10-14, Colored pavement: Varies. See comments for details-(Cntr+F NACTO Urban Bike Design Guide). Costs can become dated due to inflation, change as needed.") attr Red_Paint_Cost_Per_Square_FT =1.6 @Order(5)@Range(0,20)@Description("Useful Installed costs/sq.ft.: Paint $1.6, Epoxy/MMA: $8-11, Thermoplastic $10-14, Colored pavement: Varies. See comments for details-(Cntr+F NACTO Urban Bike Design Guide). Costs can become dated due to inflation, change as needed.") attr Other_Paint_Cost_Per_Square_FT =1.6 ###################################################### #Bridge Attributes # ######################################################

@Group("BRIDGES",110) @Order(1) @Description("Determines the various conditions by which the bridge rule will turn on. Occulsion functions are used in the bridge rule and might have some errant behavior.") @Range("Off","Concrete Extrusion Only","On, By Elevation","On, Regardless","On, Show All Piers", "On, Flag Occlusions") attr Bridge_Display = "Off" @Group("BRIDGES") @Order(20) @Description("Determines the threshold distance above the standard elevation for the bridge rule to trigger based on Elevation.") attr Bridge_Starts_At = 3 @Group("BRIDGES") @Order(30) @Description("Determines how thick the supporting cement structure of the bridge is.") attr Bridge_Thickness = 1 @Group("BRIDGES") @Order(40) @Description("Determines the distance between Piers.") attr Pier_Distance = 23 @Group("BRIDGES") @Order(50) @Description("Determines the width of the Piers.") attr Pier_Width = 2.3

# Mapped Attributes (comming from graph) #@Group("LINK TO OBJECT ATTRIBUTES",99) @Hidden @Order(5)@Description("For internal use and reporting, must be set to 'Source=Object'.") attr connectionEnd = "STREET" # built in value attributes, needs to be sourced as Object (parent) @Hidden @Order(6)@Description("For internal use and reporting, must be set to 'Source=Object'.") attr connectionStart = "STREET" # built in value attributes, needs to be sourced as Object (parent) @Hidden @Order(7)@Description("For internal use and rep_getInitialCrosswalk(connectionStart)orting, must be set to 'Source=Object'.") attr valency = 0 @Hidden @Order(8)@Description("For internal use and reporting, must be set to 'Source=Object'.")//If these two do not connect, crosswalks with have no default width-they must be connected. attr sidewalkWidthLeft = rint(geometry.dv(0,unitSpace)) @Hidden @Order(9)@Description("For internal use and reporting, must be set to 'Source=Object'.")//If these two do not connect, crosswalks with have no default width-they must be connected. attr sidewalkWidthRight = rint(geometry.dv(0,unitSpace)) @Hidden @Order(10) @Description("For internal use and reporting, must be set to 'Source=Object'.") attr SidewalkWidth = 0 @Hidden @Order(11) @Description("For internal use and reporting, must be set to 'Source=Object'.")

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 121

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D attr SidewalkLength = 0 @Order(12) @Hidden @Description("For internal use and reporting, must be set to 'Source=Object'.") attr sidewalkSide = "Error" @Hidden @Order(13) @Description("For internal use and reporting, must be set to 'Source=Object'.") attr Thematics = _Thematic @Order(14) @Hidden @Description("For internal use and reporting, must be set to 'Source=Object'.") attr elevation = 0 # built in value attributes, needs to be sourced as Object (parent) ################## # User constants # ################## #Folder Constants const StreetTextureFolder = "Complete_Streets" const LanesFolder = StreetTextureFolder+"/Lanes" const SidewalkFolder = StreetTextureFolder+"/Sidewalks" const ObjectFolder = StreetTextureFolder+"/Street_Furniture_and_Objects" const GrassFolder = StreetTextureFolder+"/Sidewalks/Grass" const TrafficControlFolder = ObjectFolder +"/Dir_Traffic_controls" const TrafficSignFolder = ObjectFolder +"/Dir_Traffic_signs" const LampsFolder = ObjectFolder+"/Dir_Lamps" const MiscFolder = StreetTextureFolder+"/Misc" #Paint Constants const ThickPaintLineWidth = 0.5 const PaintLineWidth = 0.1016 #uvSpace 36/256 const Rumble_Strip_Len = 1.5 #FWHA 7 in wide per bump with 5 in ashpalt spacing const Rumble_Strip_Wid = .355 #FWHA-typically 12-16 in wide #SideWalk and Median Constants const Bench_Threshold_Width = .9 const Bench_Adjuster =.5 const Default_Pavement = SidewalkFolder+"/Concrete Clean Light.jpg" const Planting_Threshold_Width = 2 const Median_Stop_Adjuster =-1 const CurbtoPlantingGap =.2 const Curb_Depth = 0.1524 const BusStop_Length = 12.192 const Parklet_Shift = case Parking_Protection && _Minof(Left_Buffer_Width+Left_Bike_Lane_Width,Right_Buffer_Width+Right_Bike _Lane_Width)>0:0 else:-_EmptySpace #if parking protection is on a shift will lead to geometric collision, but it will choose to collide if oneside does not have a bikelane/buffer (check later). const Max_Sidewalk_Gap = 5.4 #change this if you want a smaller or larger gap between first tree splits and crosswalks #Bike Constants const Buffer_StartGap =.2 const Bike_Lane_Twoway_Distribution =.5 const BikeBox_Fraction =.75 const Buffer_Stripe_Length = 3.048 #Not used, but can be. const Center_Tube_Marker_Dist =.1 const _Default_Buffer_Object_Spacing= case Buffer_Type=="Curb Buffer with Trees":8 case Buffer_Type=="Cycle Track With Planters":2.5 else:1.5

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 122

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D const BikeBoxGeometryThreshold = Lane_Width *BikeBox_Fraction+_Maxof(Right_Bike_Lane_Width,Left_Bike_Lane_Width)-.1 #Vegetation Constants const Random_Grass =(fileRandom(GrassFolder + "/*.jpg")) #Parking Constants const Angled_Gap =5 #Object Model Constants const Default_Lamp = (LampsFolder +"/lamp.04.single.lod0.obj") const Default_Parking_Meter = (ObjectFolder+ "/parkingMeter.obj") const Default_Traffic_Light = (TrafficControlFolder+ "/traffic_light.02.big_with_lamp_and_sign.lod1.obj") const Default_WayFinder = (ObjectFolder+ "/WayFinder.obj") const Default_Bench = (ObjectFolder+ "/Bench.obj") const Default_Bike_Rack = (ObjectFolder+ "/Bike_Rack.obj") const Default_Parklet = (ObjectFolder+ "/Parklet_"+LOD_Setting+"_LOD.obj") const Default_BusStop = (ObjectFolder+ "/Bus_Stop.obj") const Default_Median_End = (ObjectFolder+ "/Median_End.obj") #####Reporting Constants##### #Reporting fractions are based on the pixel counts of the images in question. If you change the texture, and want to recalculate the fraction- Download GIMP, and use the histogram tool on a selection. const BikeSym_WhiteFraction = 0.2178 const BusSym_WhiteFraction = 0.1373 const BikeSymNoArr_WhiteFraction = 0.2570 const Buffer_WhiteFraction = 0.1934 const AngledPark_WhiteFraction = 0.0256 const ParallelPark_WhiteFraction = 0.0049 const Center_Line_Paint_Fraction = 0.55 const CenterLane_YellowFraction = 0.1194 const CenterTurnLane_YellowFraction = 0.1194#surprisingly this fraction is almost the same as the transitions...used it const CenterTurnLane_WhiteFraction = 0.0632#surprisingly this the avg arrow fraction is almost the same as the transitions...used it const Marking_Stop_WhiteFraction = 0.0796 const Marking_AvgArrow_WhiteFraction= 0.0666 #Is the average of the arrow textures, all of them were within 2% of each other error created by using an average is marginal const Marking_AvgPlain_WhiteFraction= 0.03 const Crosswalk_PaintFraction = .5 const HOV_Diamond_WhiteFraction = 0.0230 const MainLane_WhiteFraction = 0.0121 #Stop Distance Reporting Constants #AASHTO Numbers of interest: Brake reaction time: 2.5 seconds (capabilities of most drivers), 90 percent deceleration rate: 11.2 ft/s^2- reports assume at grade-future iterations will adapt to percent max slope. const Break_Reaction_Time = 2.5 #s const Deceleration_Rate = 11.2 #ft/s^2 const Design_Speed = case Speed_Limit_in_MPH>=40:Speed_Limit_in_MPH+7.5 else: Speed_Limit_in_MPH # see Below- value chosen is on a much lower end. Please adjust as seen fit. Decision basis below. # Source 8: TRB study on Design vs Speed limits: (Discussion informed by research #"Factors used to select design speed are functional classification, rural versus urban,

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 123

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

#and terrain (used by AASHTO); AASHTO Green Book procedure, legal speed limit, #legal speed limit plus a value (e.g., 5 or 10 mph [8.1 to 16.1 km/h]), anticipated volume, #anticipated operating speed, development, costs, and consistency (state DOTs); #and anticipated operating speed and feedback loop (international practices)." #... #While the profession has a goal to set posted speed limits near the 85th percentile #speed (and surveys say that 85th percentile speed is used to set speed limits), in reality, #most sites are set at less than the measured 85th percentile speed. #NACTO has different design philosophy. # "To counteract these gruesome and unnecessary injuries and fatalities, cities should utilize #speed control mechanisms that influence behavior, lower speeds, and in turn, reduce injuries #and fatalities. Embracing a proactive design approach on new and existing streets with the goal #of reducing speeds “may be the single most consequential intervention in reducing pedestrian injury and fatality."1" #Thus they put forward: "Proactive Urban Street Design: Target Speed = Design Speed = Posted Speed" #As a result of existing research relating to traffic speed and crash risk, and the fact that for the most part this #rule is designed for urban streets, if the speed limit is greater than or equal to 40 mph (5 above NACTO suggested speed), #The design speed is assumed to be Speed_Limit +7.5 other wise it is the Speed_Limit- a decision between the two philosophies. #This is a simple way to have "context sensitive" design speed, and more complex methods maybe considered down the line. const Brake_Reaction_Dist = 1.47*Design_Speed*Break_Reaction_Time const Braking_Dist = 1.075*((Design_Speed*Design_Speed)/Deceleration_Rate)# Time spent actually braking const Stopping_Sight_Dist = Brake_Reaction_Dist+Braking_Dist #Unit Conversion- in terms of number of unit per meter,meter^2, or meter^3- convert by unit *conversion factor==new unit const SquareFeet =10.7639 #per meter ^2 const Feet =3.28084 #per meter ^1 const Miles =0.00062137 #per meter ^1 const Inches =39.3701 #per meter ^1 const CubicFeet =35.3147 #per meter ^3 #Thematic Constants const Brightness="#d7d7d7" #Lane Constants: const Default_Mix_Bus= case Transit_Lane=="Bus Lane":.05 else: .2 ##################### #Tree.Generateed Rules # ##################### import Tree : "/ESRI.lib/rules/Plants/Plant_Loader.cga" # Taken from ESRI.lib and uses its assets. Keep this in mind when using rule.

################################################### # Initial attribute settings

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 124

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

# (to get a diversified default appeareance depending on initial shape, connection object attributes and randomness) # _Distribute_Right_Lanes = rint(Lane_Distribution*nLanesTotal)+_Transit_Lane_Dist_Adj #The Transit Lane Distribution adjuster only is active if the bus lane is put on the right to correct the bias from rounding up when transit lanes are present _getInitialLaneDistribution = case initialShape.startRule=="Roundabout": 1 case (streetWidth/ Lane_Width )>=2.2 : .5 case p(0.5) : 1 else : 0 _Initital_Transit_Lane_Sides= case Lane_Distribution==1: "Right" case Lane_Distribution==0: "Left" else: "Both" _getInitialCenterline = case oneWay || initialShape.startRule=="Junction": "none" # one way does not need centerline, neither do junctions nor roundabouts case _through : "yellow" # to be consistent always yellow for through traffic (= a street/junction/freeway without stop markings at least on one side) else : "yellow" # Else a white centerline

_getInitialStop(connection,nLanes) = case _hasStop(connection) && (streetLength>30): case connection=="ROUNDABOUT": 60%: "with stop marking" else: "arrows for right turn" case nLanes>2 : 25%: "line only" 25%: "with stop marking" 15%: "arrows on all lanes" 12%: "arrows on side lanes" 17%: "arrows for right turn" else: "line only" else : 35%: "line only" 45%: "with stop marking" 10%: "arrows on all lanes" 10%: "arrows on side lanes" else: "line only" else: "none"

_InititalSpeedLimit= case nLanesTotal>5: _Minof((nLanesTotal*10),75) else: 35

_getInitialCrosswalk(connection) = case _hasStop(connection) && streetLength>10 && _PedRank>.5: "continental" case _hasStop(connection) && streetLength>10: 85%: "continental" 5%: "ladder custom" 5%: "transverse" else: "none" else: "none"

_getInitialGap(connection)= case _hasStop(connection): 2.4 else: -2

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 125

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

_ParkingWidth(side) = case side=="Right": case Right_Parking_Type=="None": 0 case Right_Parking_Type=="Parallel": 2.44 #Door zone should have another 1-1.5 ft if parking is on inside else: 6.1 else: case Left_Parking_Type=="None": 0 case Left_Parking_Type=="Parallel": 2.44 #Door zone should have another 1-1.5 ft if parking is on inside else: 6.1 _ParkingLength(side) = case side=="Right": case Right_Parking_Type=="None": 0 case Right_Parking_Type=="Parallel": 6.1 else: 2.6 else: case Left_Parking_Type=="None": 0 case Left_Parking_Type=="Parallel": 6.1 else: 2.6 _Right_Car_Angle = case Right_Parking_Type =="Parallel": 0 case leftHandTraffic: 120 else: 60 _Left_Car_Angle = case Left_Parking_Type =="Parallel": 0 case leftHandTraffic: 120 else: 60 _Front_Parking_Spacing(Parking_Type) = case Front_Parking_Spacing!=0: Front_Parking_Spacing else: case Parking_Type=="Parallel": 3 case Parking_Type=="Angled Nose In": 6 case Parking_Type=="Angled Back In": 6 else: 1

_Rear_Parking_Spacing(Parking_Type) = case Rear_Parking_Spacing!=0:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 126

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Rear_Parking_Spacing else: case Parking_Type=="Parallel": 1 case Parking_Type=="Angled Nose In": 3 case Parking_Type=="Angled Back In": 3 else: 1 ################################################### # Internal utilities # #Street Length and Lanes @Hidden @Order(1) @Range(0,30) attr streetWidth = geometry.dv(0,unitSpace) # REALWORLD-distance in V-direction corresponds to width of street (in case the geometry does not contain rounded entry geometry) @Hidden @Order(2) @Range(0,30) attr Main_streetWidth =streetWidth- (_LeftSplitSum+_RightSplitSum+_centerWidth+_Transit_Lane_Widths) @Hidden @Order(3) @Range(1,6) attr laneWidth = geometry.dv(0,unitSpace) # note that TEXTURE-distance in V-direction corresponds to number of lanes (as generated by CityEngine) @Hidden @Order(4)#Only applies when rule is first set to determine if a median/centerlane is put in place. attr Initial_streetWidth = streetWidth- (_LeftSplitSum+_RightSplitSum+ PaintLineWidth*4) const streetLength = geometry.du(0,unitSpace) # REALWORLD-distance in U-direction corresponds to length of street const nLanesTotal = case rint(Main_streetWidth/Lane_Width )>0:floor(Main_streetWidth/ Lane_Width ) case floor(Main_streetWidth/ Lane_Width )<=0:0 else: 1 const nLanesLeft = floor(nLanesTotal- _Distribute_Right_Lanes )

########################################################################### ############################################ #Directional const rightHandTraffic = Traffic_Direction =="right-hand" const leftHandTraffic = !rightHandTraffic const oneWay = Lane_Distribution <=0 || Lane_Distribution>=1 #Used to be:_Distribute_Right_Lanes <=0 || nLanesLeft<=0 const DirectionalFlip = case rightHandTraffic:1 else:-1 # This is used to mirror UVs when right hand traffic is false const DirectionalRotation = case rightHandTraffic:0 else:180

#Other const _oneWayForward = (rightHandTraffic && Lane_Distribution>=1) || (leftHandTraffic && Lane_Distribution<=0) # in direction of graph segment? const _oneWayReverse = oneWay && !_oneWayForward const _stopBegin = case Stop_Begin =="none" || _oneWayForward: 0 else: 1 const _stopEnd = case Stop_End =="none" || _oneWayReverse: 0 else: 1 const _neighborBegin = case _hasStop(connectionStart):1 else: 0 const _neighborEnd = case _hasStop(connectionEnd):1 else: 0

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 127

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D const _crosswalkWidth = case _Maxof(sidewalkWidthLeft,sidewalkWidthRight)==0:3 else:(_Maxof(sidewalkWidthLeft,sidewalkWidthRight)+0.05)//changed to match width of largest sidewalk +0.05 (2 inches), if 0 default is 2. const _crosswalkBeginWidth = case Crosswalk_Begin =="none": 0 else: (Crosswalk_Width) const _crosswalkEndWidth = case Crosswalk_End =="none" : 0 else: (Crosswalk_Width) const _centerWidth = case oneWay: 0 case Center_Type=="Barrier":.98 case Center_Type=="Barrier & Shoulder":Center_Width case Center_Type != "None": Center_Width else:PaintLineWidth*4 const _Texture_Switch = case Display_Textures: 4 else: 0 # This switch will delete the opacity map UV if texturing is on- transparencys mess with the tree transparencies anyway. If you want UVset 4 you can change the 4 to a 999 and it should work...but only through an unhandled exception const _isnotCenterline = case Center_Type != "None":0 else:1 const _Bike_Paint_Adjuster = case Bike_Paint_Line_Sides=="Right"||Bike_Paint_Line_Sides=="None":1 else:2 const _EmptySpace =(streetWidth-(nLanesTotal* Lane_Width +_LeftSplitSum +_RightSplitSum+_centerWidth+_Transit_Lane_Widths))/2 # is Per Side-so combined is this *2 #Transit Lane Constants const _Transit_Lane_Widths = case Transit_Lane=="None":0 case Transit_Lane_Sides=="Both": 2*Transit_Lane_Width else:Transit_Lane_Width# Is the combined width of transit lanes not in Center const _Rt_Transit_Lane_Width= case Transit_Lane=="None":0 case Transit_Lane_Sides=="Right" || Transit_Lane_Sides=="Both":Transit_Lane_Width else: 0 const _Lt_Transit_Lane_Width= case Transit_Lane=="None":0 case Transit_Lane_Sides=="Left" || Transit_Lane_Sides=="Both":Transit_Lane_Width else: 0 const _Transit_Lane_Dist_Adj= case Transit_Lane=="None":0 case oneWay:0 case Transit_Lane_Sides=="Right":-1 else:0 #all this constant does is adjust the lane distribution so that transit lanes do not overly interfere with lane distribution calculations for right transit lanes (we want it to count as a "Lane") const _Transit_Lane_Count = case Transit_Lane=="None":0 case Transit_Lane_Sides=="Both":2 else:1 const _Rt_Transit_Lane_Count= case Transit_Lane=="None"||Transit_Lane=="Left":0 else:1 const _Lt_Transit_Lane_Count= case Transit_Lane=="None"||Transit_Lane=="Right":0 else:1 #To keep the units exact, we do not distribute the lanes, we fill empty space with concrete (drainage). const _through = connectionEnd=="STREET" || connectionStart=="STREET" || connectionEnd=="JUNCTION" || connectionStart=="JUNCTION" || connectionEnd=="FREEWAY" || connectionStart=="FREEWAY" # Vegetation and Hardscape costs ------const TreeCostAverage = 750 const GrassSurfaceCostAverage = 10 # In square meters const HardscapePaverCost = 25 # In square meters

###################################################

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 128

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

#Functions # ################################################### #Split Based and Misc Functions _RightSplitSum= Right_Bike_Lane_Width + Right_Parking_Width + Right_Buffer_Width #Generates right road side features that need to be fractions of lanewidths

_LeftSplitSum= Left_Bike_Lane_Width + Left_Parking_Width + Left_Buffer_Width #Generates right road side features that need to be fractions of lanewidths

_Bike_Box_Gap(street_side)= case street_side=="Begin" && Left_Bike_Box:Bike_Box_Length/2 case street_side=="End" && Right_Bike_Box:Bike_Box_Length/2 else:0

_MaxSplitSum= case _RightSplitSum>=_LeftSplitSum: _RightSplitSum else: _LeftSplitSum _Orientation_Modified_SplitSum= _MaxSplitSum-_BikeSense_Modifier

_MaxParkingSum= case _MaxSplitSum==_RightSplitSum: Right_Parking_Width else: Left_Parking_Width

_MaxBufferSum= case _MaxSplitSum==_RightSplitSum: Right_Buffer_Width else: Left_Buffer_Width

_Transit_Lane_Width_Switch(dir,Location)= case Transit_Lane=="None": 0 case dir==0 && (Transit_Lane_Sides=="Both" || Transit_Lane_Sides=="Right"): case Location==Transit_Lane_Position: # Each call of this function has a string defining its location. Transit_Lane_Width else: 0 case dir==2 && (Transit_Lane_Sides=="Both" || Transit_Lane_Sides=="Left"): case Location==Transit_Lane_Position: # Each call of this function has a string defining its location. Transit_Lane_Width else: 0 else: 0 _tooShort(length,goal_len)= # This function will be equal to 0 (making a split length 0 via *) if the length of a segment is less than a goal length). case length

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 129

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

#Stop Tex Functions _hasStop(neighbor) = neighbor=="CROSSING" || neighbor=="ROUNDABOUT" || neighbor=="JUNCTION_ENTRY"||neighbor=="JUNCTION" _stopTex(stopType,lanenumber,lanestotal) = case stopType == "with stop marking" : case rightHandTraffic: "_stop_word" else: "_stop_word_mirrored" case stopType == "arrows on all lanes" : "_stop_arrows_all_"+str((case lanenumber+1>5:5 else:lanenumber+1)) case stopType == "arrows on side lanes" : "_stop_arrows_sides_"+str((case lanenumber+1==1:1 case lanenumber+1==lanestotal:4 else:3)) case stopType == "arrows for right turn": "_stop_arrows_right_"+str((case lanenumber+1>4:4 else:lanenumber+1)) else : "_stop_strip" _stopTexPaintFractions(markings,lanenumber) =

case markings=="_stop_word"|| markings== "_stop_word_mirrored": Marking_Stop_WhiteFraction case markings=="_stop_arrows_all_*":Marking_AvgArrow_WhiteFraction case markings=="_stop_arrows_sides_1"|| markings=="_stop_arrows_sides_4":Marking_AvgArrow_WhiteFraction case markings=="_stop_arrows_right_1"|| markings=="_stop_arrows_right_4":Marking_AvgArrow_WhiteFraction else: Marking_AvgPlain_WhiteFraction

#Paintcontrol and Bus Furniture functions _PaintLineControl(side,Control_String)= case side=="Left": case Control_String=="Both": 1 case Control_String=="Right": 0 case Control_String=="Left": 1 else: 0 else: case Control_String=="Both": 1 case Control_String=="Right": 1 case Control_String=="Left": 0 else: 0 _Bus_Furniture_Base(Center_Section,Location,Facing_Side)= case Median_Bus_Stop=="None":#2 0 case Location=="Far and Near Side" && Median_Bus_Stop_Location!="Mid- Block": case Facing_Side==0: case Median_Bus_Stop=="Left"||Median_Bus_Stop=="Both": BusStop_Length else: 0 else: case Median_Bus_Stop=="Right"||Median_Bus_Stop=="Both": BusStop_Length else: 0 case Median_Bus_Stop_Location=="Mid-Block" && Facing_Side==1: BusStop_Length #This works for the Mid_Block Section, right and left are handled in another #function (below) for mid-block because they occupy the same shape.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 130

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

case Facing_Side==0:#2 case Median_Bus_Stop=="Right"||Median_Bus_Stop=="Both":#3 case Median_Bus_Stop_Location==Location:#4 BusStop_Length else:#4 0 else:0#3 case Facing_Side==2:#2 case Median_Bus_Stop=="Left" ||Median_Bus_Stop=="Both":#3 case Median_Bus_Stop_Location==Location:#4 BusStop_Length else:#4 0 else:0#3 else:#2 0 _Bus_Sidewalk_Base(Location)= case Sidewalk_Bus_Stop=="None": 0 case sidewalkSide==Sidewalk_Bus_Stop || Sidewalk_Bus_Stop=="Both": case Sidewalk_Bus_Stop_Location==Location: BusStop_Length else: 0 else:# 0 _Median_Midblock_Switch(Side,Pad_Type)= case Pad_Type=="WalkWay": case Median_Bus_Stop=="Both": 0 case Median_Bus_Stop=="Right": case Side==0: 0 else: .5 case Median_Bus_Stop=="Left": case Side==2: 0 else: .5 else: 0 else: case Median_Bus_Stop=="Both": .5 case Median_Bus_Stop=="Right": case Side==0: .5 else: 0 case Median_Bus_Stop=="Left": case Side==2: .5 else: 0 else: 0 _Bus_Alloc(Location) =.5 #Allows user to adjust by location if customized.

_Bike_Rack_Alloc(Location) =

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 131

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

case Location== "Median" || Location=="Boulevard": case Median_Bike_Rack: .2 else: 0 else: case Sidewalk_Bike_Rack:.2 else: 0 _WayFinder_Alloc(Location) = case Location== "Median" || Location=="Boulevard": case Median_Way_Finder: .3 else: 0 else: case Sidewalk_Way_Finder:.2 else: 0

_Sidewalk_CrossStop_Gap(Dir,Begin)= #Limits the amount of gap to 5.4 meters (3 m sidewalk+2.4 crosswalkgap) Keep trees out of crosswalk/clear view for drivers at intersections. case Dir==0: case Begin=="Begin": _Minof(_crosswalkEndWidth+ End_Crosswalk_To_Stop_Bar,Max_Sidewalk_Gap) else: _Minof(_crosswalkBeginWidth+ Begin_Crosswalk_To_Stop_Bar,Max_Sidewalk_Gap) else: case Begin=="Begin": _Minof(_crosswalkBeginWidth+ Begin_Crosswalk_To_Stop_Bar,Max_Sidewalk_Gap) else: _Minof(_crosswalkEndWidth+ End_Crosswalk_To_Stop_Bar,Max_Sidewalk_Gap)

_uScale = case geometry.du(0,unitSpace)>10: 1 case geometry.du(0,unitSpace)>4 : 1/2 # in case the street is too short, we only use half of the texture else : 1/6 # if even shorter, we use only the start of the texture (i.e. centerline only)

#Parking Functions: _ParParkedFacing(Side) = case Side=="Right":# This makes the park car facing adapt to whether the street is one way etc. case Lane_Distribution<=0: 2 case Lane_Distribution>=1: 0 else: 0 else: #Only other option is Left case Lane_Distribution<=0: 2 case Lane_Distribution>=1: 0 else: 2 _Parklet_OneWay_Shift(Rotation)= # This function serves to make sure the parklet is not colliding with cars on oneway streets-it modifies the adjustment based on parking length case Lane_Distribution==1: case Rotation==180: -1 else:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 132

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

1 case Lane_Distribution==0: case Rotation==180: 1 else: -1 else: 1 #Misc Functions #_isEven(number) = (rint(abs(number))%2) == 0 #Make number positive, round to nearest integer just in case of 6 being 5.99999999999999, or 6.000000000000001. #_isOdd(number) = !_isEven(number)

_Maxof(num1,num2)= #Finds the max of two numbers case num1>=num2: num1 else: num2 _Minof(num1,num2)= #Finds the min of two numbers case num1<=num2: num1 else: num2 _PaintCost(paintColor)= case paintColor=="green": Green_Paint_Cost_Per_Square_FT case paintColor=="white": White_Paint_Cost_Per_Square_FT case paintColor=="yellow": Yellow_Paint_Cost_Per_Square_FT case paintColor=="red": Red_Paint_Cost_Per_Square_FT else: Other_Paint_Cost_Per_Square_FT

################################################ #Thematic Functions _Usage(Usage) = case Display_Thematics=="Usage": #Please construct your own usage zones if the current ones are not sufficient-Colors based on NACTO illustrations case Usage=="Pedestrian": "#FFFFFF" case Usage=="Conflict Zones": "#F9ECB7" case Usage=="Bikeways": "#6AAA70" case Usage=="Auto": "#C3C2C0" case Usage=="Transit": "#AF4E57" case Usage=="Plantings": "#B5DC98" else: "#000000" else: Thematics #Attribute that diverts to _Thematic _Thematic = case Display_Thematics=="Thematics Off": Brightness # Started as: "#d7d7d7" as constant

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 133

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

case Display_Thematics=="Solid Color": Solid_Color case Display_Thematics=="Bike Stress": getHexColorString(1-_BikeRank, _BikeRank, 0) case Display_Thematics=="Auto Stress": getHexColorString(1-_AutoRank,_AutoRank,0) case Display_Thematics=="Transit Stress": getHexColorString(1-_TransitRank,_TransitRank,0) case peakRunoffDisplayOn: "#FFFFFF" case Display_Thematics=="Pedestrian Stress": getHexColorString(1-_PedRank,_PedRank,0) else: Brightness _BikeSense_Modifier =#changes combined "bike protection" width based orientation-with splitsum creates distance from through lane case ! Buffer_Protection && Parking_Protection : (_MaxBufferSum) case Buffer_Protection && ! Parking_Protection : (_MaxParkingSum) case Buffer_Protection && Parking_Protection : 0 else: (_MaxParkingSum + _MaxBufferSum) ########################### #Stress Metrics Rankings- Create your own or edit the existing ########################### #Transit_Lane_Count adjusts the lane total based on the presence of one (+1) or two (+2) bus lanes. Only matters for reporting. _BikeRank =#Adapted from MTI Report 11-19 # Does not take into account Boulevard Cycle Paths case Parking_Protection && _MaxParkingSum>1 && (Right_Bike_Lane_Width>0 || Left_Bike_Lane_Width>0) : case floor(((nLanesTotal/2)+(_Transit_Lane_Count/2)))<=1 && Speed_Limit_in_MPH<=25 && Level_of_Blockage=="Rare" &&_Orientation_Modified_SplitSum>=4.572: 1 #LTS 1- case (Speed_Limit_in_MPH<25)||(floor(((nLanesTotal/2)+(_Transit_Lane_Count/2)))< =2 && Speed_Limit_in_MPH<=30 && Level_of_Blockage=="Rare" &&_Orientation_Modified_SplitSum>=4.2672): .66 #LTS 2 case (floor(((nLanesTotal/2)+(_Transit_Lane_Count/2)))<=2 && Speed_Limit_in_MPH<=35 && Level_of_Blockage!="Frequent" &&_Orientation_Modified_SplitSum>=4.1148): .33 #LTS 3 else: 0 #LTS 4

case (Right_Bike_Lane_Width>0 || Left_Bike_Lane_Width>0) &&_MaxParkingSum<=1: # Bike Lanes not along parking lane case floor(((nLanesTotal/2)+(_Transit_Lane_Count/2)))<=1 && Speed_Limit_in_MPH<=30 && Level_of_Blockage=="Rare" && _Orientation_Modified_SplitSum>=1.8288: 1 #LTS 1 case (Speed_Limit_in_MPH<25)|| (Speed_Limit_in_MPH<=35 &&(floor(((nLanesTotal/2)+(_Transit_Lane_Count/2)))<=(case Center_Type =="Median":2 else: 1)&& Level_of_Blockage=="Rare" && _Orientation_Modified_SplitSum<1.8288)): .66 #LTS 2-speed limit has no effect so it jumps to next highest speed limit

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 134

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

case (Speed_Limit_in_MPH<=35 && Level_of_Blockage!="Frequent"): .33 #LTS 3 else: 0 #LTS 4 else: case (((nLanesTotal)+_Transit_Lane_Count)<=3 && Speed_Limit_in_MPH<=25): 1 #LTS 1 case (((nLanesTotal)+_Transit_Lane_Count)<=3 && Speed_Limit_in_MPH<=30): .66 #LTS 2 case (((nLanesTotal)+_Transit_Lane_Count)<=4 && Speed_Limit_in_MPH<=30): .33 #LTS 3 else: 0 #LTS 4 _PedRank =#Rule creator criteria-a road with low speed limits and less lanes is good OR a road with good separation between cars and pedestrians and a wider sidewalk is better case (rint((nLanesTotal/2)+(_Transit_Lane_Count/2))<=1 && Speed_Limit_in_MPH<=20 && _centerWidth<=7) || (_MaxSplitSum>=5 && _Maxof(sidewalkWidthLeft,sidewalkWidthRight)>=3.3 && Speed_Limit_in_MPH<=30): 1 case (rint((nLanesTotal/2)+(_Transit_Lane_Count/2))<=2 && Speed_Limit_in_MPH<=25) || (_MaxSplitSum>=3 && _Maxof(sidewalkWidthLeft,sidewalkWidthRight)>=2.5 && Speed_Limit_in_MPH<=35): .8 case (rint((nLanesTotal/2)+(_Transit_Lane_Count/2))<=2 && Speed_Limit_in_MPH<=30) || (_MaxSplitSum>=2 && _Maxof(sidewalkWidthLeft,sidewalkWidthRight)>=1.8 && Speed_Limit_in_MPH<=40): .6 case (rint((nLanesTotal/2)+(_Transit_Lane_Count/2))<=3 && Speed_Limit_in_MPH<=35) &&(_Maxof(sidewalkWidthLeft,sidewalkWidthRight)>=1.8): .4 case (rint(((nLanesTotal/2)+(_Transit_Lane_Count/2)))<=4 && Speed_Limit_in_MPH<=40) && (_Maxof(sidewalkWidthLeft,sidewalkWidthRight)>=1.524): .2 else: 0 _AutoRank = #Criteria is simply based on lanewidths, on- street parking presence,lane number (does it enable passing?), and reduction of turning conflicts (is there a center turn lane). The top rank is practically high way conditions with a shoulder (shoulders reduce driver stress about accidents /reduce variance is highway performance by providing vehicle storage). case ((rint((nLanesTotal/2)+(_Transit_Lane_Count/2)))>=3 && Lane_Width >=3.6576 && _Maxof(Left_Parking_Width,Right_Parking_Width)==0) || (Center_Type=="Center Turn Lane" && (rint((nLanesTotal/2) +_Transit_Lane_Count/2))>=2 && Lane_Width >=3.3528 && _Maxof(Left_Parking_Width,Right_Parking_Width)==0)&& (Buffer_Type=="Shoulder" || Center_Type=="Barrier & Shoulder") : 1 case ((rint((nLanesTotal/2) +(_Transit_Lane_Count/2)))>=2 && Lane_Width >=3.6576 && _Maxof(Left_Parking_Width,Right_Parking_Width)==0) || (Center_Type=="Center Turn Lane" && (rint((nLanesTotal/2)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 135

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

+_Transit_Lane_Count/2))>=2 && Lane_Width >=3.3528 && _Maxof(Left_Parking_Width,Right_Parking_Width)==0): .8 case ((rint((nLanesTotal/2) +(_Transit_Lane_Count/2)))>=2 && Lane_Width >=3.358 && (Left_Parking_Width==0 || Right_Parking_Width==0)) || (Center_Type=="Center Turn Lane" && (rint((nLanesTotal/2) +_Transit_Lane_Count/2))>=1 && Lane_Width >=3.048 && _Maxof(Left_Parking_Width,Right_Parking_Width)==0): .6 case ((rint((nLanesTotal/2) +(_Transit_Lane_Count/2)))>=1 && Lane_Width >=3.048 && (Left_Parking_Width==0 || Right_Parking_Width==0)) || (Center_Type=="Center Turn Lane" && (rint((nLanesTotal/2) + _Transit_Lane_Count/2))>=1 && Lane_Width >=3.048 && (Left_Parking_Width==0 ||Right_Parking_Width==0)): .4 case ((rint((nLanesTotal/2) + (_Transit_Lane_Count/2)))>=1 && Lane_Width >=3.048) || (Center_Type=="Center Turn Lane" && (rint((nLanesTotal/2) +_Transit_Lane_Count/2))>=1 && Lane_Width >=3.048): .2 else: 0

_TransitRank = #Criteria based on whether or not there are, proper lane widths, transit dedicated lanes, painted red is better,boulevard transit lanes are best performing (no ability to get into transit lane)-HOV lane is treated a like a preferential bus lane- essentially ranks a roads ability to provide preferential service case Bus_Lane_Color== "red" && Transit_Lane =="Bus Lane" && Transit_Lane_Width >=3.35 && (rint((nLanesTotal/2))+(_Transit_Lane_Count/2))<=2 && Transit_Lane_Sides =="Both" ||Center_Type=="Boulevard" && Boulevard_Configuration=="Bus Lanes" && Boulevard_Inside_Width>=6.5: 1 case Bus_Lane_Color== "red" && Transit_Lane =="Bus Lane": .8 case Transit_Lane !="None" && Lane_Width >=3.048 && (rint(((nLanesTotal/2))+(_Transit_Lane_Count/2)))<=3: .6 case Transit_Lane !="None" && Lane_Width >=3.048: .4 case (rint(((nLanesTotal/2)) + _Transit_Lane_Count/2))<=2: .2 else: 0 #This is the code for the decimal number to hex converter, and it is used to create thematics based on a numerical #critera that is normalized on a 0 to 1 scale. #Number 0 to 1 decimal to Hexstring converter code from Chris Wilkins #Hex string and 256 values from normal values (0 to 1). convertNormalTo256(normalValue) = rint(normalValue * 255) getSixteensDigitFrom256(value256) = floor(value256 / 16) getOnesDigitFrom256(value256) = value256 - (getSixteensDigitFrom256(value256) * 16) # Just # getHex256(sixteens, ones) = (sixteens * 16) + ones getHex256String(sixteens, ones) = hexString(sixteens) + hexString(ones) getHexColorString(normalR, normalG, normalB) = "#" + getHex256String(

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 136

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

getSixteensDigitFrom256(convertNormalTo256(normalR)) , getOnesDigitFrom256(convertNormalTo256(normalR)) ) + getHex256String( getSixteensDigitFrom256(convertNormalTo256(normalG)) , getOnesDigitFrom256(convertNormalTo256(normalG)) ) + getHex256String( getSixteensDigitFrom256(convertNormalTo256(normalB)) , getOnesDigitFrom256(convertNormalTo256(normalB)) ) hexString(hexValue) = case hexValue == 0 : "0" case hexValue == 1 : "1" case hexValue == 2 : "2" case hexValue == 3 : "3" case hexValue == 4 : "4" case hexValue == 5 : "5" case hexValue == 6 : "6" case hexValue == 7 : "7" case hexValue == 8 : "8" case hexValue == 9 : "9" case hexValue == 10 : "A" case hexValue == 11 : "B" case hexValue == 12 : "C" case hexValue == 13 : "D" case hexValue == 14 : "E" case hexValue == 15 : "E" case hexValue == 16 : "F" else : "" #Error.

################################ # Normalization to 0 to 1 range. const NormalMin = 0 const NormalMax = 1 #Use the following functions if you had data that can be fed into the _Rank functions: #dataValueAdj(dataValueOriginal,Max_Data_Value, Min_Data_Value) = # case dataValueOriginal < Min_Data_Value: Min_Data_Value # case dataValueOriginal > Max_Data_Value: Max_Data_Value # else: dataValueOriginal

#normalValue(dataValue,Max_Data_Value,Min_Data_Value) = # NormalMin + (((dataValueAdj(dataValue,Max_Data_Value,Min_Data_Value) - Min_Data_Value ) # * ( NormalMax - NormalMin )) # / ( Max_Data_Value - Min_Data_Value)) ################################################### ################################################### ##

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 137

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

## RULES ## ##

################################################### # Street Lane Texturing #

@StartRule # split away the crosswalks at the beginning (if any) using the special UVSET 1 Street --> #DeleteUV if texturing is off case _uScale==1: #IF the Street is long enough continue normally. report("LTS (0 to 1 scale):Bicycle Stress", _BikeRank) report("LTS (0 to 1 scale):Pedestrian Stress", _PedRank) report("LTS (0 to 1 scale):Transit Stress", _TransitRank) report("LTS (0 to 1 scale):Auto Stress", _AutoRank) report("Speed:Level Braking Distance (ft)",Braking_Dist) report("Speed:Level Braking Reaction Distance (ft)",Brake_Reaction_Dist) report("Speed:Level Stopping Sight Distance (ft)",Stopping_Sight_Dist)#Design Value is rounded to nearest 5 feet. BridgeMain split(u,uvSpace,1){_crosswalkBeginWidth/10: Asphalt(true,1,"Auto") | _crosswalkBeginWidth : Crosswalk( Crosswalk_Begin ,1) | ~1 : StreetWithCrosswalkEnd } else: #If the street is too short no stop lines, no bike boxes. report("LTS (0 to 1 scale):Bicycle Stress", _BikeRank) report("LTS (0 to 1 scale):Pedestrian Stress", _PedRank) report("LTS (0 to 1 scale):Transit Stress", _TransitRank) report("LTS (0 to 1 scale):Auto Stress", _AutoRank) report("Speed:Braking Distance (ft)",Braking_Dist) report("Speed:Braking Reaction Distance (ft)",Brake_Reaction_Dist) report("Speed:Stopping Sight Distance (ft)",Stopping_Sight_Dist) BridgeMain set( Right_Bike_Box ,false) set( Left_Bike_Box ,false) set( Stop_Begin ,"none") set( Stop_End ,"none") StreetWithEntries

# split away the crosswalks at the end (if any) using the special UVSET 2 StreetWithCrosswalkEnd --> split(u,uvSpace,2){ _crosswalkEndWidth/10: Asphalt(true,1,"Auto") | _crosswalkEndWidth : Crosswalk( Crosswalk_End ,2) | ~1 : CrossWalkGap}

CrossWalkGap--> #This solution while imperfect and vulnerable to distortion prevents UVspace/UnitSpace conflicts from cutting geometry. User can adjust relative gaps to compensate.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 138

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

split(u,unitSpace,0) {( Begin_Crosswalk_To_Stop_Bar ):Asphalt(true,1,"Auto") |~1:StreetWithEntries |( End_Crosswalk_To_Stop_Bar ):Asphalt(true,1,"Auto")} # split into the two street sides (if not oneway) StreetWithEntries -->

split(v,unitSpace,0) {~1:Drainage |(_RightSplitSum+ _Distribute_Right_Lanes* Lane_Width+_Rt_Transit_Lane_Width):scaleUV(0,DirectionalFlip,1)StopBox("Rig htSide")# Will flip with a change in driving direction | _centerWidth : scaleUV(0,DirectionalFlip,1)CenterLineReporting# Will flip with a change in driving direction |(_LeftSplitSum+nLanesLeft* Lane_Width+_Lt_Transit_Lane_Width) :scaleUV(0,DirectionalFlip,1)StopBox("LeftSide")# Will flip with a change in driving direction |~1:Drainage}

#The StopBox rule creates both the stop line and Bikebox when they are selected, #and then moves the rest of the space left to the dedicated lane spaces. StopBox(RuleChoice)--> case RuleChoice=="RightSide": case Right_Bike_Box && geometry.dv(0,unitSpace)>BikeBoxGeometryThreshold :#Must be enough room, turned on. split(u,unitSpace,0) {~1:RightSide| Bike_Box_Length :BikeBoxCreation("Right")} else: split(u,unitSpace,0) {~1:RightSide|_stopEnd*ThickPaintLineWidth:AsphaltPainted("white",true,1,"A uto")}

case RuleChoice=="LeftSide": case Left_Bike_Box && geometry.dv(0,unitSpace)>BikeBoxGeometryThreshold: #Must be enough room, turned on. split(u,unitSpace,0) { Bike_Box_Length :BikeBoxCreation("Left")|~1:LeftSide} else: split(u,unitSpace,0) {_stopBegin*ThickPaintLineWidth:AsphaltPainted("white",true,1,"Auto")|~1:Le ftSide} else: case RuleChoice=="RightSide": split(u,unitSpace,0) {~1:RightSide|_stopEnd*ThickPaintLineWidth:AsphaltPainted("white",true,1,"A uto")} else: split(u,unitSpace,0) {_stopBegin*ThickPaintLineWidth:AsphaltPainted("white",true,1,"Auto")|~1:Le ftSide}

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 139

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

# Divides the two street sides into left subsection made up of splitspace (holds bike, parking, and buffer),repeater conventional lanes, and transit lanes (activiated by Location Switch). RightSide--> split(v,unitSpace,0){(_Transit_Lane_Width_Switch(0,"Sidewalk Side")):Transit_Lane_Reporting(0) |_RightSplitSum:RightSplitSpace |(_Transit_Lane_Width_Switch(0,"Right Most Lane")):Transit_Lane_Reporting(0) |( _Distribute_Right_Lanes* Lane_Width ):Lanes(0,(case rightHandTraffic: Stop_End else: Stop_Begin)) |(_Transit_Lane_Width_Switch(0,"Left Most Lane")):Transit_Lane_Reporting(0)} # Divides the two street sides into left subsection made up of splitspace (holds bike, parking, and buffer),repeater conventional lanes, and transit lanes (activiated by Location Switch). LeftSide--> split(v,unitSpace,0){(_Transit_Lane_Width_Switch(2,"Left Most Lane")): scaleUV(0,-1,-1) Transit_Lane_Reporting(2) |(nLanesLeft* Lane_Width ): translateUV(0,0,-geometry.vMax) scaleUV(0,-1,-1) # mirror the uv coords Lanes(2,(case rightHandTraffic: Stop_Begin else: Stop_End) ) |(_Transit_Lane_Width_Switch(2,"Right Most Lane")):scaleUV(0,-1,-1) Transit_Lane_Reporting(2) |_LeftSplitSum:LeftSplitSpace |(_Transit_Lane_Width_Switch(2,"Sidewalk Side")):scaleUV(0,-1,-1) Transit_Lane_Reporting(2)} # "Sidewalk Side","Right Most Lane","Left Most Lane"

## ##Note about Dir Variable-#Dir represents direction 0 for right, 2 for left. Any other number is to handle an exception. ## ## # split lanes into a single lane each and respective transit lane (location based transit lanes) Lanes(dir,stopType) --> split(v,unitSpace,0){{Lane_Width : LaneReporting(dir,split.total,split.index,stopType,"MainLanes")}*}

# prepare the uv coordinates and texture the shape LaneMarkings(dir,lanenumber,markings) --> # is used for textures for intersection approach (stop,turn arrows etc). tileUV(0,~14,~Lane_Width ) # the tileUV operation makes sure that one unit in u-space corresponds to approx 14 meters, the v- coord is not touched in the case of 0 as parameter normalizeUV(0,v,separatePerFace) texture(StreetTextureFolder + "/Lanes/lanes_4"+markings+"_14x14m.jpg") deleteUV(_Texture_Switch) color(_Usage("Auto"))#If Display Thematics==Usage, goes to usage, if not, Thematic. AsphaltPainted("white",false,_stopTexPaintFractions(markings,lanenumb er),"Auto") Asphalt(false,(1-_stopTexPaintFractions(markings,lanenumber)),"Auto") #TODO-More combinations MainLaneMarkings(dir,lanenumber,markings)-->

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 140

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

tileUV(0,~14,~ Lane_Width ) # the tileUV operation makes sure that one unit in u-space corresponds to approx 14 meters, the v- coord is not touched in the case of 0 as parameter scaleUV(0,_uScale,1/4) # flip direction if needed, handle short lanes with _uScale, and scaling the v coord for the texture (e.g. a street with 2 lanes has v coords from 0 to 2, this means it has to map onto 0 to 2/8 on our texture with its 8 lanes) texture(StreetTextureFolder + "/Lanes/lanes_4"+markings+"_14x14m.jpg") deleteUV(_Texture_Switch) color(_Usage("Auto"))#If Display Thematics==Usage, goes to usage, if not, Thematic. AsphaltPainted("white",false,MainLane_WhiteFraction,"Auto") Asphalt(false,(1-MainLane_WhiteFraction),"Auto") #This rule contains the reports for the lanes defined by the lanes rule, no bike/pking lanes etc. LaneReporting(dir,lanestotal,lanenumber,stopType,laneType)--> report("Lane: Actual Lane Width (ft)",geometry.dv(0,unitSpace)*Feet) #Used to provide lane widths in feet report("Lane: Car Lane Area (m^2)",geometry.area) ConventionalLane(dir,lanestotal,lanenumber,stopType)

################################# #Lane choice Region # #################################

###################### #Convential Lane Set Up # ConventionalLane(dir,lanestotal,lanenumber,stopType)--> case stopType=="none" && lanenumber==lanestotal-1:# Makes sure with no stop type last lane has no lane with contiguous stripes Asphalt(true,1,"Auto") VehiclesOnLane(dir) case stopType!="none" && (lanenumber==lanestotal-1):# Makes sure with no stop type last lane has no lane with contiguous stripes split(u,unitSpace,0){ ~1: Asphalt(true,1,"Auto") | 14: LaneMarkings(dir,lanenumber,_stopTex(stopType,lanenumber,lanestotal)) } VehiclesOnLane(dir) else: # Makes basic lanes that that are not next to the last lane or a bus/hov lane (if they are on). split(u,unitSpace,0){ ~1: MainLaneMarkings(dir,lanenumber,"_stripes_white") | 14: LaneMarkings(dir,lanenumber,_stopTex(stopType,lanenumber,lanestotal))} VehiclesOnLane(dir)

####################################################### ####################################################### #Multimodal Lane Creation and Non-Car Lane Splits Transit_Lane_Reporting(dir)--> #Reports based on shape geometry and sends to allocator report("Lane-Transit: Transit Lane Width (ft)",geometry.dv(0,unitSpace)*Feet) #Used to provide lane widths in feet report("Lane-Transit: Transit Lane Area (m^2)",geometry.area)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 141

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Transit_Lane_Allocator(dir)

Transit_Lane_Allocator(dir)--> #Allocates the texture rule based on what type of transit lane is selected. case Transit_Lane=="Bus Lane": Buslane_Texture_Rule(dir) case Transit_Lane=="HOV Lane": HOVlane_Texture(dir) else: #Do not leave blank geometry. Buslane_Texture_Rule(dir)

Buslane_Texture_Rule(dir)--> split(v,unitSpace,0){PaintLineWidth*_PaintLineControl("Right", Transit_Paint_Line_Sides ):AsphaltPainted("white",true,1,"Transit") #Level 1-First split indentation

|~1:split(u,unitSpace,0){2:AsphaltPainted(Bus_Lane_Color,true,1,"Tran sit") #Level 2- sub-split indentation | Transit_Lane_Width:BuslaneStamp(dir) |~ Transit_Symbol_Spacing :AsphaltPainted(Bus_Lane_Color,true,1,"Transit") |{ Transit_Lane_Width :BuslaneStamp(dir) |~ Transit_Symbol_Spacing :AsphaltPainted(Bus_Lane_Color,true,1,"Transit")}* | Transit_Lane_Width :BuslaneStamp(dir)

|2:AsphaltPainted(Bus_Lane_Color,true,1,"Transit")}

|PaintLineWidth*_PaintLineControl("Left", Transit_Paint_Line_Sides ):AsphaltPainted("white",true,1,"Transit")} BusOnLane(dir)

BuslaneStamp(dir)--> scaleUV(0,1,DirectionalFlip)# Will flip with a change in driving direction rotateUV(0,90) tileUV(0,~Transit_Lane_Width,~ Transit_Lane_Width ) texture(LanesFolder+"/BusLaneStamp"+(case Bus_Lane_Color=="black":"_black" else:"")+".jpg")#If Black change the stamp chosen, might make more elegant later. deleteUV(_Texture_Switch) color(_Usage("Transit"))#If Display Thematics==Usage, goes to usage, if not, Thematic. AsphaltPainted(Bus_Lane_Color,false,1,"Transit")

AsphaltPainted("white",false,BusSym_WhiteFraction,"Transit")

HOVlane_Texture(dir)--> split(v,unitSpace,0){PaintLineWidth*2*_PaintLineControl("Right", Transit_Paint_Line_Sides ):AsphaltPainted("yellow",true,1,"Transit") #Level 1-First split indentation

|~1:split(u,unitSpace,0){2:Asphalt(true,1,"Transit") #Level 2- sub-split indentation

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 142

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

| Transit_Lane_Width:HOVlaneStamp(dir) |~ Transit_Symbol_Spacing :Asphalt(true,1,"Transit") |{ Transit_Lane_Width :HOVlaneStamp(dir) |~ Transit_Symbol_Spacing :Asphalt(true,1,"Transit")}* | Transit_Lane_Width :HOVlaneStamp(dir)

|2:Asphalt(true,1,"Transit")}

|PaintLineWidth*2*_PaintLineControl("Left", Transit_Paint_Line_Sides ):AsphaltPainted("yellow",true,1,"Transit")} VehiclesOnLane(dir)

HOVlaneStamp(dir)--> scaleUV(0,1,DirectionalFlip)# Will flip with a change in driving direction rotateUV(0,90) tileUV(0,~ Transit_Lane_Width ,~Transit_Lane_Width )#Lane width is used for texture size because it can repeat if need for large streets and because it allows the text to stay in scale with that of a Bus or car. texture(LanesFolder+"/HOV_Diamond"+".jpg")#If Black change the stamp chosen, might make more elegant later. deleteUV(_Texture_Switch) color(_Usage("Transit"))#If Display Thematics==Usage, goes to usage, if not, Thematic. AsphaltPainted("white",false,HOV_Diamond_WhiteFraction,"Transit") Asphalt(false,(1-HOV_Diamond_WhiteFraction),"Transit") ############################################################## #Non-Carlane Split Space- This is the space where #parking, bike, and buffer lanes are constructed.

RightSplitSpace-->

scaleUV(0,1,case Parking_Protection :-1 else:1) split(v,unitSpace,0){Right_Parking_Width :ParkingLane("Right",Right_Parking_Type,Right_Parking_Length,Right_Parking_ Width) |( Right_Bike_Lane_Width + Right_Buffer_Width ):RightBikeLaneSpace("list")}

LeftSplitSpace-->

scaleUV(0,1,case Parking_Protection :-1 else:1) split(v,unitSpace,0){( Left_Bike_Lane_Width + Left_Buffer_Width ):LeftBikeLaneSpace("list") | Left_Parking_Width :ParkingLane("Left",Left_Parking_Type,Left_Parking_Length,Left_Parking_Widt h)}

#################### #####BikeLane Rules- Includes Lane and Buffer #Bike Space-Total LeftBikeLaneSpace(list)-->

scaleUV(0,1,case Buffer_Protection : -1 else:1) scaleUV(0,1,case Parking_Protection :-1 else:1)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 143

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

split(v,unitSpace,0) { Left_Bike_Lane_Width :LeftBikeLaneSection(list) |Left_Buffer_Width :BikeBuffer(Left_Buffer_Width,2)}

RightBikeLaneSpace(list)-->

scaleUV(0,1,case Buffer_Protection : -1 else:1) scaleUV(0,1,case Parking_Protection :-1 else:1) split(v,unitSpace,0) {Right_Buffer_Width :BikeBuffer(Right_Buffer_Width,0) |Right_Bike_Lane_Width :RightBikeLaneSection(list)} #BikeLane Start

RightBikeLaneSection(list)--> case Bike_Lane_Type=="One-way": BikeLane(1,Right_Bike_Lane_Width) else: split(v,unitSpace,0) {'.5:BikeLane(- 1,Right_Bike_Lane_Width)|~1:BikeLane(1,Right_Bike_Lane_Width)}

LeftBikeLaneSection(list)--> case Bike_Lane_Type=="One-way": BikeLane(-1,Left_Bike_Lane_Width) else: split(v,unitSpace,0) {'.5:BikeLane(-1,Left_Bike_Lane_Width)| ~1:BikeLane(1,Left_Bike_Lane_Width)}

BikeLane(sideflip,Width)-->#Was Left,now both, fairly modular Bikes((case sideflip==1:0 else: 2),(case Bike_Lane_Type=="Two- way":Width/2 else: Width)) color(_Usage("Bikeways"))#If Display Thematics==Usage, goes to usage, if not, Thematic. scaleUV(0,sideflip,sideflip) split(v,unitSpace,0){PaintLineWidth*_PaintLineControl("Left", Bike_Paint_Line_Sides):BikeLaneLines #Level 1-First split indentation

|~1:split(u,unitSpace,0){2:AsphaltPainted(Bike_Lane_Color,true,1,"Bik eways") #Level 2- sub-split indentation | Width :BikeLaneStamp(Width ,Bike_Lane_Color+"_stamp.jpg",Bike_Lane_Color) |~ Bike_Symbol_Spacing :AsphaltPainted(Bike_Lane_Color,true,1,"Bikeways") |{ Width :BikeLaneStamp(Width ,Bike_Lane_Color+"_stamp.jpg",Bike_Lane_Color) |~ Bike_Symbol_Spacing :AsphaltPainted(Bike_Lane_Color,true,1,"Bikeways")}* | Width :BikeLaneStamp(Width,Bike_Lane_Color+"_stamp.jpg",Bike_Lane_Color) | Bike_Conflict_Spacing :ConflictZone(Bike_Lane_Color)

|1:AsphaltPainted((Bike_Lane_Color),true,1,"Bikeways")}

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 144

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

|PaintLineWidth*_PaintLineControl("Right", Bike_Paint_Line_Sides):BikeLaneLines}

BikeLaneLines--> split(u,unitSpace,0){~1:AsphaltPainted("white",true,1,"Bikeways")

|Bike_Conflict_Spacing:ConflictZone("white")

|1:AsphaltPainted("white",true,1,"Bikeways")}

BikeLaneStamp(Stamp_Width,FileEnd, Color)--> scaleUV(0,1,DirectionalFlip)# Will flip with a change in driving direction tileUV(0,~Stamp_Width,~Stamp_Width) texture(LanesFolder+"/street_1bike_"+FileEnd) deleteUV(_Texture_Switch) color(_Usage("Bikeways"))#If Display Thematics==Usage, goes to usage, if not, Thematic. AsphaltPainted(Color,false,1,"Bikeways") AsphaltPainted("white",false,(case FileEnd==Color+"_stamp_noarrow.jpg":BikeSymNoArr_WhiteFraction else:BikeSym_WhiteFraction),"Bikeways")

ConflictZone(passedcolor)--> split(u,unitSpace,0){~1: AsphaltPainted(passedcolor,true,1,"Conflict Zones")|~1:Asphalt(true,1,"Conflict Zones")}*

#Buffer Rules (Some Shared Rules in Median).

BikeBuffer(Buffer_Width,Dir)--> case Buffer_Type=="Painted Stripes": color(_Usage("Bikeways"))#If Display Thematics==Usage, goes to usage, if not, Thematic. Striped_Buffer(Buffer_Width) case Buffer_Type=="Solid White": color(_Usage("Bikeways"))#If Display Thematics==Usage, goes to usage, if not, Thematic. AsphaltPainted("white",true,1,"Bikeways") case Buffer_Type=="Asphalt": Asphalt(true,1,"Auto") case Buffer_Type=="Shoulder": Shoulder(Dir) case Buffer_Type=="Curb Buffer with Trees" || Buffer_Type=="Curb Buffer with Plantings": color(_Usage("Bikeways"))#If Display Thematics==Usage, goes to usage, if not, Thematic. Raised_Curb("Buffer",1) case Buffer_Type=="Curb Buffer": color(_Usage("Bikeways"))#If Display Thematics==Usage, goes to usage, if not, Thematic. Raised_Curb("Buffer",1) case Buffer_Type=="Cycle Track With Planters": color(_Usage("Bikeways"))#If Display Thematics==Usage, goes to usage, if not, Thematic. Striped_Buffer(Buffer_Width)

ObjectSetup("Planter",Buffer_Object_Spacing,"/Planter_"+LOD_Setting+" _LOD.obj",Buffer_Width) case Buffer_Type=="Cycle Track With Tubular Markers":

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 145

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

color(_Usage("Bikeways"))#If Display Thematics==Usage, goes to usage, if not, Thematic. Striped_Buffer(Buffer_Width) ObjectSetup("Tubular Marker",Buffer_Object_Spacing,"/Tubular_Marker.obj",Buffer_Width) else: color(_Usage("Bikeways"))#If Display Thematics==Usage, goes to usage, if not, Thematic. Striped_Buffer(Buffer_Width)

ObjectSetup(Object_Type,distance_between_objs,File_Extension,Width)--> alignScopeToAxes(y) alignScopeToGeometry(yUp,largest,longest) split(u,unitSpace,0){~.5:NIL

|{Width*.9:Cycle_Track_ObjIns(Object_Type,File_Extension,Width) |~distance_between_objs:NIL}* |~.2:NIL}

Cycle_Track_ObjIns(Object_Type,Buffer_File,Width)--> alignScopeToAxes(y) alignScopeToGeometry(yUp,largest,0) s(0,0,0) i(ObjectFolder+Buffer_File) deleteUV(_Texture_Switch) report("Objects: "+Object_Type+ " Count",1) center(xz)

Buffer_Tree_Split--> split(u,unitSpace,0) {Buffer_StartGap:NIL |{~Buffer_Object_Spacing/2:NIL |1:Tree_Setup("Buffer", Sidewalk_Tree_1_Percentage , Sidewalk_Tree_1_Type,Sidewalk_Tree_2_Type ) |~Buffer_Object_Spacing/2:NIL}* |Buffer_StartGap:NIL}

Buffer_Top--> case Buffer_Type=="Curb Buffer with Trees": Sidewalk_Planting Buffer_Tree_Split case Buffer_Type=="Curb Buffer": Buffer_Texture case Buffer_Type=="Curb Buffer with Plantings": Sidewalk_Planting else: Buffer_Texture

Buffer_Texture--> tileUV(0,2,2) texture(Sidewalk_Texture) deleteUV(_Texture_Switch) scaleUV(0, Sidewalk_Texture_Scale, Sidewalk_Texture_Scale) rotateUV(0, Sidewalk_Texture_Rotation)

Shoulder(Dir)--> case Dir==0:

split(v,unitSpace,0){PaintLineWidth:AsphaltPainted("white",true,1,"Au to")

|Rumble_Strip_Wid:Rumble_Strip

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 146

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

|~1:Asphalt(true,1,"Auto")} else: split(v,unitSpace,0){~1:Asphalt(true,1,"Auto")

|Rumble_Strip_Wid:Rumble_Strip

|PaintLineWidth:AsphaltPainted("white",true,1,"Auto")}

Striped_Buffer(Buffer_Width)--> rotateUV(0,90) tileUV(0,~ Buffer_Width ,~Buffer_Width*1.5 ) texture(LanesFolder+"/street_1bike_"+"buffer2.jpg") deleteUV(_Texture_Switch) AsphaltPainted("black",false,1-Buffer_WhiteFraction,"Bikeways") AsphaltPainted("white",false,Buffer_WhiteFraction,"Bikeways")

#Bike Box Creation Rule- controls the splits for the bike box. Works best if Bike lane is adjacent to sidewalk. BikeBoxCreation(side)--> case side=="Left": split(v, unitSpace,0) {PaintLineWidth:AsphaltPainted("white",true,1,"Bikeways")| ~1:split(u, unitSpace,0){

PaintLineWidth:AsphaltPainted("white",true,1,"Bikeways") |~1:BikeBoxSymbol(side)

|ThickPaintLineWidth:AsphaltPainted("white",true,1,"Bikeways")} |Left_Bike_Lane_Width - PaintLineWidth*_Bike_Paint_Adjuster:split(u,unitSpace,0){

PaintLineWidth:AsphaltPainted("white",true,1,"Bikeways")|~1:AsphaltPa inted(Bike_Box_Color_Override,true,1,"Bikeways")}

|PaintLineWidth:AsphaltPainted("white",true,1,"Bikeways")} else: split(v, unitSpace,0) {PaintLineWidth:AsphaltPainted("white",true,1,"Bikeways") | Right_Bike_Lane_Width - PaintLineWidth*_Bike_Paint_Adjuster:split(u,unitSpace,0){

~1:AsphaltPainted(Bike_Box_Color_Override,true,1,"Bikeways")|PaintLin eWidth:AsphaltPainted("white",true,1,"Bikeways")} |~1:split(u, unitSpace,0){

ThickPaintLineWidth:AsphaltPainted("white",true,1,"Bikeways") |~1:BikeBoxSymbol(side)

|PaintLineWidth:AsphaltPainted("white",true,1,"Bikeways")}

|PaintLineWidth:AsphaltPainted("white",true,1,"Bikeways")}

BikeBoxSymbol(side)--> case side=="Left": scaleUV(0,-1,1) split(v,unitSpace,0) {~ Bike_Box_Symbol_Spacing /2:AsphaltPainted(Bike_Box_Color_Override ,true,1,"Bikeways")

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 147

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

| Lane_Width *BikeBox_Fraction: BikeLaneStamp( Lane_Width ,Bike_Box_Color_Override +"_stamp_noarrow.jpg",Bike_Box_Color_Override) |~ Bike_Box_Symbol_Spacing /2:AsphaltPainted(Bike_Box_Color_Override ,true,1,"Bikeways")}* else: scaleUV(0,1,1) split(v,unitSpace,0) {~ Bike_Box_Symbol_Spacing /2:AsphaltPainted(Bike_Box_Color_Override,true,1,"Bikeways") | Lane_Width *BikeBox_Fraction:BikeLaneStamp( Lane_Width ,Bike_Box_Color_Override +"_stamp_noarrow.jpg",Bike_Box_Color_Override) |~ Bike_Box_Symbol_Spacing /2:AsphaltPainted(Bike_Box_Color_Override,true,1,"Bikeways")}*

######################## #####Parking Lane Rules ParkingLane(Side,ParkingType,ParkingLength,ParkingWidth)-->

case ParkingType=="Parallel": color(_Usage("Auto"))#If Display Thematics==Usage, goes to usage, if not, Thematic. scaleUV(0, case Lane_Distribution==1: -1 case Lane_Distribution==0: 1 else: case Side=="Right":-1 else:1 ,1) split(u,unitSpace,0) {~_Front_Parking_Spacing(ParkingType):Asphalt(true,1,"Auto")

|{ParkingLength:ParkingSpace(Side,ParkingType,split.index,split.total ,ParkingLength,ParkingWidth)}*

|~_Rear_Parking_Spacing(ParkingType):Asphalt(true,1,"Auto")} else: color(_Usage("Auto"))#If Display Thematics==Usage, goes to usage, if not, Thematic. scaleUV(0,case Side=="Right":-1 else:1,1)

split(u,unitSpace,0){~_Front_Parking_Spacing(ParkingType):Asphalt(tru e,1,"Auto")# Make sure to pass right parameters/type shoudl work here

|{ParkingLength:ParkingSpace(Side,ParkingType,split.index,split.total ,ParkingLength,ParkingWidth)}*

|~_Rear_Parking_Spacing(ParkingType):Asphalt(true,1,"Auto")}

ParkingSpace(Side,ParkingType,SpaceNumber,TotalSpacesonSide,ParkingLength,P arkingWidth)--> case rand(0,100)<=Parklet_Percentage && SpaceNumber>1: Asphalt(true,1,"Pedestrian") Parklet_Insert(ParkingLength,case Side=="Right":0 else: 180)

case ParkingType=="Angled Nose In":

AngledNoseIn(Side,ParkingType,SpaceNumber,TotalSpacesonSide,ParkingLe ngth,ParkingWidth)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 148

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

case ParkingType=="Parallel":

ParallelParking(Side,ParkingType,SpaceNumber,TotalSpacesonSide,Parkin gLength,ParkingWidth) else:

AngledNoseOutParking(Side,ParkingType,SpaceNumber,TotalSpacesonSide,P arkingLength,ParkingWidth)

Parklet_Insert(ParkingLength,Rotation)--> alignScopeToGeometry(yUp, largest, 1) rotateScope(0,Rotation,0) s(scope.sx-Parklet_Shift,0,scope.sz) t(Parklet_Shift,0,_Parklet_OneWay_Shift(Rotation)*(ParkingLength/8)) report("Objects: Parklet Count",1) i(Parklet_Object) deleteUV(_Texture_Switch)

AngledNoseIn(Side,ParkingType,SpaceNumber,TotalSpacesonSide,ParkingLength,P arkingWidth)--> AngledParkingCar((case Side=="Right":0 else:2),ParkingType,ParkingLength, ParkingWidth,SpaceNumber) scaleUV(0,-1, (case Side=="Right": (case Parking_Protection :1 else:-1) else: (case Parking_Protection :-1 else:1))) tileUV(0,~ParkingLength,~ParkingWidth) texture(LanesFolder+"/AngledParking.jpg") deleteUV(_Texture_Switch) color(_Usage("Auto"))#If Display Thematics==Usage, goes to usage, if not, Thematic. ParkingReport(Side,ParkingType,case SpaceNumber==1: false else:true)#Don't include last spot

AngledNoseOutParking(Side,ParkingType,SpaceNumber,TotalSpacesonSide,Parking Length,ParkingWidth)--> AngledParkingCar((case Side=="Right":0 else:2),ParkingType,ParkingLength, ParkingWidth,SpaceNumber) scaleUV(0,1,(case Side=="Right": (case Parking_Protection :1 else:- 1) else: (case Parking_Protection :-1 else:1))) tileUV(0,~ParkingLength,~ParkingWidth) texture(LanesFolder+"/AngledParking.jpg") deleteUV(_Texture_Switch) color(_Usage("Auto"))#If Display Thematics==Usage, goes to usage, if not, Thematic. ParkingReport(Side,ParkingType,case SpaceNumber==1: false else:true) #Don't include last spot

ParallelParking(Side,ParkingType,SpaceNumber,TotalSpacesonSide,ParkingLengt h,ParkingWidth)--> case SpaceNumber==TotalSpacesonSide-2:#1 from index total, 1 from additional split ParallelParkingCar(_ParParkedFacing(Side),ParkingLength, ParkingWidth)# Fix Parking Angle on oneway Streets scaleUV(0,1,(case Side=="Right":

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 149

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

(case Parking_Protection :1 else:- 1) else: (case Parking_Protection :-1 else:1))) tileUV(0,~ParkingLength,~ParkingWidth) texture(LanesFolder+"/ParallelParkFront.jpg") deleteUV(_Texture_Switch) color(_Usage("Auto"))#If Display Thematics==Usage, goes to usage, if not, Thematic. ParkingReport(Side,ParkingType,true)

case SpaceNumber==1:

scaleUV(0,1,(case Side=="Right": (case Parking_Protection :1 else:- 1) else: (case Parking_Protection :-1 else:1))) tileUV(0,~ParkingLength,~ParkingWidth) texture(LanesFolder+"/ParallelParkRear.jpg") deleteUV(_Texture_Switch) color(_Usage("Auto"))#If Display Thematics==Usage, goes to usage, if not, Thematic. ParkingReport(Side,ParkingType,false)#it is the last texture, it does not make an actual parking space.

else: ParallelParkingCar(_ParParkedFacing(Side),ParkingLength, ParkingWidth)# Fix Parking Angle on oneway Streets-TODO scaleUV(0,1,(case Side=="Right": (case Parking_Protection :1 else:- 1) else: (case Parking_Protection :-1 else:1))) tileUV(0,~ParkingLength,~ParkingWidth) texture(LanesFolder+"/ParallelParkMid.jpg") deleteUV(_Texture_Switch) color(_Usage("Auto"))#If Display Thematics==Usage, goes to usage, if not, Thematic. ParkingReport(Side,ParkingType,true)

ParallelParkingCar(dir,ParkingLength, ParkingWidth) --> case p(Parked_Car_Percentage): ParallelParkingCarStep2(dir,ParkingLength, ParkingWidth)

else: NIL

ParallelParkingCarStep2(dir,ParkingLength, ParkingWidth) --> alignScopeToGeometry(yUp, 0, (case dir==2:3 else:1))#If distortion is too high, the edge numbers might change making this look weird. Hard to evaluate options. rotateScope(0,DirectionalRotation,0) s(0,0,0) i(vehicleAsset("car")) t(0,0,(ParkingLength/2)+1) center(x) deleteUV(_Texture_Switch)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 150

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

AngledParkingCar(dir,ParkingType,ParkingLength, ParkingWidth,SpaceNumber)-- > case p(Parked_Car_Percentage)&& SpaceNumber!=1: #Don't include last spot case (dir == 2): AngledParkingCarStep2(-1,case ParkingType=="Angled Nose In":1 else:-1,Left_Parked_Car_Angle,ParkingLength, ParkingWidth)

else: AngledParkingCarStep2(1,case ParkingType=="Angled Nose In":1 else:-1,Right_Parked_Car_Angle,ParkingLength, ParkingWidth) else: NIL

AngledParkingCarStep2(DirsenseFlip,NoseSenseFlip,Rotation_Angle,ParkingLeng th, ParkingWidth)--> alignScopeToGeometry(yUp, 0, (case DirsenseFlip==-1:3 else:1))#If distortion is too high, the edge numbers might change making this look weird. Hard to evaluate options. s(0,0,0) t((ParkingWidth/2.3),0,(ParkingLength)) # Suggest changing base concept later. rotateScope(0,NoseSenseFlip*-Rotation_Angle,0) i(vehicleAsset("car")) deleteUV(_Texture_Switch)

ParkingReport(Side,ParkingType,Rear_Edge_Case)-->#This edge case parameter only makes sure the correct number of parking spaces is reported. case Rear_Edge_Case: report("Parking: "+Side+" Parking Space Area (m^2)",geometry.area) report("Parking: Total Parking Space Area (m^2)",geometry.area) AsphaltPainted("black",false,case ParkingType=="Parallel":1- ParallelPark_WhiteFraction else:1-AngledPark_WhiteFraction,"Auto") AsphaltPainted("white",false,case ParkingType=="Parallel":ParallelPark_WhiteFraction else:AngledPark_WhiteFraction,"Auto") else: AsphaltPainted("black",false,case ParkingType=="Parallel":1- ParallelPark_WhiteFraction else:1-AngledPark_WhiteFraction,"Auto") AsphaltPainted("white",false,case ParkingType=="Parallel":ParallelPark_WhiteFraction else:AngledPark_WhiteFraction,"Auto") ################################################### # Centerline and Center Section Code # CenterLineReporting--> report("Center: Center Section Area",geometry.area) color(_Usage("Auto"))#If Display Thematics==Usage, goes to usage, if not, Thematic. CenterSpace

CenterSpace --> case Center_Type =="Median": Raised_Curb("Median",1)# IF a median, and this will be use dto make a different rule case Center_Type =="Boulevard": Boulevard case Center_Type =="Barrier": split(u,unitSpace,0) {{1:Barrier }*|1:Asphalt(true,1,"Auto")} Asphalt(true,1,"Auto") case Center_Type =="Barrier & Shoulder":

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 151

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

split(u,unitSpace,0) {{1:Barrier }*|1:NIL} split(v,unitSpace,0) {Rumble_Strip_Wid:Rumble_Strip |~1:Asphalt(true,1,"Auto") |Rumble_Strip_Wid:Rumble_Strip} case Center_Type=="Center Turn Lane": Center_Turn_Lane case Centerline_Color =="none": split(u,unitSpace,0){ _stopBegin*21: CenterLineMarkings("single_white") | ~1 : CenterLineMarkings("stripes_white") | _stopEnd*21 : CenterLineMarkings("single_white") } else: CenterLineMarkings("double_"+ Centerline_Color )

Center_Turn_Lane--> split(u,unitSpace,0){(_Bike_Box_Gap("Begin")): Bike_Box_Left_Turn_Gap("Begin")

|_neighborBegin*_stopBegin*ThickPaintLineWidth:AsphaltPainted("white" ,true,1,"Auto")

|(_tooShort(geometry.du(0,unitSpace),30))*_neighborBegin*_stopBegin*1 8:CenterTurnLaneStamp("Transition_",180) |~ Lane_Width :CenterTurnLaneStamp("",90) |{~ Lane_Width :CenterTurnLaneStamp("",90) | Lane_Width :CenterTurnLaneStamp("Turn_",90) | ~Lane_Width :CenterTurnLaneStamp("",90)}* |~ Lane_Width :CenterTurnLaneStamp("",90)

|(_tooShort(geometry.du(0,unitSpace),30))*_neighborEnd*_stopEnd*18:Ce nterTurnLaneStamp("Transition_",0)

|_neighborEnd*_stopEnd*ThickPaintLineWidth:AsphaltPainted("white",tru e,1,"Auto") |(_Bike_Box_Gap("End")): Bike_Box_Left_Turn_Gap("End")}

Boulevard--> case Boulevard_Configuration=="Open Space": #If open space send to different split set up. split(v,unitSpace,0){~(case WalkWay_Width==0:1 else:WalkWay_Width):Raised_Curb("Boulevard",0)

|Boulevard_Inside_Width:Raised_Curb("Open Space",0) |~(case WalkWay_Width==0:1 else:WalkWay_Width):scaleUV(0,-1,-1)Raised_Curb("Boulevard",2)} else: # If any type of lane set to Typical split set up. split(v,unitSpace,0){~(case WalkWay_Width==0:1 else:WalkWay_Width):Raised_Curb("Boulevard",0) |Boulevard_Inside_Width/2- (Boulevard_Center_Width/2):Boulevard_StopBars(0) |Boulevard_Center_Width:Boulevard_Center |Boulevard_Inside_Width/2- (Boulevard_Center_Width/2): Boulevard_StopBars(2)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 152

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

|~(case WalkWay_Width==0:1 else:WalkWay_Width):scaleUV(0,-1,-1)Raised_Curb("Boulevard",2)} Boulevard_StopBars(dir)--> case Boulevard_Configuration=="Bus Lanes": case dir==0: split(u,unitSpace,0) {~1:Buslane_Texture_Rule(dir)|_stopEnd*ThickPaintLineWidth:AsphaltPainted(" white",true,1,"Auto")} else: split(u,unitSpace,0) {_stopBegin*ThickPaintLineWidth:AsphaltPainted("white",true,1,"Auto")|~1:sc aleUV(0,-1,-1)Buslane_Texture_Rule(dir)} case Boulevard_Configuration=="Normal Lanes": case dir==0: split(u,unitSpace,0) {~1:Center_Normal_Lanes(dir)|_stopEnd*ThickPaintLineWidth:AsphaltPainted("w hite",true,1,"Auto")} else: split(u,unitSpace,0) {_stopBegin*ThickPaintLineWidth:AsphaltPainted("white",true,1,"Auto")|~1:sc aleUV(0,-1,-1)Center_Normal_Lanes(dir)} else: case dir==0: split(u,unitSpace,0) {~1:BikeLane(1,geometry.dv(0,unitSpace))|_stopEnd*ThickPaintLineWidth:Aspha ltPainted("white",true,1,"Auto")} else: split(u,unitSpace,0) {_stopBegin*ThickPaintLineWidth:AsphaltPainted("white",true,1,"Auto")|~1:Bi keLane(-1,geometry.dv(0,unitSpace))} Boulevard_Center--> case Boulevard_Center_Type=="Center Line": CenterLineMarkings("double_"+ (case Centerline_Color=="none":"yellow" else:Centerline_Color)) case Boulevard_Center_Type=="Median": Raised_Curb("Boulevard Center",1) #HAS no bus stop case Boulevard_Center_Type=="Curb Buffer": Raised_Curb("Boulevard Center",1) #HAS no bus stop case Boulevard_Center_Type=="Tubular Markers": ObjectSetup("Tubular Marker",Center_Tube_Marker_Dist,"/Tubular_Marker.obj",1) Asphalt(true,1,"Auto") case Boulevard_Center_Type=="Chain Link Fence": split(u,unitSpace,0) {.3:NIL|~1:Fence("Boulevard Center")|.3:NIL}#The split only makes it so the fence poles are not put in the curb. Raised_Curb("Boulevard Center",1) case Boulevard_Center_Type=="Gate Fence": split(u,unitSpace,0) {.3:NIL|~1:Fence("Boulevard Center")|.3:NIL}#The split only makes it so the fence poles are not put in the curb. Raised_Curb("Boulevard Center",1) else: CenterLineMarkings("double_"+(case Centerline_Color=="none":"yellow" else:Centerline_Color))

Center_Normal_Lanes(Dir)--> split(v,unitSpace,0) {~1:Drainage |{ Lane_Width :MainLaneMarkings(0,split.index,"_stripes_white") VehiclesOnLane(Dir)}*

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 153

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

| Lane_Width :Asphalt(true,1,"Auto") VehiclesOnLane(Dir)}

CenterLineMarkings(tex) --> normalizeUV(0,v,collectiveAllFaces) tileUV(0,~14,0) texture(StreetTextureFolder + "/Lanes/centerline_" + tex + "_14m.jpg") deleteUV(_Texture_Switch) AsphaltPainted(case Centerline_Color=="none":"white" else:Centerline_Color,false,Center_Line_Paint_Fraction,"Auto")#Slight over estimate for none-case. color(_Usage("Auto"))#If Display Thematics==Usage, goes to usage, if not, Thematic.

CenterTurnLaneStamp(texture_choice,degree)-->

normalizeUV(0,v,collectiveAllFaces) rotateUV(0,degree) tileUV(0, '1 ,'1) texture(LanesFolder+"/Center_"+texture_choice+"Lane"+".jpg") deleteUV(_Texture_Switch) color(_Usage("Auto"))#If Display Thematics==Usage, goes to usage, if not, Thematic.

AsphaltPainted("yellow",false,CenterTurnLane_YellowFraction,"Auto") AsphaltPainted("white",false,case texture_choice=="Turn_" || texture_choice=="Transition_":CenterTurnLane_WhiteFraction else: 0,"Auto")

Bike_Box_Left_Turn_Gap(street_side)--> #If Bike boxes are on for the correct side case street_side=="Begin": split (u,unitSpace,0) {PaintLineWidth:AsphaltPainted("white",true,1,"Conflict Zones")

|~1:split(v,unitSpace,0)

{PaintLineWidth:AsphaltPainted("white",true,1,"Conflict Zones")| ~1:Asphalt(true,1,"Conflict Zones")}} case street_side=="End": split (u,unitSpace,0) {~1:split(v,unitSpace,0){ ~1:Asphalt(true,1,"Conflict Zones")|PaintLineWidth:AsphaltPainted("white",true,1,"Conflict Zones")}

|PaintLineWidth:AsphaltPainted("white",true,1,"Conflict Zones")} else: Asphalt(true,1,"Conflict Zones")

Barrier--> alignScopeToGeometry(yUp, largest, 0) i(ObjectFolder+"/Jersey_Barrier.obj") report("Objects: Jersey Barrier Count",1) r(0,90,0) s(1,1,1.2) center(x) deleteUV(_Texture_Switch) #Raised Curb and Street_Pavement- #This code is a fairly modular is called by several different rules. #Dir is 0 for right, 2, left, 1 middle or not assigned. Raised_Curb(Location,Dir)--> Cut_And_Fill_Reporting(Location) Street_Lamp_Center(Location,Dir) split(u,unitSpace,0){ Curb_Depth:Curbs_Mass(true)|#End Curb

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 154

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

~1:split(v,unitSpace,0){ Curb_Depth:Curbs_Mass(false)

|~1:Street_Pavement(0,Location,Dir) | Curb_Depth:Curbs_Mass(false)} | Curb_Depth:Curbs_Mass(true)}#End Curb

Street_Pavement(Boulevard_Side,Location,Dir)--> #Boulevard side is used when arranging the Benches where the WalkWay Side and Side of Boulevard are both needed #if it is not needed is is filled with string=="None" case Location=="Buffer": extrude(world.y, Sidewalk_Height ) comp(f){top=Buffer_Top} case Location=="Median": extrude(world.y, Sidewalk_Height ) comp(f){top=Median_Top_Setup(Dir)} case Location=="Boulevard": extrude(world.y, Sidewalk_Height ) comp(f){top=Boulevard_Top(Dir) } case Location=="Boulevard Center": extrude(world.y, Sidewalk_Height ) comp(f){top=Boulevard_Center_Top(Dir) } case Location=="WalkWay_Right"||Location=="WalkWay_Left": WalkWay_Texture

Master_Split(Boulevard_Side,(geometry.dv(0,unitSpace)>=Bench_Threshol d_Width),"WalkWay",Dir) People case Location=="Open Space": extrude(world.y, Sidewalk_Height ) comp(f){top=OpenSpace_Planting} else: extrude(world.y, Sidewalk_Height ) WalkWay_Texture

Median_Top_Setup(Dir)--> case Dir==0: Median_Top(Dir) else: scaleUV(0,-1,1) Median_Top(Dir)

Boulevard_Top(Dir)--> split(u, unitSpace,0){Median_Planting_Length+Median_Tree_Spacing:Main_Section_Constr uction(Dir) |~_Bus_Furniture_Base("Boulevard","Far- side",Dir):Bus_Stop_Base("Boulevard",case Dir==0:180 else:0)

|~geometry.du(0,unitSpace)/2:Main_Section_Construction(Dir) |~_Bus_Furniture_Base("Boulevard","Mid- Block",Dir):Bus_Stop_Base("Boulevard",case Dir==0:180 else:0)

|~geometry.du(0,unitSpace)/2:Main_Section_Construction(Dir)

|~_Bus_Furniture_Base("Boulevard","Near- side",Dir):Bus_Stop_Base("Boulevard",case Dir==0:180 else:0)

|Median_Planting_Length+Median_Tree_Spacing:Main_Section_Construction(Dir)}

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 155

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Median_Top(Dir)--> split(u, unitSpace,0){Median_Planting_Length+Median_Tree_Spacing:Main_Section_Constr uction(Dir) |~_Bus_Furniture_Base("Median","Far and Near Side",(case Median_Bus_Stop_Location=="Far-side":0 else: 2)):Bus_Stop_Base_Setup("Median",0)

|~geometry.du(0,unitSpace)/2:Main_Section_Construction(Dir) |~_Bus_Furniture_Base("Median","Mid- Block",1):Bus_Stop_Base_Setup("Median",1)

|~geometry.du(0,unitSpace)/2:Main_Section_Construction(Dir) |~_Bus_Furniture_Base("Median","Far and Near Side",(case Median_Bus_Stop_Location=="Far-side":2 else: 0)):Bus_Stop_Base_Setup("Median",2)

|Median_Planting_Length+Median_Tree_Spacing:Main_Section_Construction(Dir)}

Boulevard_Center_Top(Dir)--> case Boulevard_Center_Type=="Median": Main_Section_Construction(Dir) # Does not construct bus stop- walkways/plantings only. else: Buffer_Texture

Bus_Stop_Base_Setup(Location,Stop_Number)--> case Median_Bus_Stop_Location=="Mid-Block":

split(v,unitSpace,0){'_Median_Midblock_Switch(0,"WalkWay"):WalkWay_Te xture

|'_Median_Midblock_Switch(0,"BusStop"):Bus_Stop_Base(Location,0)

|'_Median_Midblock_Switch(2,"BusStop"):Bus_Stop_Base(Location,180)

|'_Median_Midblock_Switch(2,"WalkWay"):WalkWay_Texture} case Median_Bus_Stop_Location=="Near-side": case Stop_Number==0: split(v,unitSpace,0){'.5:Bus_Stop_Base(Location,0) |'.5:WalkWay_Texture} else: split(v,unitSpace,0){'.5:WalkWay_Texture

|'.5:Bus_Stop_Base(Location,180)} else: case Stop_Number==0: split(v,unitSpace,0){'.5:WalkWay_Texture

|'.5:Bus_Stop_Base(Location,180)} else: split(v,unitSpace,0){'.5:Bus_Stop_Base(Location,0) |'.5:WalkWay_Texture}

Main_Section_Construction(Boulevard_Side)--># Rename Walkway_Right/Walk_WayLeft- DIR can replace it but is currently only used for benches. case Planting_and_Walkway_Layout=="Plant:Walk": split(v,unitSpace,0){~1:Median_Plant_Side(Boulevard_Side,0)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 156

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

|WalkWay_Width:Street_Pavement(Boulevard_Side,"WalkWay_Left",2)} case Planting_and_Walkway_Layout=="Walk:Plant":

split(v,unitSpace,0){WalkWay_Width:Street_Pavement(Boulevard_Side,"Wa lkWay_Right",0)

|~1:Median_Plant_Side(Boulevard_Side,2)} case Planting_and_Walkway_Layout=="Plant:Walk:Plant": split(v,unitSpace,0){~1:Median_Plant_Side(Boulevard_Side,2)

|WalkWay_Width:Street_Pavement(Boulevard_Side,"WalkWay_Left",2)

|WalkWay_Width:Street_Pavement(Boulevard_Side,"WalkWay_Right",0)

|~1:Median_Plant_Side(Boulevard_Side,0)} case Planting_and_Walkway_Layout=="Walk:Plant:Walk":

split(v,unitSpace,0){WalkWay_Width:Street_Pavement(Boulevard_Side,"Wa lkWay_Right",0)

|~1:Median_Plant_Side(Boulevard_Side,0)

|WalkWay_Width:Street_Pavement(Boulevard_Side,"WalkWay_Left",2)} else: NIL

Median_Plant_Side(Boulevard_Side,Dir)-->#The Bus Stop, Bike Racks, and WayFinder are put here. split(u,unitSpace,0){{~Median_Tree_Spacing/2:WalkWay_Texture

|~Median_Planting_Length:Median_Plant_Base |~Median_Tree_Spacing/2:WalkWay_Texture }*}

Bus_Stop_Base(Location,RotationAng)--> case Location=="Median": WalkWay_Texture Median_Object_Split(RotationAng)

case Location=="Boulevard": WalkWay_Texture Boulevard_Object_Split(RotationAng)

else: WalkWay_Texture Sidewalk_Object_Split(RotationAng)

Median_Object_Split(RotationAng)--> split(u,unitSpace,0){'_Bus_Alloc("Median"):Bus_Objects_Insert("Bus Stop",Bus_Stop_Object,RotationAng,-.5,2,3,3.35)

|'_Bike_Rack_Alloc("Median"):Median_Bike_Rack_Split(RotationAng,-1)

|'_WayFinder_Alloc("Median"):Bus_Objects_Insert("Wayfinder",Wayfinder _Object,RotationAng,-.5,.3,3,1.2)}

Boulevard_Object_Split(RotationAng)--> split(u,unitSpace,0){'_Bus_Alloc("Boulevard"):Bus_Objects_Insert("Bus Stop",Bus_Stop_Object,RotationAng,0,2,3,3.35)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 157

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

|'_Bike_Rack_Alloc("Boulevard"):Bike_Rack_Split(RotationAng,-.5)

|'_WayFinder_Alloc("Boulevard"):Bus_Objects_Insert("Wayfinder",Wayfin der_Object,RotationAng,-.5,.3,3,1.2)}

Bus_Objects_Insert(Object_Identity,File_Extension,RotationAng,Translation,S X,SY,SZ)-->#Bus Object Constructor Method alignScopeToAxes(y) alignScopeToGeometry(yUp, largest, 1) rotateScope(0,RotationAng,0) center(xz) t(scope.sx-SX,0,0) t(Translation,0,0) report("Objects: "+Object_Identity+" Count",1) i(File_Extension) s(SX,SY,SZ) deleteUV(_Texture_Switch)

Bike_Rack_Split(RotationAng,Translation)--> split(v,unitSpace,0){.7:Bus_Objects_Insert("Bike Rack",Bike_Rack_Object,RotationAng,Translation,.1,1,.3) |.7:Bus_Objects_Insert("Bike Rack",Bike_Rack_Object,RotationAng,Translation,.1,1,.3) |~1:NIL} Median_Bike_Rack_Split(RotationAng,Translation)-->

case RotationAng==180: split(v,unitSpace,0){.7:Bus_Objects_Insert("Bike Rack",Bike_Rack_Object,RotationAng,Translation,.1,1,.3) |.7:Bus_Objects_Insert("Bike Rack",Bike_Rack_Object,RotationAng,Translation,.1,1,.3) |~1:NIL} else: split(v,unitSpace,0){~1:NIL |.7:Bus_Objects_Insert("Bike Rack",Bike_Rack_Object,RotationAng,Translation,.1,1,.3) |.7:Bus_Objects_Insert("Bike Rack",Bike_Rack_Object,RotationAng,Translation,.1,1,.3)} Median_Plant_Base--> case Median_Ground_Cover =="None": WalkWay_Texture else: Tree_Setup("Median", Median_Tree_1_Percentage , Median_Tree_1_Type,Median_Tree_2_Type ) Median_Planting

Median_Planting--> case Median_Ground_Cover =="Random": tileUV(0,2,2) texture(Random_Grass) deleteUV(_Texture_Switch) Pervious_Reporting else: tileUV(0,2,2)texture(GrassFolder+"/"+ Median_Ground_Cover + ".jpg") deleteUV(_Texture_Switch) Pervious_Reporting

OpenSpace_Planting-->

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 158

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

scatter(surface,geometry.du(0,unitSpace)/3,uniform) { Tree_Setup("Median", Median_Tree_1_Percentage , Median_Tree_1_Type,Median_Tree_2_Type ) } tileUV(0,2,2) texture(Random_Grass) deleteUV(_Texture_Switch) Pervious_Reporting

WalkWay_Texture-->

tileUV(0,2,2) texture(Sidewalk_Texture) deleteUV(_Texture_Switch) scaleUV(0, Sidewalk_Texture_Scale, Sidewalk_Texture_Scale) rotateUV(0, Sidewalk_Texture_Rotation) color(_Usage("Pedestrian"))#If Display Thematics==Usage, goes to usage, if not, Thematic. report("Center: Median Walkway Area (m^2)",geometry.area()) #Object Loading Insertion Master_Split(Boulevard_Side,Start_Condition, Location,Dir)-->#The Bus Stop, Bike Racks, and WayFinder are put here. case Start_Condition: case Boulevard_Side==2: split(u,unitSpace,0){~Median_Bench_Spacing/2:NIL| {~2:Bench_Rule(Boulevard_Side,Dir)}|~Median_Bench_Spacing/2:NIL}* else: split(u,unitSpace,0){~Median_Bench_Spacing/2:NIL| {~2:Bench_Rule(Boulevard_Side,Dir)}|~Median_Bench_Spacing/2:NIL}* else: NIL

Bench_Rule(Boulevard_Side,Dir)--> # DEAL WITH BUSTOP ANOTHER WAY_ DO A SPLIT THAT GROWS case Center_Type=="Boulevard": alignScopeToAxes(y) alignScopeToGeometry(yUp, largest, Boulevard_Side)#Side corresponds to appropriate edge selection Bench_Rotater(Dir) else: alignScopeToAxes(y) alignScopeToGeometry(yUp, largest, 0) Bench_Rotater(Dir)

Bench_Rotater(Dir)--> case Dir==2: rotateScope(0,90,0) Bench_Insert(Dir) else: rotateScope(0,270,0) Bench_Insert(Dir)

Bench_Insert(Dir)--> case Dir==2 && (Median_Benches=="Both"||Median_Benches=="Left"): s(1,1,2) center(xz) t(-WalkWay_Width/2+Bench_Adjuster,0,0) report("Objects: Bench Count",1) i(Bench_Object) deleteUV(_Texture_Switch) case Dir==0 && (Median_Benches=="Both"||Median_Benches=="Right"): s(1,1,2) center(xz) report("Objects: Bench Count",1)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 159

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

t(-WalkWay_Width/2+Bench_Adjuster,0,0) i(Bench_Object) deleteUV(_Texture_Switch) else: NIL

Street_Lamp_Center(Location,Dir)--> case Location=="Boulevard": split(u,unitSpace,0) {~ Median_Street_Lamp_Spacing :NIL |{1:Street_Lamp_Sider(Dir) |~ Median_Street_Lamp_Spacing :NIL}*} case Location=="Median": split(u,unitSpace,0) {~ Median_Street_Lamp_Spacing:NIL |{1:Street_Lamp_Sider(0) #Median Dir should be set to 0 to grab right edge |~ Median_Street_Lamp_Spacing :NIL}*} else: NIL

Street_Lamp_Sider(Dir)--> case Median_Street_Lamps =="Both": split(v,unitSpace,0) {.5:Lamp_Center_Asset(90,case Dir==0:0 else:2,Dir) |~1:NIL |.5:Lamp_Center_Asset(-180,case Dir==0:5 else:3,Dir)} case Median_Street_Lamps =="Right": split(v,unitSpace,0) {~1:NIL |.5:Lamp_Center_Asset(-180,case Dir==0:5 else:3,Dir)} case Median_Street_Lamps =="Left": split(v,unitSpace,0) {.5:Lamp_Center_Asset(90,case Dir==0:0 else:2,Dir) |~1:NIL} else: NIL Lamp_Center_Asset(Side_Rotation,Shape_Edge,Dir)--> alignScopeToGeometry(yUp, largest,Shape_Edge) alignScopeToAxes(y) // place the Lamps vertically center(xz) s(0,5,0) //set initital height to 5 others are based on OBJ r(0,Side_Rotation,0) report("Objects: Street Lamp Count", 1) i(Street_Lamp_Object) deleteUV(_Texture_Switch)

########################################## #Tree Loader Code Median_TreeSplit--> #color(rand(1),rand(1),rand(1)) split(u,unitSpace,0){{~Median_Tree_Spacing/2:NIL |1:Tree_Setup("Median", Median_Tree_1_Percentage , Median_Tree_1_Type, Median_Tree_2_Type) |~Median_Tree_Spacing/2:NIL}*}

Tree_Setup(Location,Percentage1,Tree_Type1,Tree_Type2)-->

s(0,0,0) // set scope

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 160

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

r(scopeCenter, 0,rand(0,360),0)// random rotate alignScopeToAxes(y) center(xz) TreeInsert(Location,Percentage1,Tree_Type1,Tree_Type2)

TreeInsert(Location,Percentage1,Tree_Type1,Tree_Type2) --> case texturingOn: case p(Percentage1): s(0,0,0) report("Vegetation: Construction, Tree Cost",TreeCostAverage) set(Tree.Name, Tree_Type_Adjusted(Tree_Type1)) #set(Tree.Height, _Tree_Height(Tree_Type1)) #set(Tree.Radius,_Tree_Radius(Tree_Type1)) Tree.Generate case Tree_Type2!="None": s(0,0,0) report("Vegetation: Construction, Tree Cost", TreeCostAverage) set(Tree.Name, Tree_Type_Adjusted(Tree_Type2)) Tree.Generate else: NIL else: #If Texturing is off, the tree texture is overrided to the current thematic color case p(Percentage1): s(0,0,0) report("Vegetation: Construction, Tree Cost",TreeCostAverage) set(Tree.Name, Tree_Type_Adjusted(Tree_Type1)) set(Tree.OverwriteColor,_Usage("Plantings")) Tree.Generate case Tree_Type2!="None": #So if the percentage if 50%, and Tree1 does not fire, if tree 2 is not set to None, that tree 2 will be selected. s(0,0,0) report("Vegetation: Construction, Tree Cost", TreeCostAverage) set(Tree.Name, Tree_Type_Adjusted(Tree_Type2)) set(Tree.OverwriteColor,_Usage("Plantings")) Tree.Generate else: NIL

Tree_Type_Adjusted(Tree_Type) = case Tree_Type == "Random": randomTreeType else: Tree_Type randomTreeType = 20%: "Tree of Heaven" 20%: "White Ash" 20%: "Common Hackberry" 20%: "Sweetgum" else: "Sassafras" ###################################################

################################################### # Crosswalk # Crosswalk(crosswalkType,uvSet) --> case crosswalkType == "transverse" : CrosswalkTransverse(uvSet)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 161

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

case crosswalkType == "dashed" : CrosswalkDashed(uvSet) case crosswalkType == "ladder" : CrosswalkLadder(uvSet) case crosswalkType == "solid" : AsphaltPainted( Crosswalk_Color,true,1,"Conflict Zones") case crosswalkType == "custom" : CrosswalkWalkway(true) case crosswalkType == "ladder custom": CrosswalkLadderWalkway(uvSet) else : CrosswalkContintental

CrosswalkContintental --> report("Crosswalk: Crosswalk Area",geometry.area()) split(v,uvSpace,0){ (ceil(geometry.vMin-0.01)-geometry.vMin): Asphalt(true,1,"Conflict Zones") | ~1: CrosswalkStripes(1) | geometry.vMax-floor(geometry.vMax+0.01): Asphalt(true,1,"Conflict Zones") }

CrosswalkLadder(uvSet) --> report("Crosswalk: Crosswalk Area",geometry.area()) split(u,uvSpace,uvSet){ 0.17: AsphaltPainted( Crosswalk_Color,true,1,"Conflict Zones") | ~1 : CrosswalkStripes(1) | 0.17: AsphaltPainted( Crosswalk_Color,true,1,"Conflict Zones" ) }

CrosswalkTransverse(uvSet) --> report("Crosswalk: Crosswalk Area",geometry.area()) split(u,uvSpace,uvSet){ 0.27: AsphaltPainted( Crosswalk_Color,true,1,"Conflict Zones" ) | ~1 : Asphalt(true,1,"Conflict Zones") | 0.27: AsphaltPainted( Crosswalk_Color,true,1,"Conflict Zones" ) }

CrosswalkLadderWalkway(uvSet)--> report("Crosswalk: Crosswalk Area",geometry.area()) split(u,uvSpace,uvSet){ 0.27: AsphaltPainted( Crosswalk_Color,true,1,"Conflict Zones") | ~1 : CrosswalkWalkway(false) | 0.27: AsphaltPainted( Crosswalk_Color,true,1,"Conflict Zones" ) } CrosswalkDashed(uvSet) --> report("Crosswalk: Crosswalk Area",geometry.area()) split(u,uvSpace,uvSet){ 0.17: CrosswalkStripes(0.6) | ~1 : Asphalt(true,1,"Conflict Zones") | 0.17: CrosswalkStripes(0.6) }

CrosswalkStripes(stripeWidth) --> report("Crosswalk: Crosswalk Area",geometry.area()) cleanupGeometry(all, 0.001) tileUV(0,0,~1) scaleUV(0,1,1/8/stripeWidth) # to setup the v-direction: a continental crosswalk line is 1m width, and the texture contains 8 of these. texture(StreetTextureFolder + "/Lanes/crosswalk_continental_"+ Crosswalk_Color +".jpg") deleteUV(_Texture_Switch) color(_Usage("Conflict Zones"))#If Display Thematics==Usage, goes to usage, if not, Thematic. AsphaltPainted(Crosswalk_Color,false,Crosswalk_PaintFraction,"Conflic t Zones") Asphalt(false,1-Crosswalk_PaintFraction,"Conflict Zones")

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 162

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

CrosswalkWalkway(reporting)--> case reporting: tileUV(0,2,2) texture(Custom_Crosswalk_Texture) deleteUV(_Texture_Switch) color(_Usage("Conflict Zones"))#If Display Thematics==Usage, goes to usage, if not, Thematic. report("Crosswalk: Crosswalk Area",geometry.area()) else: tileUV(0,2,2) texture(Custom_Crosswalk_Texture) deleteUV(_Texture_Switch) color(_Usage("Conflict Zones"))#If Display Thematics==Usage, goes to usage, if not, Thematic.

################################################### # Other default Start Rules of the graph # #Many are only sent to Asphalt. This includes joints, crossings, and junctions. # drive-through street segments Joint --> BridgeMain report("Joint Area",geometry.area())#Only reports given to Joints Asphalt(true,1,"Auto")

Junction --> BridgeMain report("Intersection Area",geometry.area()) Asphalt(true,1,"Auto")

Freeway -->

report("Freeway Area",geometry.area())#Only reports given to freeways. set(streetWidth,geometry.dv(0,unitSpace)) set( Lane_Width ,streetWidth/geometry.dv(0,uvSpace)) split(v,unitSpace,0){ Lane_Width *18/256: tileUV(0,0,- Lane_Width ) MainLaneMarkings(0,split.index,"_stripes_white") # with tileUV we make sure that the v-coord starts always at zero (independent of the direction of the segment) and since the last stripe is on the top of the texture, we have to reverse the v-coord | { Lane_Width : MainLaneMarkings(0,split.index,"_stripes_white")}* | Lane_Width :Asphalt(true,1,"Auto")} BridgeMain # crossing is just Asphalt for now

Crossing --> BridgeMain report("Crossing Area", geometry.area())#Only reports given to crossings Asphalt(true,1,"Auto") # freeway entries have an additional striped line (splits the shape into lanes but also splits away a shape just for the striped line using special UVSET 1

FreewayEntry -->

report("Freeway Entry Area",geometry.area())#Only reports given to freeways.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 163

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

set(streetWidth,geometry.dv(0,unitSpace)) set( Lane_Width ,streetWidth/geometry.dv(0,uvSpace)) split(v,unitSpace,1){ Lane_Width *18/256: tileUV(0,0,- Lane_Width ) MainLaneMarkings(0,split.index,"_stripes_white") # with tileUV we make sure that the v-coord starts always at zero (independent of the direction of the segment) and since the last stripe is on the top of the texture, we have to reverse the v-coord | { Lane_Width : MainLaneMarkings(0,split.index,"_stripes_white")}* } BridgeMain

################################################### # Roundabout #

Roundabout --> case valency>1: Asphalt(true,1,"Auto") BridgeMain #split(v,unitSpace,0){ 1: MainLaneMarkings(0,split.index,"_stripes_white") }* else : Asphalt(true,1,"Auto") BridgeMain # cul-de-sac is Asphalt only

RoundaboutIsland --> case Sidewalk_Ground_Cover !="None": IslandWithGreen BridgeMain else : Asphalt(true,1,"Auto") BridgeMain # cul-de-sac is Asphalt only

IslandWithGreen --> offset(- Sidewalk_Height ) comp(f){ inside: Tree_Scatter | border: setupProjection(0,scope.xy,'1,'1) projectUV(0) Curbs_Mass(false) }

Green --> translate(rel,world,0, Sidewalk_Height ,0) setupProjection(0,scope.yx,2,2) projectUV(0) texture(Random_Grass) deleteUV(_Texture_Switch) Pervious_Reporting

Tree_Scatter--> scatter(surface,3,gaussian,center,'2) { Tree_Setup("Round About", Sidewalk_Tree_1_Percentage ,Sidewalk_Tree_1_Type,Sidewalk_Tree_2_Type) } Green

################################################### # Sidewalk #

Sidewalk--> BridgeSide set(SidewalkWidth,scope.sz) set(SidewalkLength,scope.sx) color(_Usage("Pedestrian"))#If Display Thematics==Usage, goes to usage, if not, Thematic. report("Cut/Fill: Total Sidewalk Cut/Fill Volume (m^3)", geometry.area()*Sidewalk_Height) report("Sidewalk: Total Sidewalk Area (m^2)", geometry.area()) split(v,unitSpace,0){Curb_Depth: Curbs_Mass(false) | ~1: Sidewalk_Setup }

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 164

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Curbs_Mass(RotateUV)--> extrude(world.y, Sidewalk_Height ) comp(f) {top:Curbs(RotateUV)|side:Curbs(false)}

Curbs(RotateUV) --> case RotateUV:#Used to handle an exception where scope changes on horizontal curbs (parallel to crosswalk) rotateUV(0,270) setupProjection(0,scope.yx,~2,'1)#Notice axis choice changed. texture(SidewalkFolder+"/curbs_2m.jpg") projectUV(0) deleteUV(_Texture_Switch) else: setupProjection(0,scope.xy,~2,'1) texture(SidewalkFolder+"/curbs_2m.jpg") projectUV(0) deleteUV(_Texture_Switch)

Sidewalk_Setup--> case sidewalkSide=="Right": extrude(world.y, Sidewalk_Height ) comp(f){top=SidewalkTop|side:Pavement("Building Side") } case sidewalkSide=="Left": scaleUV(0,1,1) extrude(world.y, Sidewalk_Height ) comp(f){top=SidewalkTop|side:Pavement("Building Side") } else: print("Error: two right sidewalks as default- please map this attribute.") extrude(world.y, Sidewalk_Height ) comp(f){top=SidewalkTop|side:Pavement("Building Side") }

SidewalkTop--> case valency>1: Pavement("Corners")

case Sidewalk_Ground_Cover =="None": split(v,unitSpace,0) {CurbtoPlantingGap:Sign_Loader|~1:Pavement("Through Zone") People} else: split(v,unitSpace,0){CurbtoPlantingGap:Sign_Loader |Sidewalk_Planting_Width: Sidewalk_Loading_Section(case sidewalkSide=="Right":0 else:2) |~1:Pavement("Through Zone") People} Sign_Loader--> Pavement("Sign Gap") Traffic_Light_Setup Parking_Meter_Setup Lamp_Setup

Lamp_Setup--> case Sidewalk_Street_Lamps =="None": NIL case sidewalkSide=="Right": case Sidewalk_Street_Lamps =="Right" || Sidewalk_Street_Lamps =="Both": split(u,unitSpace,0) {~ Sidewalk_Street_Lamp_Spacing :NIL |{.1:Lamp(0)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 165

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

|~ Sidewalk_Street_Lamp_Spacing :NIL}*} else: NIL case sidewalkSide=="Left": case Sidewalk_Street_Lamps =="Left" || Sidewalk_Street_Lamps =="Both": split(u,unitSpace,0) {~ Sidewalk_Street_Lamp_Spacing :NIL |{.1:Lamp(2) |~ Sidewalk_Street_Lamp_Spacing :NIL}*} else: NIL else: NIL Traffic_Light_Setup--> case Traffic_Lights=="None": NIL case sidewalkSide=="Right": case Traffic_Lights=="Right" || Traffic_Lights=="Both": split(u,unitSpace,0) {_crosswalkEndWidth-3.5:NIL #-3.5 is so that if if the crosswalk is short its just placed at the end of the sidewalk-handles up to 9 m crosswalks well. |1:Traffic_Light(0) |~1:NIL} else: NIL case sidewalkSide=="Left": case Traffic_Lights=="Left" || Traffic_Lights=="Both": split(u,unitSpace,0) {_crosswalkEndWidth-3.5:NIL #-3.5 is so that if if the crosswalk is short its just placed at the end of the sidewalk-handles up to 9 m crosswalks well. |1:Traffic_Light(2) |~1:NIL} else: NIL else: NIL

Traffic_Light(index)--> alignScopeToAxes(y) // place the Lamps vertically s(0,5,0) // set height to 5 meters Traffic_Light_Asset(index)

Traffic_Light_Asset(index)--> r(0,90,0) report("Objects: Traffic Lights Count", 1) i(Traffic_Light_Object) deleteUV(_Texture_Switch)

Lamp(index) --> alignScopeToAxes(y) // place the Lamps vertically center(xz) s(0,5,0) // set height to 5 meters report("Objects: Street Lamp Count", 1) LampAsset(index) // since the scope's dimenstion are zero in x and z, these are set according to the asset

LampAsset(nr) --> case nr == 2 : r(0,90,0) i(Street_Lamp_Object)deleteUV(_Texture_Switch)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 166

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

else : r(0,90,0) i( Street_Lamp_Object) deleteUV(_Texture_Switch)

Parking_Meter_Setup--> case Parking_Meters=="None": NIL case sidewalkSide=="Right": case Parking_Meters=="Right" || Parking_Meters=="Both": Parking_Meter_Loader(Right_Parking_Length,0)

else: NIL case sidewalkSide=="Left": case Parking_Meters=="Left" || Parking_Meters=="Both": Parking_Meter_Loader(Left_Parking_Length,2) else: NIL else: NIL

Parking_Meter_Loader(Parking_Length,Dir)--> split(u,unitSpace,0) {(_Sidewalk_CrossStop_Gap(Dir,"Begin") + Parking_Meter_Setback):NIL # moves starting point for meters into near middle |{.25:Sign_Objects_Insert("Parking Meter",Parking_Meter_Object,0,0,.3,1.4,.3) |~Parking_Meters_Spacing:NIL}*

|(_Sidewalk_CrossStop_Gap(Dir,"End")):NIL}

Pavement(Location) --> case Location== "Through Zone" || Location=="Corners": alignScopeToAxes(y) tileUV(0,2,2) texture(Sidewalk_Texture) deleteUV(_Texture_Switch) scaleUV(0, Sidewalk_Texture_Scale, Sidewalk_Texture_Scale) rotateUV(0, Sidewalk_Texture_Rotation) report("Sidewalk: "+Location+" Area (m^2)",geometry.area()) case Location=="Building Side": setupProjection(0,scope.xy,2, 2) texture(Sidewalk_Texture) projectUV(0) deleteUV(_Texture_Switch) scaleUV(0, Sidewalk_Texture_Scale, Sidewalk_Texture_Scale) rotateUV(0, Sidewalk_Texture_Rotation) else: alignScopeToAxes(y) tileUV(0,2,2) texture(Sidewalk_Texture) deleteUV(_Texture_Switch) scaleUV(0, Sidewalk_Texture_Scale, Sidewalk_Texture_Scale) rotateUV(0, Sidewalk_Texture_Rotation)

Sidewalk_Loading_Section(Dir)--> split(u,unitSpace,0){(_Sidewalk_CrossStop_Gap(Dir,"Begin")):Pavement( "Cross Walk Begin Gap") |~_Bus_Sidewalk_Base("Near- side"):Bus_Stop_Base("Sidewalk",0)

|~geometry.du(0,unitSpace)/2:Sidewalk_Plant_Side("Begin")

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 167

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

|~_Bus_Sidewalk_Base("Mid- Block"):Bus_Stop_Base("Sidewalk",0)

|~geometry.du(0,unitSpace)/2:Sidewalk_Plant_Side("End") |~_Bus_Sidewalk_Base("Far- side"):Bus_Stop_Base("Sidewalk",0) |(_Sidewalk_CrossStop_Gap(Dir,"End") ):Pavement("Cross Walk End Gap")}

Sidewalk_Object_Split(RotationAng)--> split(u,unitSpace,0){'_Bus_Alloc("Sidewalk"):Bus_Objects_Insert("Bus Stop",Bus_Stop_Object,RotationAng,Sidewalk_Bus_Stop_Setback,2,3,3.35)

|'_Bike_Rack_Alloc("Sidewalk"):Bike_Rack_Split(RotationAng,0)

|'_WayFinder_Alloc("Sidewalk"):Bus_Objects_Insert("Wayfinder",Wayfind er_Object,RotationAng,-.5,.3,3,1.2)}

Sidewalk_Plant_Side(Plant_Side_Base_Switch)--> split(u,unitSpace,0){~Sidewalk_Planting_Spacing /2:Pavement("Before Planting") |~Sidewalk_Planting_Length:Plant_Base

|~Sidewalk_Planting_Spacing/2:Pavement("After Planting") Sidewalk_Bench_Loader(split.index,split.total,Plant_Side_Base_Switch)}*

Sidewalk_Bench_Loader(splitNum,splitTotal,Plant_Side_Base_Switch)--> case Sidewalk_Benches =="None": NIL case sidewalkSide=="Right" && (splitNum!=splitTotal-1 || Plant_Side_Base_Switch!="End"):#Does not place a bench on the end split of the End Sidewalk_Plant_Side_Base (if Switch is removed no bench is generated mid-block) case Sidewalk_Benches =="Right" || Sidewalk_Benches=="Both": Sidewalk_Bench_Insert(0,geometry.du(0,unitSpace)) else: NIL case sidewalkSide=="Left" && (splitNum!=splitTotal-1 || Plant_Side_Base_Switch!="End"): #Does not place a bench on the end case Sidewalk_Benches =="Left" || Sidewalk_Benches=="Both": Sidewalk_Bench_Insert(2,geometry.du(0,unitSpace)) else: NIL else: NIL

Sidewalk_Bench_Insert(Dir,geometry_Len)--> case geometry.du(0,unitSpace)>1: #Remember two gaps, so it is 2 (width of bench)/2 alignScopeToAxes(y) alignScopeToGeometry(yUp, largest, 0) rotateScope(0,90,0) s(1,1,2) t(.5,0,geometry_Len-1)#When geometry.du is used functionality is different (alignment issue?) passed parameter works best likely because it is before scope manipulation (rotate etc)dv. might work instead. report("Objects: Bench Count",1) i(Bench_Object) deleteUV(_Texture_Switch) else:

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 168

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

NIL

Plant_Base--> case Sidewalk_Ground_Cover =="None": Pavement("Plant_Space") else: Sidewalk_Planting Tree_Setup("Sidewalk", Sidewalk_Tree_1_Percentage , Sidewalk_Tree_1_Type, Sidewalk_Tree_2_Type )

Sidewalk_Planting--># THis is set up this way to support a vegetated buffer with no trees on sidewalk case Sidewalk_Ground_Cover =="None": tileUV(0,2,2) texture(Random_Grass) deleteUV(_Texture_Switch) Pervious_Reporting case Sidewalk_Ground_Cover =="Random": tileUV(0,2,2) texture(Random_Grass) deleteUV(_Texture_Switch) Pervious_Reporting else: tileUV(0,2,2)texture(GrassFolder+"/"+ Sidewalk_Ground_Cover + ".jpg") deleteUV(_Texture_Switch) Pervious_Reporting

Sign_Objects_Insert(Object_Identity,File_Extension,RotationAng,Translation, SX,SY,SZ)-->#Sidewalk Object Constructor Rule alignScopeToAxes(y) alignScopeToGeometry(yUp, largest, 1) rotateScope(0,RotationAng,0) center(xz) t(scope.sx-SX,0,0) t(Translation,0,0) i(File_Extension) s(SX,SY,SZ) report("Objects: "+Object_Identity+" Count",1) deleteUV(_Texture_Switch) ################################################## #Paint Reporting #Asphalt Painted is actually retrofitted to be the paint reporting aggregator, all "Paint Areas" originate here. AsphaltPainted(paintColor,TextureAndReport,Area_Fraction,Usage) --> case Area_Fraction==0:# If the area fraction is 0, we don't even want to have it be included in the sum (throws off averages/stats). NIL case TextureAndReport && paintColor!="black":# This makes sure that if the color is black, it is thrown into Asphalt Reporting tileUV(0,7,7) cleanupGeometry(all,0.001) texture(StreetTextureFolder + "/Lanes/asphalt_painted_" + paintColor + "_7x7m.jpg") deleteUV(_Texture_Switch) color(_Usage(Usage))#If Display Thematics==Usage, goes to usage, if not, Thematic. report("Paint: "+paintColor+" Painted Area (m^2)",geometry.area*Area_Fraction) report("Paint Cost Estimate: "+paintColor+" Painted Area ($)",(geometry.area*Area_Fraction*SquareFeet)*_PaintCost(paintColor)) case paintColor=="black":#If Black redirect to asphalt rule. Asphalt(TextureAndReport,Area_Fraction,Usage)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 169

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

else:#Only Reports no texturing desired. report("Paint: "+paintColor+" Painted Area (m^2)", (geometry.area*Area_Fraction)) report("Paint Cost Estimate: "+paintColor+" Painted Area ($)",(geometry.area*Area_Fraction*SquareFeet)*_PaintCost(paintColor)) # ------Paint:------####################################################################### #Vehicles # # Sample assets provided by lowpolygon3d.com # # More assets with high-res textures can be # purchased at http://www.lowpolygon3d.com. # # ------vehicleAsset(type) = fileRandom(StreetTextureFolder + "/LowPolygon3D.com_Vehicles/" + type + "/*.obj") const vehiclesProb = ( Vehicles_Per_KM *minCarDistance)/1000 const busProb = (Bus_Lane_Buses_Per_KM*minCarDistance)/1000 const minCarDistance = 6

BusOnLane(dir)--> case geometry.du(0,unitSpace)>10: split(u,unitSpace,0){ ~1: BusOnLane(dir) | (rand(15,25)): Bus_Vehicle(dir,"bus") } else: NIL

VehiclesOnLane(dir) --> case geometry.du(0,unitSpace) > 1000: split(u,unitSpace,0){ '0.5: VehiclesOnLane(dir) | '0.5: VehiclesOnLane(dir) } case geometry.du(0,unitSpace) > 10 && p( Mixed_Traffic_Bus_Percentage): split(u,unitSpace,0){ ~1: VehiclesOnLane(dir) | (rand(15,25)): Vehicle(dir,"bus") } case geometry.du(0,unitSpace) > 5: split(u,unitSpace,0){ ~1: VehiclesOnLane(dir) | (rand(minCarDistance,15)): VehicleTaxiOrCar(dir) } else: NIL

VehicleTaxiOrCar(dir) --> case p(Taxi_Percentage): Vehicle(dir,"taxi") else: Vehicle(dir,"car")

Bus_Vehicle(dir,type) --> case p(busProb): split(u,unitSpace,0){ ~1: NIL | 0.5: alignScopeToGeometry(yUp,dir) VehicleAsset(type) | ~1: NIL } else: NIL

Vehicle(dir,type) --> case p(vehiclesProb): split(u,unitSpace,0){ ~1: NIL | 0.5: alignScopeToGeometry(yUp,dir) VehicleAsset(type) | ~1: NIL }

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 170

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

else: NIL

VehicleAsset(type) --> t(0,0,'rand(0.4,0.6)) s(0,0,0) r(0,90,0) r(0,DirectionalRotation,0) i(vehicleAsset(type)) color(_Usage(case type=="bus":"Transit" else:"Auto")) Delete_Texture

# ------# Cyclists # # Sample assets provided by lowpolygon3d.com # # More assets with high-res textures can be # purchased at http://www.lowpolygon3d.com. # # ------bikeAsset = fileRandom(StreetTextureFolder + "/LowPolygon3D.com_Cyclists/*.obj") const bikeProb = (Bicycles_Per_KM * minBikeDistance)/1000 const minBikeDistance = 2

Bikes(dir,Bike_Lane_Width) --> case bikeProb > 0: BikesOnLane(dir,Bike_Lane_Width) else: NIL

BikesOnLane(dir,Bike_Lane_Width) --> #Fix: Lots of logic here that doesn't apply to bikes, since it was adapted from car logic. case geometry.du(0,unitSpace) > 1000: split(u,unitSpace,0){ '0.5: BikesOnLane(dir,Bike_Lane_Width) | '0.5: BikesOnLane(dir,Bike_Lane_Width) } case geometry.du(0,unitSpace)> 10: split(u,unitSpace,0){ ~1: BikesOnLane(dir,Bike_Lane_Width) | (rand(minBikeDistance,minBikeDistance*2)): Bike(dir,Bike_Lane_Width) } case geometry.du(0,unitSpace) > 5: split(u,unitSpace,0){ ~1: BikesOnLane(dir,Bike_Lane_Width) | (rand(minBikeDistance,3)): Bike(dir,Bike_Lane_Width) } else: NIL

Bike(dir,Bike_Lane_Width) --> case p(bikeProb): split(u,unitSpace,0){ ~1: NIL | 0.5: alignScopeToGeometry(yUp,dir) BikeAsset(Bike_Lane_Width) | ~1: NIL } else: NIL

BikeAsset(Bike_Lane_Width) --> rotateScope(0,DirectionalRotation,0) t(0,0,Bike_Lane_Width/2 + rand(-Bike_Lane_Width/4,Bike_Lane_Width/4)) s(0,0,0) i(bikeAsset) r(scopeCenter,0,90,0)

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 171

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Bike_Delete_Texture_Color # will only color when textures are removed.

Bike_Delete_Texture_Color--> case texturingOn: X. else: deleteUV(0) color(_Usage("Bikeways"))

# Our bicycle models have both textured and colored parts. # So when texturing is off, we still need to change the color of the bikes. # color(thematicColor)- see remove_Bike_color Delete_Texture--> case texturingOn: X. else: deleteUV(0)

# ------# People # # Sample assets provided by lowpolygon3d.com # # More assets with high-res textures can be # purchased at http://www.lowpolygon3d.com. # # ------peopleAsset = fileRandom(StreetTextureFolder + "/LowPolygon3D.com_People/*.obj") dirHuman = 50%: 90 else: -90

People --> case geometry.du(0,unitSpace) > 20: split(u,unitSpace,0){ '0.5: People | '0.5: People } case People_Percentage > 0: 50% : split(u,unitSpace,0){ { 0.1: Human | ~rand(2,5): NIL | 0.1: Human | ~rand(2,5): NIL }* | 0.1: Human } # could be distributed better... else: split(u,unitSpace,0){ { 0.1: Human | ~rand(0.5,5.5): NIL | 0.1: Human | ~rand(0.5,5.5): NIL }* | 0.1: Human } # could be distributed better... else: NIL

Human --> case (scope.sz < 2 && p(People_Percentage*0.3)) || (scope.sz >= 2 && p(People_Percentage)): alignScopeToAxes(y) t(0,0,'rand(0.1,0.6)) s(0,rand(1.7,1.9),0) r(0,dirHuman,0) i(peopleAsset) color(_Usage("Pedestrian")) deleteUV(_Texture_Switch) else: NIL

# Bridge can be explicitly activated or deactivated,

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 172

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

# or automatically set by height over terrain. isBridge = (Bridge_Display == "On, Regardless") || (Bridge_Display == "On, Show All Piers") || (Bridge_Display == "On, Flag Occlusions") || (Bridge_Display == "On, By Elevation" && isRaised)

# Road segment is raised if it is higher than Bridge_Starts_At attribute. # isRaised DOES NOT imply it is a bridge. isRaised = heightOverTerrain > Bridge_Starts_At heightOverTerrain = convert(y, scope, world, pos, scope.sx * 0.5, scope.sy * 0.5, scope.sz * 0.5) - elevation # The above convert function finds the y world coordinate at the center # of the scope, then subtracts the elevation to get the # height over the terrain. # NOTE: To use this function, you must add a layer attribute # to your terrain layer, like this: # attr elevation = map_01(brightness, 405.20847, 419.22385) + elevationDelta

BridgeMain --> case isBridge: # For debugging: #print("heightOverTerrain = " + heightOverTerrain) # Give bridge thickness, sending the street shape to thickness rule. BridgeConcrete(Bridge_Thickness) # Drop street shape down by thickness, to split for piers. translate(rel, world, 0, -Bridge_Thickness, 0) # Split to make starting points for piers. split(u, unitSpace, 0) { ~( Pier_Distance / 2) : NIL | { Pier_Width : Pier | ~ Pier_Distance : NIL }* # XX: Not sure why the pattern was repeated in this manner: | Pier_Width : Pier | ~ Pier_Distance : NIL } case Bridge_Display== "Concrete Extrusion Only": BridgeConcrete(Bridge_Thickness) else : NIL

Pier --> case heightOverTerrain > 0: split(v,unitSpace,0){ '0.15: NIL | '0.70: PierStep2 | '0.15: NIL } else: NIL

PierStep2 --> alignScopeToGeometry(yUp,0,0) # Make "feeler" for occlusion check in next rule. # Extrude down to the terrain (must be mapped in layer attribute). extrude(world.y,-heightOverTerrain) # Align to yUp for feeler scaling. alignScopeToAxes(y) # Scale to go past regular pier shape.

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 173

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

s('1,'20,'1) t(0,-0.5,0) # Check if pier will hit something. PierCheck

PierCheck --> case (Bridge_Display == "On, Show All Piers"): # Occlusion test is disabled, by "On, Show All piers". PierShow case (Bridge_Display == "On, Flag Occlusions"): case overlaps(inter): # This pier hits another model. print("Occlusion true: Bridge pier overlaps another model!") # Flag the pier in red. This is a debugging mode for the piers. color(1,0,0) PierShow else: # No occlusion so show the pier. print("Occlusion false.") PierShow else: # Use standard occlusion method. case overlaps(inter): # Omit piers due to positive occlusion check. # This means the pier would hit a street or other model. NIL else: # No occlusion so show the pier. PierShow

PierShow --> # Scale back occlusion feelers, reversing the feeler code. s('1,'0.05,'1) t(0,0.5,0) # split(y){2.2: PierBase | ~1: PierShafts | 1: BridgeSolid }

# XX: Come back later and make smarter pier sizing code. PierShafts --> case scope.sz > 7: split(x){ 0.5: NIL | ~1 : split(z){ ~1: NIL | ~3: comp(f){side: BridgeSolid} | ~4: NIL | ~3: comp(f){side: BridgeSolid} | ~1: NIL } | 0.5: NIL } else: split(x){ 0.5: NIL | ~1 : split(z){ ~0.5: NIL | ~3: comp(f){side: BridgeSolid} | ~0.5: NIL } | 0.5: NIL }

# XX: Come back later and make smarter pier sizing code. PierBase --> s('1,scope.sy+5,'1) t(0,-5.3,0) i("builtin:cube") comp(f){ side: BridgeSolid | top: roofHip(60) split(y){ 0.3: BridgeSolid } }

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 174

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

BridgeSide --> case isBridge: BridgeRailing BridgeConcrete(0.4) translate(rel,world,0,-0.4,0) reverseNormals comp(f){all: BridgeSlope } case Bridge_Display== "Concrete Extrusion Only": BridgeConcrete(Bridge_Thickness) else: NIL

BridgeCrossing --> case isBridge: BridgeConcrete(Bridge_Thickness) else: NIL

BridgeSlope --> case geometry.isRectangular(10) && Bridge_Thickness > 2: roofShed(23,2) comp(f){all = BridgeMaterial } else: NIL

BridgeConcrete(height) --> translate(rel,world,0,-height,0) extrude(world.y,height) comp(f){top: NIL | all= BridgeMaterial }

BridgeRailing --> case LOD_Setting=="High": translate(rel,world,0, Sidewalk_Height ,0) split(v,unitSpace,0){ ~1: NIL | 0.4: extrude(world.y,0.8) color(case coloringOn: "#eeeeee" else: "") comp(f){all: BridgeMaterial} } split(v,unitSpace,0){ ~1: NIL | 0.1: translate(rel,world,0,0.8,0) VerticalRails translate(rel,world,0,0.3,0) extrude(world.y,0.05) RailMaterial | 0.17: NIL } else: translate(rel,world,0, Sidewalk_Height ,0) split(v,unitSpace,0){ ~1: NIL | 0.4: extrude(world.y,0.8) color(case coloringOn: "#eeeeee" else: "") comp(f){all: BridgeMaterial } } split(v,unitSpace,0){ ~1: NIL | 0.1: translate(rel,world,0,0.8,0) VerticalRails translate(rel,world,0,0.3,0) comp(f){ all: extrude(world.y,0.05) comp(f){front: RailMaterial} | 0.17: NIL } }

VerticalRails --> case LOD_Setting=="High": comp(f){all: split(x){ ~1 : NIL | 0.1: s('1,0.07,'1) center(y) extrude(world.y,0.3) RailMaterial | { ~2 : NIL | 0.1: s('1,0.07,'1) center(y) extrude(world.y,0.3) RailMaterial }* | ~1 : NIL } }

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 175

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

else: comp(f){all: split(x){ ~1 : NIL | 0.1: s('1,0.07,'1) center(y) extrude(world.y,0.3) comp(f){front: RailMaterial} | { ~2 : NIL | 0.1: s('1,0.07,'1) center(y) extrude(world.y,0.3) comp(f){front: RailMaterial} }* | ~1 : NIL } }

BridgeSolid --> comp(f){ all: setupProjection(2,scope.xy,'1,'1) projectUV(2) set(material.dirtmap,LanesFolder+"/dirtmap.1.512x512.jpg") BridgeMaterial }

BridgeMaterial --> case texturingOn: setupProjection(0,scope.xy,~12,~9,1) projectUV(0) texture(Default_Pavement) else: X.

RailMaterial --> case texturingOn: set(material.specular.r, 1) set(material.specular.g, 1) set(material.specular.b, 1) set(material.shininess, 20) setupProjection(0,scope.xy,~12,~9,1) projectUV(0) texture(SidewalkFolder+"/Concrete Rough Light.jpg") RailMaterialStep2 else: RailMaterialStep2

RailMaterialStep2 --> case coloringOn: color("#cccccc") else: X.

################################################### # Misc # Pervious_Reporting--> case peakRunoffDisplayOn: report("Vegetation: Pervious Area",geometry.area) color(0,0,1) X. else: report("Vegetation: Pervious Area",geometry.area) color(_Usage("Plantings"))#If Display Thematics==Usage, goes to usage, if not, Thematic. X. Cut_And_Fill_Reporting(Text_Fill)--> report("Cut/Fill: Total "+Text_Fill+" Cut/Fill Volume (m^3)", geometry.area()*Sidewalk_Height) X.

Asphalt(TextureAndReport,Area_Fraction,Usage) --> case TextureAndReport: tileUV(0,14,14) cleanupGeometry(all, 0.001) texture(StreetTextureFolder + "/Lanes/asphalt_14x14m.jpg")

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 176

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

deleteUV(_Texture_Switch) color(_Usage(Usage))#If Display Thematics==Usage, goes to usage, if not, Thematic-strings might have other purpose later. report("Lane: Asphalt Only Area Total (m^2)",geometry.area*Area_Fraction) else: report("Lane: Asphalt Only Area Total (m^2)",geometry.area*Area_Fraction)

Rumble_Strip--> tileUV(0,~Rumble_Strip_Len,~Rumble_Strip_Wid) rotateUV(0,90) texture(LanesFolder+"/Rumble_Strip.jpg") deleteUV(_Texture_Switch) color(_Usage("Auto")) Asphalt(false,1,"Auto")

Drainage--> case geometry.dv(0,unitSpace)> Lane_Width /3 && Flag_Empty_Space:#Will flag the drainage area as Red if it is >1/3 the laneWidth-I mean really 1/3 of a lane is drainage? Put a bike lane or something tileUV(0,~1,'1) cleanupGeometry(all, 0.001) texture(LanesFolder+"/Drainage_Side.jpg") color(_Usage("Conflict Zones"))#If Display Thematics==Usage, goes to usage, if not, Thematic. color(.7,0,0) deleteUV(_Texture_Switch) else: tileUV(0,~1,'1) cleanupGeometry(all, 0.001) texture(LanesFolder+"/Drainage_Side.jpg") color(_Usage("Conflict Zones"))#If Display Thematics==Usage, goes to usage, if not, Thematic. deleteUV(_Texture_Switch)

#Fence Rule

Fence(Location)--> split(v,unitSpace,0) {~1:NIL| .05:FenceMesh |~1:NIL} FencePoles

FenceMesh --> extrude(world.y,1.3) alignScopeToAxes(y) #Cast Scope to prevent edge issues alignScopeToGeometry(yUp, 0, 3)#Cast Scope to prevent edge issues. FencePrep

FencePrep--> comp(f) {left=FenceTexture|all:NIL}

FenceTexture --> case Boulevard_Center_Type=="Chain Link Fence": setupProjection(0, scope.xy, ~1.2, '1) projectUV(0) texture(MiscFolder+"/Fence/wireTexture.png") deleteUV(_Texture_Switch) case Boulevard_Center_Type=="Gate Fence":

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 177

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

setupProjection(0, scope.xy, ~4, '1) projectUV(0) texture(MiscFolder+"/Fence/aluminumPerimeter.png") deleteUV(_Texture_Switch) else: setupProjection(0, scope.xy, ~1.2, ~1) projectUV(0) texture(MiscFolder+"/Fence/wireTexture.png") deleteUV(_Texture_Switch)

FencePoles --> case Boulevard_Center_Type=="Chain Link Fence": split(u,unitSpace,0) {{0.01: PoleBase | ~ 3.5: NIL }* | 0.01: PoleBase} else: NIL poleDim = 0.04

PoleBase --> alignScopeToAxes(y) s(poleDim, 0, poleDim) center(xz) i(MiscFolder+"/Fence/quad.obj") center(xz) extrude(world.y, 1.3) comp(f) {all: PoleTexturing}

PoleTexturing --> setupProjection(0, scope.xy, 1, 1) projectUV(0) texture(MiscFolder+"/Fence/aluLight.png")

#Debugging Rules #White--> #envelope(world.up, .1016, .05, 50, .05, 50,.05,60) #alignScopeToAxes(y) #t(0,1,0) #color(1,1,1) #Red--> # alignScopeToAxes(y) # t(0,1,0) # color(1,0,0) #Blue--> #alignScopeToAxes(y) #t(0,1,0) #color(0,0,1) ##

6.3. Código empleado para generar los árboles /** * Created: 7 Nov 2013 19:16:08 GMT * Modified: Jan 2013, Redlands * Author: Esri R&D Center Zurich */ version "2013.1"

###################################################### # Control Attributes (set by user or geodatabase) #

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 178

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

@Order(1) @Range("Alder Buckthorn","Amazon Sword Plant","American Chestnut","American Sycamore","Apricot","Australian Pine","Baldcypress","Balsam Fir","Bamboo","Banana Tree","Basswood","Bay Laurel","Black Locust","Blue Gum Eucalyptus","Boxwood","Cabbage Palm Fern","California Bay","California Incense Cedar","California Palm","California Redwood","California Walnut","Coconut Palm","Common Hawthorn","Common Whitebeam","Conker Tree","Date Palm","Desert Willow","Douglas Fir","European Beech","European Larch","Ficus","Field Elm","Flannelbush","Flowering Dogwood","Giant Sequoia","Hedgehog Agave","Japanese Angelica Tree","Lacy Tree Philodendron","Leyland Cypress","Lily of the Valley","Lodgepole Pine","Mediterranean Buckthorn","Mexican Palmetto","Mountain Mahogany","Northern Red Oak","Norway Maple","Norway Spruce","Orange Tree","Orchid","Oval-leaved Privet","Palm Lily","Palo Verde","Paper Birch","Parlour Palm","Prickly Pear Cactus","Red Alder","Red Hickory","Rhododendron Azaleas","Rose","Ruffle Palm","Saguaro Cactus","Sassafras","Scots Pine","Sea Islands Yucca","Shadbush","Snake Plant","Southern Magnolia","Spanish Broom","Strawberry Tree","Sugar Maple","Sunflower","Sweetgum","Umbrella Acacia","Western Juniper","White Ash","White Oak","White Poplar","White Willow","Witch Hazel","","______","GENERICS","","Generic Dead Tree","Generic Stump","Generic Unknown","","______","PROXIES","","Algarrobo","Ameri can Elderberry","American Pepper","American Silverberry","Athel Tamarisk","Avocado","Black Tupelo","Buttonbush","Canada Buffaloberry","Chinaberry Tree","Chinese Tallow Tree","Common Hackberry","Common Holly","Common Persimmon","Desert Bitterbrush","European Hornbeam","Giant Chinquapin","Honey Locust","Hophornbeam","Huckleberry Shrub","Japanese Hemlock","Japanese Nutmeg","Judas Tree","Lawson Cypress","Loblolly Bay","Mexican Buckeye","Necklacepod","Northern Bilberry","Northern White Cedar","Octopus Tree","Osage Orange","Paper Bark Tree","Pawpaw","Persian Silk Tree","Princess Tree","Smooth Sumac","Sourwood","Southern Wax Myrtle","Tanoak","Tree of Heaven","Turkish Hazel","Western Soapberry","White Mulberry","Yellow Poplar","Yew","","______","LATIN NAME","","Abies balsamea","Acacia tortilis","Acer platanoides","Acer saccharum","Aesculus hippocastanum","Agave stricta","Ailanthus altissima","Aiphanes horrida","Albizia julibrissin","Alnus rubra","Amelanchier canadensis","Aralia elata","Arbutus unedo","Asimina triloba","Betula papyrifera","Bulbophyllum phalaenopsis","Buxus sempervirens","Calocedrus decurrens","Carnegiea saguaro","Carpinus betulus","Carya ovalis","Castanea dentata","Casuarina equisetifolia","Celtis occidentalis","Cephalanthus occidentalis","Cercis siliquastrum","Cercocarpus montanus","Chamaecyparis lawsoniana","Chamaedorea elegans","Chilopsis linearis","Chrysolepis chrysophylla","Citrus sinensis","Cocos nucifera","Convallaria majalis","Cordyline petiolaris","Cornus florida","Corylus colurna","Crataegus monogyna","Cupressus leylandii","Cyrilla racemiflora","Diospyros virginiana","Echinodorus bleheri","Elaeagnus commutata","Eucalyptus globulus","Fagus sylvatica","Ficus benjamina","Frangula alnus","Fraxinus americana","Fremontodendron californicum","Generic deadtree","Generic stump","Generic unknown","Gleditsia triacanthos","Gordonia lasianthus","Hamamelis virginiana","Helianthus annuus","Ilex aquifolium","Juglans regia","Juniperus occidentalis","Larix decidua","Laurus nobilis","Ligustrum ovalifolium","Liquidambar styraciflua","Liriodendron tulipifera","Lithocarpus densiflorus","Maclura pomifera","Magnolia grandiflora","Melaleuca quinquenervia","Melia azedarach","Morus alba","Musa acuminata","Myrica cerifera","Nyssa sylvatica"," aciculata","Ostrya virginiana","Oxydendrum arboreum","Parkinsonia aculeata","Paulownia tomentosa","Persea americana","Philodendron selloum","Phlebodium

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 179

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D aureum","Phoenix dactylifera","Phyllostachys aurea","Picea abies","Pinus contorta","Pinus sylvestris","Platanus occidentalis","Populus tremuloides","Prosopis nigra","Prunus armeniaca","Pseudotsuga menziesii","Purshia glandulosa","Quercus alba","Quercus rubra","Rhamnus alaternus","Rhododendron tsutsuji","Rhus glabra","Robinia pseudoacacia","Rosa grandiflora","Sabal mexicana","Salix alba","Sambucus canadensis","Sansevieria trifasciata","Sapindus saponaria","Sassafras albidum","Schefflera actinophylla","Schinus molle","Sequoia sempervirens","Sequoiadendron giganteum","Shepherdia canadensis","Sophora tomentosa","Sorbus aria","Spartium junceum","Tamarix aphylla","Taxodium distichum","Taxus baccata","Thuja occidentalis","Tilia americana","Torreya nucifera","Triadica sebifera","Tsuga diversifolia","Ulmus minor","Umbellularia californica","Ungnadia speciosa","Vaccinium uliginosum","Washingtonia filifera","Yucca gloriosa") attr Name = "Alder Buckthorn" # Redlands: removed "Orange Tree" as default until more accurate Orange Tree model is located (truck is too long). @Order(2) @Range(0.5,80) attr Height = getStandardHeight # default depends on Name (i.e. adapts if user selects another plant (if not overwritten by user)) @Order(3) @Range(0.5,30) attr Radius = getRadius # default depends on Name and Height (and adapts in case user adjusts only height in Inspector)

@Group("Options",4) @Order(1) @Range("Model","Fan","Analytical") attr Representation = "Model" @Group("Options") @Order(2) @Range(0,1) attr Transparency = 0 @Group("Options") @Order(3) @Color @Description("To turn color overwrite off, delete the color value (in the text field)") attr OverrideColor = "" @Group("Options") @Order(4) attr RandomRotation = true @Group("Options") @Order(5) @Description("Note that this tripples the instance count e.g. web scenes get three times bigger") attr RandomBrightness = false @Group("Options") @Order(5) @Range("Mature only","Mature and young") attr RandomHeights = "Mature and young" @Group("Options") @Order(6) @Range("None","Metadata","Instance Information") @Description("Instance Information suited for LumentRT of e- on Software and other 3rd party applications.") attr Reporting = "None"

# Constants const AssetFolder = "Plants" # no "/" at the end (taken care of below) const FallbackPlant = "Generic Unknown" # this plant representation is used in case the user-selected plant does not exist in library const RandomRadiusDeviation = 0.10 # plant radius varies plus/minus within this percentage const RandomHeightYoungPercentage = case RandomHeights=="Mature only": 0 else: 0.5 # this percentage gives random heights below the minheight

######################################################

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 180

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

# Library Functions (suited for external usage) #

# attribute lookups getGenus(commonName) = _genus(_indexFromCommonName(commonName)) getSpecies(commonName) = _species(_indexFromCommonName(commonName)) getWikipediaURL(commonName) = _wikipediaURL(_indexFromCommonName(commonName)) # consists of latin name getStandardHeight(commonName) = _heightAvg(_indexFromCommonName(commonName)) getMinimumHeight(commonName) = _heightMin(_indexFromCommonName(commonName)) getMaximumHeight(commonName) = _heightMax(_indexFromCommonName(commonName)) getRandomHeight(commonName) = _randomHeight(_indexFromCommonName(commonName)) getStandardRadius(commonName) = _radiusAvg(_indexFromCommonName(commonName)) getStandardTrunkRadius(commonName) = _trunkRadiusAvg(_indexFromCommonName(commonName)) getStandardTrunkHeight(commonName) = _trunkHeightAvg(_indexFromCommonName(commonName)) getRegions(commonName) = _regions(_indexFromCommonName(commonName)) getCrownShape(commonName) = _crownShape(_indexFromCommonName(commonName)) isProxy(commonName) = _proxy(_indexFromCommonName(commonName)) != "X"

# attribute lookups assuming that Name attr has been set correctly set getGenus = _genus(_indexFromCommonName(Name)) getSpecies = _species(_indexFromCommonName(Name)) getLatinName = getGenus + " " + getSpecies getWikipediaURL = _wikipediaURL(_indexFromCommonName(Name)) # consists of latin name getStandardHeight = _heightAvg(_indexFromCommonName(Name)) getMinimumHeight = _heightMin(_indexFromCommonName(Name)) getMaximumHeight = _heightMax(_indexFromCommonName(Name)) getRandomHeight = _randomHeight(_indexFromCommonName(Name)) getStandardRadius = _radiusAvg(_indexFromCommonName(Name)) getRegions = _regions(_indexFromCommonName(Name)) getHardinessZoneMin = _zoneMin(_indexFromCommonName(Name)) getHardinessZoneMax = _zoneMax(_indexFromCommonName(Name)) getCrownShape = _crownShape(_indexFromCommonName(Name)) isProxy = _proxy(_indexFromCommonName(Name)) != "X"

# attribute lookups assuming that Name and Height have been set getRadius = _radius(_indexFromCommonName(Name),Height) # relative to current height getRandomRadius = _randomRadius(_indexFromCommonName(Name),Height) # +-5% of default radius getTrunkHeight = _trunkHeight(_indexFromCommonName(Name),Height) # relative to current height

# attribute lookups assuming that Name and Radius have been set getTrunkRadius = _trunkRadius(_indexFromCommonName(Name),Radius) # relative to current radius

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 181

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

# general utility functions isPlantInLibrary(commonName) = listIndex(_dataCommonName,commonName) >= 0

# utility functions needed for setups which are driven by latin names (i.e. genus and species) isPlantInLibrary(genus,species) = listIndex(_dataLatinName,genus+" "+species) >= 0 isGenusInLibrary(genus) = listIndex(_dataGenus,genus) >= 0 getCommonName(genus,species) = _commonName(_indexFromLatinName(genus,species)) # NOTE: in case species is not given or wrong, then it falls back to first plant entry with this genus (i.e. first entry should be a very common species of this genus)

###################################################### # Library data with accessors (for internal usage only) #

# number of plants in library const nPlants = 127 const nModels = 82 # models (= non-proxies) MUST be listed first in the data (see _getAsset function)

# THE data from Excel sheet (latin name contains both the genus AND species column) const _dataCommonName = "Orange Tree;Balsam Fir;Umbrella Acacia;Norway Maple;Sugar Maple;Conker Tree;Hedgehog Agave;Ruffle Palm;Red Alder;Shadbush;Japanese Angelica Tree;Strawberry Tree;Paper Birch;Orchid;Boxwood;California Incense Cedar;Saguaro Cactus;Red Hickory;American Chestnut;Australian Pine;Mountain Mahogany;Parlour Palm;Desert Willow;Coconut Palm;Lily of the Valley;Palm Lily;Flowering Dogwood;Common Hawthorn;Leyland Cypress;Amazon Sword Plant;Blue Gum Eucalyptus;European Beech;Ficus;Alder Buckthorn;White Ash;Flannelbush;Generic Stump;Generic Dead Tree;Generic Unknown;Witch Hazel;Sunflower;California Walnut;Western Juniper;European Larch;Bay Laurel;Oval-leaved Privet;Sweetgum;Southern Magnolia;Banana Tree;Prickly Pear Cactus;Palo Verde;Lacy Tree Philodendron;Cabbage Palm Fern;Date Palm;Bamboo;Norway Spruce;Lodgepole Pine;Scots Pine;American Sycamore;White Poplar;Apricot;Douglas Fir;Northern Red Oak;White Oak;Mediterranean Buckthorn;Rhododendron Azaleas;Black Locust;Rose;Mexican Palmetto;White Willow;Snake Plant;Sassafras;California Redwood;Giant Sequoia;Common Whitebeam;Spanish Broom;Baldcypress;Basswood;Field Elm;California Bay;California Palm;Sea Islands Yucca;Tree of Heaven;Persian Silk Tree;Pawpaw;European Hornbeam;Common Hackberry;Buttonbush;Judas Tree;Lawson Cypress;Giant Chinquapin;Turkish Hazel;Huckleberry Shrub;Common Persimmon;American Silverberry;Honey Locust;Loblolly Bay;Common Holly;Yellow Poplar;Tanoak;Osage Orange;Paper Bark Tree;Chinaberry Tree;White Mulberry;Southern Wax Myrtle;Black Tupelo;Hophornbeam;Sourwood;Princess Tree;Avocado;Algarrobo;Desert Bitterbrush;Smooth Sumac;American Elderberry;Western Soapberry;Octopus Tree;American Pepper;Canada Buffaloberry;Necklacepod;Athel Tamarisk;Yew;Northern White Cedar;Japanese Nutmeg;Chinese Tallow Tree;Japanese Hemlock;Mexican Buckeye;Northern Bilberry;" const _dataLatinName = "Citrus sinensis;Abies balsamea;Acacia tortilis;Acer platanoides;Acer saccharum;Aesculus hippocastanum;Agave stricta;Aiphanes horrida;Alnus rubra;Amelanchier canadensis;Aralia elata;Arbutus unedo;Betula papyrifera;Bulbophyllum phalaenopsis;Buxus sempervirens;Calocedrus decurrens;Carnegiea saguaro;Carya ovalis;Castanea dentata;Casuarina equisetifolia;Cercocarpus montanus;Chamaedorea

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 182

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D elegans;Chilopsis linearis;Cocos nucifera;Convallaria majalis;Cordyline petiolaris;Cornus florida;Crataegus monogyna;Cupressus leylandii;Echinodorus bleheri;Eucalyptus globulus;Fagus sylvatica;Ficus benjamina;Frangula alnus;Fraxinus americana;Fremontodendron californicum;Generic stump;Generic deadtree;Generic unknown;Hamamelis virginiana;Helianthus annuus;Juglans regia;Juniperus occidentalis;Larix decidua;Laurus nobilis;Ligustrum ovalifolium;Liquidambar styraciflua;Magnolia grandiflora;Musa acuminata;Opuntia aciculata;Parkinsonia aculeata;Philodendron selloum;Phlebodium aureum;Phoenix dactylifera;Phyllostachys aurea;Picea abies;Pinus contorta;Pinus sylvestris;Platanus occidentalis;Populus tremuloides;Prunus armeniaca;Pseudotsuga menziesii;Quercus rubra;Quercus alba;Rhamnus alaternus;Rhododendron tsutsuji;Robinia pseudoacacia;Rosa grandiflora;Sabal mexicana;Salix alba;Sansevieria trifasciata;Sassafras albidum;Sequoia sempervirens;Sequoiadendron giganteum;Sorbus aria;Spartium junceum;Taxodium distichum;Tilia americana;Ulmus minor;Umbellularia californica;Washingtonia filifera;Yucca gloriosa;Ailanthus altissima;Albizia julibrissin;Asimina triloba;Carpinus betulus;Celtis occidentalis;Cephalanthus occidentalis;Cercis siliquastrum;Chamaecyparis lawsoniana;Chrysolepis chrysophylla;Corylus colurna;Cyrilla racemiflora;Diospyros virginiana;Elaeagnus commutata;Gleditsia triacanthos;Gordonia lasianthus;Ilex aquifolium;Liriodendron tulipifera;Lithocarpus densiflorus;Maclura pomifera;Melaleuca quinquenervia;Melia azedarach;Morus alba;Myrica cerifera;Nyssa sylvatica;Ostrya virginiana;Oxydendrum arboreum;Paulownia tomentosa;Persea americana;Prosopis nigra;Purshia glandulosa;Rhus glabra;Sambucus canadensis;Sapindus saponaria;Schefflera actinophylla;Schinus molle;Shepherdia canadensis;Sophora tomentosa;Tamarix aphylla;Taxus baccata;Thuja occidentalis;Torreya nucifera;Triadica sebifera;Tsuga diversifolia;Ungnadia speciosa;Vaccinium uliginosum;" const _dataGenus = "Citrus;Abies;Acacia;Acer;Acer;Aesculus;Agave;Aiphanes;Alnus;Amelanchier;Ar alia;Arbutus;Betula;Bulbophyllum;Buxus;Calocedrus;Carnegiea;Carya;Castanea; Casuarina;Cercocarpus;Chamaedorea;Chilopsis;Cocos;Convallaria;Cordyline;Cor nus;Crataegus;Cupressus;Echinodorus;Eucalyptus;Fagus;Ficus;Frangula;Fraxinu s;Fremontodendron;Generic;Generic;Generic;Hamamelis;Helianthus;Juglans;Juni perus;Larix;Laurus;Ligustrum;Liquidambar;Magnolia;Musa;Opuntia;Parkinsonia; Philodendron;Phlebodium;Phoenix;Phyllostachys;Picea;Pinus;Pinus;Platanus;Po pulus;Prunus;Pseudotsuga;Quercus;Quercus;Rhamnus;Rhododendron;Robinia;Rosa; Sabal;Salix;Sansevieria;Sassafras;Sequoia;Sequoiadendron;Sorbus;Spartium;Ta xodium;Tilia;Ulmus;Umbellularia;Washingtonia;Yucca;Ailanthus;Albizia;Asimin a;Carpinus;Celtis;Cephalanthus;Cercis;Chamaecyparis;Chrysolepis;Corylus;Cyr illa;Diospyros;Elaeagnus;Gleditsia;Gordonia;Ilex;Liriodendron;Lithocarpus;M aclura;Melaleuca;Melia;Morus;Myrica;Nyssa;Ostrya;Oxydendrum;Paulownia;Perse a;Prosopis;Purshia;Rhus;Sambucus;Sapindus;Schefflera;Schinus;Shepherdia;Sop hora;Tamarix;Taxus;Thuja;Torreya;Triadica;Tsuga;Ungnadia;Vaccinium;" const _dataSpecies = "sinensis;balsamea;tortilis;platanoides;saccharum;hippocastanum;stricta;hor rida;rubra;canadensis;elata;unedo;papyrifera;phalaenopsis;sempervirens;decu rrens;saguaro;ovalis;dentata;equisetifolia;montanus;elegans;linearis;nucife ra;majalis;petiolaris;florida;monogyna;leylandii;bleheri;globulus;sylvatica ;benjamina;alnus;americana;californicum;stump;deadtree;unknown;virginiana;a nnuus;regia;occidentalis;decidua;nobilis;ovalifolium;styraciflua;grandiflor a;acuminata;aciculata;aculeata;selloum;aureum;dactylifera;aurea;abies;conto rta;sylvestris;occidentalis;tremuloides;armeniaca;menziesii;rubra;alba;alat ernus;tsutsuji;pseudoacacia;grandiflora;mexicana;alba;trifasciata;albidum;s empervirens;giganteum;aria;junceum;distichum;americana;minor;californica;fi lifera;gloriosa;altissima;julibrissin;triloba;betulus;occidentalis;occident alis;siliquastrum;lawsoniana;chrysophylla;colurna;racemiflora;virginiana;co mmutata;triacanthos;lasianthus;aquifolium;tulipifera;densiflorus;pomifera;q uinquenervia;azedarach;alba;cerifera;sylvatica;virginiana;arboreum;tomentos a;americana;nigra;glandulosa;glabra;canadensis;saponaria;actinophylla;molle

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 183

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

;canadensis;tomentosa;aphylla;baccata;occidentalis;nucifera;sebifera;divers ifolia;speciosa;uliginosum;" const _dataHeightMin = "5;10;5;20;25;25;1;3;15;3;3;5;12;0.5;0.8;20;3;20;20;10;3;1;2;20;0.15;2;5;5; 3;0.5;20;10;2;6;10;2;0.4;5;5;2;1.5;15;20;20;2;2;10;15;3;0.5;2;0.5;0.5;20;5; 12;30;25;20;12;4;45;18;14;1;0.5;10;0.5;12;12;0.5;9;50;50;15;2;25;25;20;20;1 4;2;10;5;8;15;7;2;6;20;20;15;3;2;1;20;10;10;18;20;3;10;4;10;3;20;14;10;10;1 0;10;1;1;2;2;3;10;1;1;12;10;10;10;8;15;2;0.5;" const _dataHeightMax = "13;20;15;30;35;35;2;10;20;5;5;10;18;1.5;1.2;30;9;30;30;20;4;3;6;30;0.3;4;1 0;15;7;1.5;30;15;4;14;16;4;1;35;35;4;3.5;25;25;40;6;4;16;25;6;1;6;1.5;1.5;2 5;9;20;50;45;40;20;10;75;35;24;5;2;16;1.5;18;18;1;18;80;80;25;4;40;35;26;30 ;22;3;15;12;12;25;13;4;10;40;30;25;5;4;3;30;20;10;32;25;7;20;12;14;5;25;18; 20;25;20;20;3;4;4;6;15;15;4;3;18;20;20;20;12;25;4;1.5;" const _dataHeightAvg = "9;15;10;25;30;30;1.5;6.5;17.5;4;4;7.5;15;1;1;25;6;25;25;15;3.5;2;4;25;0.25 ;3;7.5;10;5;1;25;12.5;3;10;13;3;0.6;20;20;3;2.5;20;22.5;30;4;3;13;20;4.5;0. 75;4;1;1;22.5;7;16;40;32;30;16;7;60;24;19;3;1.25;13;1;15;15;0.75;13.5;65;65 ;20;3;30;30;23;25;18;2.5;12.5;8.5;10;20;10;3;8;30;25;20;4;3;2;25;15;15;24;2 2.5;5;15;8;12;4;22;16;15;17;15;15;2;2;3;4;10;12;2.5;2;15;15;15;15;10;20;3;1 ;" const _dataRadiusAvg = "2.5;3.35;4.35;6.3;10.21;9;1.06;2.16;2.97;0.92;1.84;2.54;3.75;0.47;0.44;4.3 5;0.82;9.02;4.38;3.28;1.38;0.83;2.11;5.12;0.07;0.7;2.4;3.07;0.64;0.56;7.1;4 .5;0.9;3.63;2.8;0.66;0.5;5;5;1.72;0.56;9.06;11.03;4.57;0.8;0.5;2.85;7.64;1. 5;0.49;2.16;0.7;0.85;6.56;1.66;3.02;6.59;5.96;6.06;2.9;2.02;12.28;10.35;8.5 6;1.07;0.37;3.49;0.57;3.59;4.17;0.13;2.94;9.42;13.93;6;0.99;8.56;6.85;7.81; 9.38;3.24;0.68;2.69;2.72;3;4.36;2.18;0.66;2.88;6.57;11.26;4.56;1.58;0.87;0. 4;8.51;4.6;2.72;9.17;8.11;1.44;4.26;2.15;4.33;2.29;4.74;6.11;4.03;7.65;4.33 ;6.47;1.14;0.66;0.92;2.16;2.68;3.98;0.83;1.41;6.47;1.91;1.91;2.84;3;3.78;0. 99;0.22;" const _dataCrownShape = "S4;S8;S5;S4;S4;S5;S6;S6;S7;S6;S5;S4;S4;S2;S6;S4;S2;S4;S5;S6;S6;S5;S5;S4;S5 ;S5;S5;S5;S3;S5;S4;S4;S4;S5;S5;S7;S1;S4;S4;S4;S6;S4;S4;S4;S5;S7;S5;S4;S4;S4 ;S5;S6;S5;S4;S6;S5;S4;S6;S4;S5;S4;S6;S5;S4;S4;S6;S4;S4;S4;S6;S6;S5;S5;S4;S4 ;S5;S6;S5;S4;S4;S4;S4;S5;S5;S4;S5;S5;S7;S4;S6;S4;S5;S6;S4;S7;S4;S5;S5;S4;S4 ;S4;S4;S4;S4;S4;S5;S4;S4;S4;S4;S5;S4;S5;S5;S5;S4;S6;S5;S6;S5;S3;S3;S5;S4;S5 ;S5;S7;" const _dataTrunkRadiusAvg = "0.13;0.35;0.35;0.46;0.85;0.8;0.04;0.1;0.34;0.12;0.11;0.21;0.23;0.05;0.05;0 .31;0.18;0.68;0.56;0.32;0.12;0.04;0.13;0.2;0.05;0.03;0.23;0.21;0.09;0.07;0. 64;0.32;0.06;0.1;0.17;0.1;0.5;0.5;0.5;0.06;0.04;0.4;1.03;0.5;0.06;0.11;0.2; 0.48;0.09;0.04;0.09;0.1;0.09;0.54;0.08;0.23;0.58;0.39;0.68;0.23;0.11;0.88;0 .82;0.46;0.11;0.03;0.18;0.05;0.21;0.23;0.04;0.22;1.3;2.39;0.29;0.1;0.46;0.4 3;1.11;1.1;0.25;0.04;0.17;0.26;0.2;0.33;0.16;0.1;0.2;0.64;0.61;0.29;0.13;0. 05;0.07;0.7;0.32;0.22;0.58;0.57;0.08;0.38;0.11;0.32;0.08;0.29;0.38;0.2;0.41 ;0.23;0.51;0.09;0.07;0.06;0.09;0.13;0.18;0.08;0.2;0.51;0.26;0.26;0.21;0.15; 0.28;0.1;0.03;" const _dataTrunkHeightAvg = "2.1;4;5.2;4.25;8.1;4.8;0;3.64;6.3;0;1;2.17;3.3;0;0;6;1.32;4;7.25;2.25;0;0; 1.52;15.75;0;0.81;2.17;2.1;0.15;0.26;7;3;0.63;1.8;1.43;0;0.6;6;6;0.45;0;4.8 ;7.87;4.5;0;0;2.34;3.2;2.48;0.04;1.36;0;0;12.6;0;2.4;8.6;7.36;6.6;2.08;1.75 ;7.2;9.84;3.99;0.24;0;4.03;0;9.15;4.9;0;2.97;29.9;9.1;6.8;0;16.5;6.6;7.59;6 .75;11.7;0.68;1.38;2.46;2.1;4.4;2.2;0;1.92;4.5;5.25;4.4;0;0.75;0;6.75;3.15; 1.95;3.84;5.4;1.25;4.2;2.48;1.92;0.6;2.42;2.56;4.65;3.57;3.75;6.15;0;0;0.63 ;1.36;3.1;3.36;0;0;6.15;0.45;0.45;2.25;3.4;3;0;0;" const _dataRegions = "NA,EU,AS,SA;NA;AF,AS;EU,AS;NA,EU;EU;NA;SA,NA;NA;NA;AS;AS;NA;AS;NA,EU;NA;NA ;NA,EU;NA,EU,AS;AU;NA;NA;NA;NA,AS;NA,AS,EU;AU;NA,EU;EU,AS,AF;NA,EU;SA,NA;AU ,AS,NA;EU;AU;AU,EU;EU,NA,AS;NA,EU;NA,AS,EU,AF,SA,AU;NA,AS,EU,AF,SA,AU;NA,AS ,EU,AF,SA,AU;NA;NA,SA,EU;EU,NA;NA;EU,NA,AS;EU,NA;EU;NA;NA;AS,SA;NA;NA,AF;NA

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 184

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

,AF,AU;NA,SA;AS,NA,SA;AS;EU;NA;EU,AS,NA;NA;NA;NA,EU,AS;NA;NA;NA;EU;NA,EU,AS ;NA,EU;NA,EU;NA;NA,EU,AS;AS,SA;NA;NA;NA;EU;EU,AS,AF;NA;NA;EU,NA;NA;NA;NA;AS ,NA;AS;NA;EU;NA;NA;EU,AS;NA;NA;AS;NA,SA;NA,EU;NA;AS,NA;NA,AS;EU,AF,AS;NA,AS ;NA;NA,AS;AU;AU;NA;NA;NA;EU,NA;NA;AS;NA;SA;NA;NA;NA;NA;AU;SA;NA;AS,NA;AF,AU ,AS;EU,AF,AS;NA;AS;AS,NA;AS,NA;NA;NA;" const _dataZoneMin = "9;3;9;3;3;4;10;10;7;4;4;7;2;11;5;5;8;4;4;9;4;10;7;10;2;10;5;4;6;10;9;4;10; 3;3;9;0;0;0;3;4;5;5;3;8;4;5;6;9;8;8;8;9;8;6;2;1;3;4;2;5;3;3;3;8;3;4;3;8;2;9 ;4;7;6;6;8;4;3;3;9;9;6;5;6;5;5;3;4;6;5;6;4;5;4;2;4;8;5;4;7;4;9;7;4;7;4;3;5; 6;9;9;3;3;4;7;9;8;2;9;7;5;2;6;8;6;7;2;" const _dataZoneMax = "11;5;11;7;8;7;11;11;8;7;8;9;7;11;8;8;11;8;8;11;4;11;11;11;7;11;9;8;10;11;1 1;7;11;7;9;11;12;12;12;8;9;9;8;6;10;7;9;10;11;10;11;11;11;11;11;7;7;7;9;5;7 ;6;8;9;9;7;9;10;11;8;11;8;10;8;8;9;10;9;9;11;11;11;8;9;8;7;9;10;9;7;9;7;10; 9;6;8;9;9;9;11;9;11;9;9;10;9;9;8;9;10;9;9;9;9;10;11;11;6;11;10;8;8;10;10;9; 9;6;" const _dataProxy = "X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X; X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X ;X;X;X;X;X;X;X;White Ash;Flowering Dogwood;Ficus;Sassafras;Sassafras;Flannelbush;European Beech;Australian Pine;White Oak;Basswood;Mountain Mahogany;Apricot;Flannelbush;Sugar Maple;Common Hawthorn;White Poplar;Southern Magnolia;European Beech;Apricot;Blue Gum Eucalyptus;Black Locust;Red Hickory;Witch Hazel;White Ash;Southern Magnolia;Black Locust;White Oak;Apricot;Northern Red Oak;Rose;Spanish Broom;Common Hawthorn;Palo Verde;Black Locust;White Willow;Spanish Broom;Lacy Tree Philodendron;Northern Red Oak;Leyland Cypress;Leyland Cypress;Norway Spruce;Common Whitebeam;Norway Spruce;Spanish Broom;Flannelbush;"

# Get index from common name, latin name, or genus. _indexFromName(name) = _indexCheckCommonName(listIndex(_dataCommonName, name), name) _indexCheckCommonName(idx, name) = case idx < 0: _indexCheckLatinName(listIndex(_dataLatinName, name), name) # fallback if plant has not been found else: idx _indexCheckLatinName(idx, name) = case idx < 0: _indexCheckGenus(listIndex(_dataGenus,_genusFromLatinName(name))) # fallback if plant has not been found else: idx _indexCheckGenus(idx) = case idx < 0: _fallbackIdx # fallback if plant has not been found else: idx

# getting index for accessors either via common name only (no latin name fallback) # kept here in case we still need it, but might be deprecated due to _indexFromName. _indexFromCommonName(commonName) = _indexFromName(commonName) _indexCheck(idx) = case idx < 0: _fallbackIdx else: idx # fallback if plant has not been found

_genusFromLatinName(latinName) = getPrefix(latinName, " ")

# getting index via latin name: in case plant cannot be found, we try to search a plant of at least the given genus as first fallback

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 185

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

_indexFromLatinName(genus,species) = _indexCheckLatin(listIndex(_dataLatinName,genus+" "+species),genus) _indexCheckLatin(idx,genus) = case idx < 0: _indexCheck(listIndex(_dataGenus,genus)) else: idx

# this plantNbr is displayed if the user-selected plant does not exist in library const _fallbackIdx = listIndex(_dataCommonName,FallbackPlant)

# accessors _commonName(idx) = listItem(_dataCommonName,idx) _latinName(idx) = listItem(_dataLatinName,idx) _genus(idx) = listItem(_dataGenus,idx) _species(idx) = listItem(_dataSpecies,idx) _heightMax(idx) = float(listItem(_dataHeightMax,idx)) _heightMin(idx) = float(listItem(_dataHeightMin,idx)) _heightAvg(idx) = case _valid(idx): float(listItem(_dataHeightAvg,idx)) else: 1 # to avoid divisions by zero _radiusAvg(idx) = case _valid(idx): float(listItem(_dataRadiusAvg,idx)) else: 1 # to avoid divisions by zero _trunkHeightAvg(idx)= float(listItem(_dataTrunkHeightAvg,idx)) _trunkRadiusAvg(idx)= float(listItem(_dataTrunkRadiusAvg,idx)) _crownShape(idx) = listItem(_dataCrownShape,idx) _regions(idx) = listItem(_dataRegions,idx) _zoneMin(idx) = float(listItem(_dataZoneMin,idx)) _zoneMax(idx) = float(listItem(_dataZoneMax,idx)) _proxy(idx) = listItem(_dataProxy,idx)

# special accessors: randomHeight _randomHeight(idx) = case p(RandomHeightYoungPercentage): _randomHeightYoung(_heightMin(idx)) else : _randomHeightMature(_heightMin(idx),_heightMax(idx)) _randomHeightYoung(hMin) = rand(hMin * 0.7,hMin)

_randomHeightMature(hMin,hMax) = rand(hMin,hMax)

# special accessors: getting plant attributes for given height or radius _radius(idx,height) = _radiusAvg(idx) * height/_heightAvg(idx) _randomRadius(idx,height) = _radius(idx,height) * rand(1- RandomRadiusDeviation,1+RandomRadiusDeviation) _trunkHeight(idx,height) = _trunkHeightAvg(idx) * height/_heightAvg(idx) _trunkRadius(idx,radius) = _trunkRadiusAvg(idx) * radius/_trunkRadiusAvg(idx)

# helper _valid(idx) = 0 <= idx && idx < nPlants _wikipediaURL(idx) = "http://en.wikipedia.org/wiki/" + _genus(idx) + "_" + _species(idx)

###################################################### # Internal functions for rules only #

# for higher performance (i.e. plant index for getting radius/height/radius can be stored to avoid multiple index lookups via name) @Hidden

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 186

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D attr _plantNbr = 0 @Hidden attr _plantName = "" @Hidden attr _plantHeight = 0 @Hidden attr _plantRadius = 0

# validate name (assummes that _plantNbr has been set) _validate(name) = case _plantNbr==_fallbackIdx: FallbackPlant else: name

# file handling (assumes that Name and _plantNbr is correctly set) _getAsset = case _plantNbr < nModels: _getFilepath(replace(_plantName," ","_")) else : _getFilepath(replace(_proxy(_plantNbr)," ","_"))

_getFilepath(commonNameUnderscores) = AssetFolder + "/" + commonNameUnderscores + "/" + commonNameUnderscores + "_" + Representation + "_0.obj"

# asset scale handling (assumes that Height, Radius, _plantNbr have been set and the asset has been inserted) _getScaleY = _plantHeight/scope.sy _getScaleXZ = case _plantRadius > 0 : _plantRadius/_radius(_plantNbr,scope.sy) # the ratio of the user-set ratio versus the ratio of the inserted asset (since the ratio does not correspond to the bounding box, this has to be looked up (i.e. getting the value of the average-sized tree)) else : _plantHeight/scope.sy * rand(1- RandomRadiusDeviation,1+RandomRadiusDeviation) # in case the Radius is zero, we assume the (most typical) random case. This is for performance reasons only --> see also alternative plant loader rule which uses this as marker (to save above lookups which are not needed if the user-set Radius has not been set)

# rule helpers _roundTransparency = rint(20*Transparency) / 20 # round to 0.05 steps (to avoid the creation of too many materials) _randomRotation = case RandomRotation: rand(0,360) else: 0

######################################################################## ######################################################################## ### ### RULES ### ###

###################################################### # Plant Loader #

@StartRule # assumes that all main attributes have been set outside

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 187

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Generate --> case Height > 0: set(_plantNbr,_indexFromName(Name)) set(_plantName,_validate(_commonName(_plantNbr))) set(_plantHeight,Height) set(_plantRadius,Radius) s(0,0,0) center(xyz) alignScopeToAxes(y) TrunkOrigin else: Generate(Name)

TrunkOrigin --> case Representation == "Analytical": PlantAnalytical case Representation == "Fan": PlantFan else: PlantModel

###################################################### # Alternative Plant Loader (doesn't use the main attributes!) # # In the most typical design use case where a random-sized plant needs to # be set, we recommend to use this rule in the importing rule file. # # On the one hand it is more practical since the attributes do not need to be # set before calling it as in the Plant rule above. But the main reason why # we are provding this rule is that it is faster (because less library lookups # are required here).

Generate(name) --> set(_plantNbr,_indexFromName(name)) set(_plantName,_validate(name)) set(_plantHeight,_randomHeight(_plantNbr)) set(_plantRadius,0) # marks that the random radius can be used s(0,0,0) center(xyz) alignScopeToAxes(y) TrunkOrigin

###################################################### # Realistic Model #

PlantModel --> PlantModel(_getAsset)

PlantModel(asset) --> # needs special treatment because the bbox of the asset is not centered in orgin: i(asset) PlantModel(_getScaleY,_getScaleXZ,

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 188

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

assetInfo(asset,tx)/scope.sx, # relative origin offset in x-dir (trunk is at origin i.e. this value is needed for scaling around origin) assetInfo(asset,tz)/scope.sz) # relative origin offset in z-dir (trunk is at origin i.e. this value is needed for scaling around origin)

PlantModel(scaleY,scaleXZ,relOffsetX,relOffsetZ) --> t('-relOffsetX,0,'-relOffsetZ) r(0,_randomRotation,0) s('scaleXZ,'scaleY,'scaleXZ) # scale standard model to meet the user-given Height and Radius t('relOffsetX,0,'relOffsetZ) PlantVisualization

###################################################### # Analytical Model #

PlantAnalytical --> i(_getAsset) PlantAnalytical(_getScaleY,_getScaleXZ)

PlantAnalytical(scaleY,scaleXZ) --> s('scaleXZ,'scaleY,'scaleXZ) center(xz) PlantVisualization

###################################################### # Fan #

PlantFan --> i(_getAsset) PlantFan(_getScaleY,_getScaleXZ)

PlantFan(scaleY,scaleXZ) --> s('scaleXZ,'scaleY,'scaleXZ) center(xz) r(scopeCenter,0,_randomRotation,0) PlantVisualization

###################################################### # Post operations #

PlantVisualization --> case OverrideColor != "" && _roundTransparency > 0.01: # leaf cards will not work in webgl anymore (CE2013) set(material.opacity,1-_roundTransparency) set(material.colormap,"") color( OverrideColor ) PlantReporting case OverrideColor != "": # leaf cards will not work in webgl anymore (CE2013) set(material.colormap,"") color( OverrideColor )

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 189

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

PlantReporting case _roundTransparency > 0.01: # leaf cards will not work in webgl anymore (CE2013) set(material.opacity,1-_roundTransparency) PlantReporting case RandomBrightness: color(40%: "#ffffff" 33%: "#dddddd" else: "#bbbbbb") # variation in brightness for better looks (but tripples the instance count...) PlantReporting else: PlantReporting

PlantReporting --> case Reporting == "Metadata": PlantFinal report( "Common Name", _plantName ) report( "Genus", _genus(_plantNbr) ) report( "Species", _species(_plantNbr) ) report( "Total Height", _plantHeight ) report( "Trunk Height", _trunkHeight(_plantNbr,_plantHeight) ) report( "Trunk Radius", _trunkRadius(_plantNbr,_plantRadius) ) report( "Crown Radius", _plantRadius ) report( "Crown Shape", _crownShape(_plantNbr) ) report( "Wikipedia URL for Species",_wikipediaURL(_plantNbr) ) report( "Minimun Height of Species",_heightMin(_plantNbr) ) report( "Maximum Height of Species",_heightMax(_plantNbr) ) report( "Hardiness Zone Min", _zoneMin(_plantNbr) ) report( "Hardiness Zone Max", _zoneMax(_plantNbr) ) report( "Contintents of Species", _regions(_plantNbr) ) NIL case Reporting == "Instance Information": PlantFinal report("asset", "Plants/" + _plantName ) report("scale", _plantHeight ) # report position in world coords s(0.001,'1,0.001) center(xz) # This line was causing trees to become vertical line. report("xpos", convert(x,scope,world,pos,0,0,0) ) report("ypos", convert(y,scope,world,pos,0,0,0) ) report("zpos", convert(z,scope,world,pos,0,0,0) ) # report rotation in world coords

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 190

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

report("xrot", - (convert(x,scope,world,orient,0,0,0)) ) report("yrot", - (convert(y,scope,world,orient,0,0,0)) ) report("zrot", convert(z,scope,world,orient,0,0,0) ) NIL else: PlantFinal

PlantFinal --> PlantFinal.

########################################### # DEV NOTES: # # Move Random Brightness and Height to the distributor rules - Loader standalone does not use them. # Consider replacing all instances of _indexFromCommonName with _indexFromName; needs more thorough testing first. # Reporting of strings is not supported yet, but we are reporting strings here in anticipation of that.

6.4. Código empleado para generar el edificio nuevo

/** * File: edificio_nuevo.cga * Created: 4 May 2008 23:27:29 GMT * Author: Antonio */ version "2010.3"

/* Attributes *************************************/ attr groundfloor_height = 4 attr floor_height = 3.5 attr tile_width = 3 attr Height = 11 attr wallColor = "#fefefe" attr LOD = 1 /* Assets *************************************/

// geometries window_asset = "facades/window.obj"

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 191

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

// textures frontdoor_tex = "facades/textures/shopdoor.tif" wall_tex = "facades/textures/brickwall.jpg" dirt_tex = "facades/textures/dirtmap.15.tif" roof_tex = "roofs/roof.tif"

# this function will get one of the 9 window textures in the assets folder randomWindowTexture = fileRandom("*facades/textures/window.*.tif")

/* Initial Shape starting rule *************/

# scale the lit to leave a small border and extrude the lot to building height Lot --> extrude(Height) Building

# inner lots are dropped LotInner --> NIL

# split the building geometry into its facade components Building --> comp(f) { front : Frontfacade | side : Sidefacade | top: Roof}

# the front facade is subdivided into one front groundfloor # and upper floors Frontfacade --> setupProjection(0, scope.xy, 1.5, 1, 1) # setup 1.5m x 1m texture tiles along scopes xy plane (and distortion in z) setupProjection(2, scope.xy, scope.sx, scope.sy) split(y){ groundfloor_height : Groundfloor | {~floor_height : Floor}* }

# a side facade is subdivided into one bottom floor # and upper floors. Sidefacade --> setupProjection(0, scope.xy, 1.5, 1, 1) # setup 1.5m x 1m texture tiles along scopes xy plane (and distortion in z) setupProjection(2, scope.xy, scope.sx, scope.sy) split(y){ groundfloor_height : Floor | {~floor_height : Floor}* }

# a roof texture is applied to the roof face Roof --> setupProjection(0, scope.xy, scope.sx, scope.sy) texture(roof_tex) projectUV(0)

# each floor is horizontally split into two narrow corner areas on # each side of the floor, and into a set of window tiles in between Floor -->

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 192

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

split(x){ 1 : Wall | { ~tile_width : Tile }* | 1 : Wall }

# similarily, the front groundfloor is horizontally split into # two narrow corner areas on each side of the floor, # a special entrance tile on the right # and into a set of window tiles in between Groundfloor --> split(x){ 1 : Wall | { ~tile_width : Tile }* | ~tile_width : EntranceTile | 1 : Wall }

# a tile consists of a centered window element and # wall elements above, below, left and right Tile --> split(x){ ~1 : Wall | 2 : split(y){ 1: Wall | 1.5: Window | ~1: Wall } | ~1 : Wall }

# similarily, the EntranceTile contains a centered Door element, # but with no wall on spacing below EntranceTile --> split(x){ ~1 : SolidWall | 2 : split(y){ 2.5: Door | ~2: SolidWall } | ~1 : SolidWall }

# firstly, the depth and the depth position of the future window is set # secondly, one of nine window textures is randomly selected # finally, the window geometry asset is inserted Window --> case LOD > 0 : s('1,'1,0.4) t(0,0,-0.25) texture(randomWindowTexture) i(window_asset) else : setupProjection(0,scope.xy,scope.sx,scope.sy) texture(randomWindowTexture) projectUV(0)

# same for the door asset. Scaling, positioning, texture selection # and geometry insert # TODO: fix door uv bug (problem with uv handling on split?) Door --> case LOD > 0 : s('1,'1,0.1) t(0,0,-0.5) texture(frontdoor_tex) i("builtin:cube") else : setupProjection(0,scope.xy,scope.sx,scope.sy) texture(frontdoor_tex) projectUV(0)

# for the wall asset, setting the texture scale params u and v

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 193

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

# guarantees a texture mapping that nicely fits over the whole facade Wall --> color(wallColor) texture(wall_tex) set(material.dirtmap, dirt_tex) projectUV(0) projectUV(2)

SolidWall --> case LOD > 0 : color(wallColor) s('1,'1,0.4) t(0,0,-0.4) texture(wall_tex) set(material.dirtmap, dirt_tex) i("builtin:cube:notex") projectUV(0) projectUV(2) else : Wall

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 194

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

7. Mapas

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 195

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 196

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 197

Antonio de la Torre Morales Técnicas Geomáticas y Modelado Procedural para la Generación de Modelos Urbanos en 3D

Centro de Estudios de Postgrado Master Universitario en Tecnologías Geoespaciales aplicadas a la Gestión Inteligente del Territorio 198