Working with and Exporting Geospatial Data

Working with and Exporting Geospatial Data

We are introducing an upcoming set of features that enable Grasshopper users to work with geospatial data and export the project in the GeoJSON format that can be used to generate web maps and other interactive web content. 

In the first part of this introduction / tutorial I will give a brief overview of the new components. In the second part I will present the Mapbox platform, which offers web maps creation trough user-friendly editing interface without the requirement of prior web developement experience.

Research Team: Ondřej Veselý, Martin Bielik, Dr. Reinhard Koenig

You can download an early test release of components used in this article here.

Spatial Reference components|   

Give access to WKT (Well-known-text) definition for any spatial reference system (SRS) your data could use.

EPSG:4326 component provides you with WGS84. This is basicaly the default SRS that you should use for exporting your data as GeoJSON.

Get UTM component gives you UTM system used at the given location. This is the SRS your data were probably reprojected to, if you used plugins like Gismo or Elk2.

Get WKT component queries spatialreference.org for any other arbitrary SRS and gives you the WKT definition.

Reprojection components |   

Use ProjNET and GeoAPI libraries to reproject a set of points / coordinates from one SRS to another.

Transformation component generates a transformation guide that you can use to reproject points from one SRS to another.

Reprojection component transforms coordinates to target SRS using guide from Transformation component.

Source Offset component helps with cases, when your source dataset was translated from it’s original position in it’s respective SRS to Rhino origin point (or any other).

(Both most popuplar plugins for getting geospatial data into Grasshopper – Gismo and Elk2 – are guilty of doing this).

Decompose Extrusion component |  

Helps you preserve 3D geometry, since GeoJSON doesn’t have native support for extrusions or meshes.

Decompose Extrusion takes any breps or meshes and gives you their footprint and z-axis minimums and maximums. You can then export them as polygons with height informaton included as property.

GeoJSON components |  

Convert Rhino Geometry to GeoJSON Features. Each branch of Grasshopper data will becomes single Feature.

Points component converts Points to GeoJSON Point, or MultiPoint if it recieves mutliple objects.

Lines component converts Lines or Curves to GeoJSON LineString, or MultiLineString if it recieves multiple objects.

Polygons component converts Curves to GeoJSON Polygonor MultiPolygon if it recieves multiple objects. Will create only simple polygons without holes!

Complex Polygons component converts Curves to GeoJSON Polygons. It supports inner holes. First curve in the list will be the exterior curve, the rest will be interior.

GeoJSON Export components |  

Creates a GeoJSON file from your geometry features.

Merge GeoJSON component takes GeoJSON Features or complete FeatureCollections and merges them into single FeatureCollection (always do this before exporting).

Write File component saves a list of strings (texts) into text file on your computer (Therefore it’s use is limited not only to saving GeoJSON).

Uploading to Mapbox

With your geospatial data exported from Grasshopper, next thing you could want is to bring it to the web. Currently there are multiple open projects focused on the issue of Web Mapping (see Leaflet, OpenLayers, Mapnikthat allow you to build your web map application from the ground up, but that could be an overhelming task to anyone without previous knowledge of web development.

For those who are not comfortable around developing apps with JavaScript, I recommend looking into Mapbox. It’s an open source mapping platform, that integrates all the neccesary web technologies into one package. You can control most of the basic aspects of your web map trough Mapbox Studio, a visual interface for managing your geospatial data and controling how exactly will it be displayed to the end-users.

To prepare the data for use in your web map, it has to be first processed into vector tile sets – basically splitting the  data into smaller chunks. Luckily, Mapbox will handle this automaticaly and host your tile sets on their server.

Just upload the GeoJSON file as a new tileset and see for yourself.

Tip: There’s of limit on maximum number of user tile sets used in one map (15).

Try combining your data into single GeoJSON/tileset and then use filters to get specific data sets back. It will also save you time when reuploading updated data later.

To create your own map, you first need to create a new Style – you can also copy one of the exisiting ones. Then add your vector tile data as additional Layers to the Style. You can modify the Layer style properties, ie. colour, stroke witdth etc., directly in the interface and immediatly see the visual changes.

Once you are happy with the result, hit Publish to update the Style and Share to generate a link that anyone can use to view the map.

Done! It was that easy. 🙂

However, if you are interested in adding some interactivity to your model, you will have to get yourself familiar with JavaScript library called Mapbox GL JS.

Mapbox GL JS is a JavaScript library that renders vector tile data from Mapbox to your browser window, but you can also use it to add custom functionality to your web application.

It’s pretty accessible even for first time JavaScript users, since it’s very well documented including many examples for any basic functionality you would like to include.

Congratulations! If you followed trough the steps, your  project should be now ready to be uploaded to web and shared with the rest of the  world!

Below you can explore an example of a project we have published using the methods described.

.

An example of a project exported from Grasshopper using the methods described.

<style><!-- [et_pb_line_break_holder] --> /*-----CSS style for the layer and view selection widget-----*/<!-- [et_pb_line_break_holder] --> #layer-menu {<!-- [et_pb_line_break_holder] --> position: absolute;<!-- [et_pb_line_break_holder] --> z-index: 1;<!-- [et_pb_line_break_holder] --> top: 10px;<!-- [et_pb_line_break_holder] --> left: 10px;<!-- [et_pb_line_break_holder] --> width: 160px;<!-- [et_pb_line_break_holder] --> font-family: 'Open Sans', sans-serif;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> #camera-menu {<!-- [et_pb_line_break_holder] --> position: absolute;<!-- [et_pb_line_break_holder] --> z-index: 1;<!-- [et_pb_line_break_holder] --> top: 10px;<!-- [et_pb_line_break_holder] --> right: 50px;<!-- [et_pb_line_break_holder] --> width: 80px;<!-- [et_pb_line_break_holder] --> font-family: 'Open Sans', sans-serif;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> #function-menu {<!-- [et_pb_line_break_holder] --> position: absolute;<!-- [et_pb_line_break_holder] --> z-index: 1;<!-- [et_pb_line_break_holder] --> top: 10px;<!-- [et_pb_line_break_holder] --> right: 140px;<!-- [et_pb_line_break_holder] --> width: 140px;<!-- [et_pb_line_break_holder] --> font-family: 'Open Sans', sans-serif;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .dropbtn {<!-- [et_pb_line_break_holder] --> width: 100%;<!-- [et_pb_line_break_holder] --> position: relative;<!-- [et_pb_line_break_holder] --> z-index: 2;<!-- [et_pb_line_break_holder] --> background-color: #31b7bc; /*AIT colors*/;<!-- [et_pb_line_break_holder] --> color: white;<!-- [et_pb_line_break_holder] --> padding: 16px;<!-- [et_pb_line_break_holder] --> font-size: 16px;<!-- [et_pb_line_break_holder] --> border: none;<!-- [et_pb_line_break_holder] --> cursor: pointer;<!-- [et_pb_line_break_holder] --> outline: none;<!-- [et_pb_line_break_holder] --> border-radius: 4px;<!-- [et_pb_line_break_holder] --> box-shadow: 0px 0px 2px 0px rgba(0,0,0,0.5);<!-- [et_pb_line_break_holder] --> font-weight: 500;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .dropbtn:hover, .dropbtn:focus {<!-- [et_pb_line_break_holder] --> background-color: #22a1a1;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .dropdown-content {<!-- [et_pb_line_break_holder] --> border-radius: 5px;<!-- [et_pb_line_break_holder] --> text-align: left;<!-- [et_pb_line_break_holder] --> display: none;<!-- [et_pb_line_break_holder] --> position: absolute;<!-- [et_pb_line_break_holder] --> top: 55px;<!-- [et_pb_line_break_holder] --> background-color: #ffffff;<!-- [et_pb_line_break_holder] --> width: 100%;<!-- [et_pb_line_break_holder] --> overflow: auto;<!-- [et_pb_line_break_holder] --> box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.4);<!-- [et_pb_line_break_holder] --> z-index: 1;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .dropdown-content a {<!-- [et_pb_line_break_holder] --> color: black;<!-- [et_pb_line_break_holder] --> padding: 12px 16px;<!-- [et_pb_line_break_holder] --> text-decoration: none;<!-- [et_pb_line_break_holder] --> display: block;<!-- [et_pb_line_break_holder] --> border-top: 1px solid #ddd;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .dropdown-content a.Off {<!-- [et_pb_line_break_holder] --> color: #6b6b6b;<!-- [et_pb_line_break_holder] --> background: #f9f9f9;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .dropdown-content a:hover {background-color: rgb(240, 240, 240);}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> .show {display: block;} <!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> /*-----CSS style for the element info popup widget-----*/<!-- [et_pb_line_break_holder] --> dd {<!-- [et_pb_line_break_holder] --> margin-left: 0;<!-- [et_pb_line_break_holder] --> margin-bottom: 8px;<!-- [et_pb_line_break_holder] --> font-weight: bold;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> dt {<!-- [et_pb_line_break_holder] --> color: #31b7bc; /*AIT colors*/<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> dl {<!-- [et_pb_line_break_holder] --> margin-bottom: 0;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip{<!-- [et_pb_line_break_holder] --> border-top-color: #31b7bc; /*AIT colors*/<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .mapboxgl-popup-content{<!-- [et_pb_line_break_holder] --> font-size: 14px;<!-- [et_pb_line_break_holder] --> color: white;<!-- [et_pb_line_break_holder] --> background-color: rgba(0, 0, 0, 0.8);<!-- [et_pb_line_break_holder] --> box-shadow: 0 0 0px 2px #31b7bc; /*AIT colors*/<!-- [et_pb_line_break_holder] --> min-width: 120px;<!-- [et_pb_line_break_holder] --> max-width: 300px;<!-- [et_pb_line_break_holder] --> max-height: 170px;<!-- [et_pb_line_break_holder] --> overflow-y: auto;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .mapboxgl-popup-close-button{<!-- [et_pb_line_break_holder] --> color: white;<!-- [et_pb_line_break_holder] --> font-size: 20px;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> /*-----CSS style for the map scale widget-----*/<!-- [et_pb_line_break_holder] --> .mapboxgl-ctrl-scale {<!-- [et_pb_line_break_holder] --> background-color: rgba(0, 0, 0, 0.75);<!-- [et_pb_line_break_holder] --> font-size: 12px;<!-- [et_pb_line_break_holder] --> border-width: medium 2px 3px;<!-- [et_pb_line_break_holder] --> border-style: none none solid;<!-- [et_pb_line_break_holder] --> border-color: #31b7bc; /*AIT colors*/<!-- [et_pb_line_break_holder] --> padding: 0 5px;<!-- [et_pb_line_break_holder] --> color: white;<!-- [et_pb_line_break_holder] --> box-sizing: border-box;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> /*-----CSS style for copyright-----*/<!-- [et_pb_line_break_holder] --> #copyright {<!-- [et_pb_line_break_holder] --> font-size: 9px;<!-- [et_pb_line_break_holder] --> color:white;<!-- [et_pb_line_break_holder] --> text-align: center;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> #copyright a {<!-- [et_pb_line_break_holder] --> color:#31b7bc; /*AIT colors*/<!-- [et_pb_line_break_holder] --> text-decoration: none;<!-- [et_pb_line_break_holder] --> font-weight: 1000;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> </style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> <div id='map' style='min-height: 500px; min-width: 460px;'> <!-- MapBox container --><!-- [et_pb_line_break_holder] --> <nav id="layer-menu"><!-- [et_pb_line_break_holder] --> <button onclick="dropdownToggle('layerDropdown')" class="dropbtn"><!-- [et_pb_line_break_holder] --> Select scenario</button><!-- [et_pb_line_break_holder] --> <div id="layerDropdown" class="dropdown-content"></div><!-- [et_pb_line_break_holder] --> <div id = "copyright">created at <a target="_blank" <!-- [et_pb_line_break_holder] --> href="https://cities.ait.ac.at/site/">AIT</a><!-- [et_pb_line_break_holder] --> by Ondrej Vesely,  2018</div><!-- [et_pb_line_break_holder] --> </nav><!-- [et_pb_line_break_holder] --> <nav id="camera-menu"><!-- [et_pb_line_break_holder] --> <button onclick="dropdownToggle('cameraDropdown')" class="dropbtn"><!-- [et_pb_line_break_holder] --> Views</button><!-- [et_pb_line_break_holder] --> <div id="cameraDropdown" class="dropdown-content"></div><!-- [et_pb_line_break_holder] --> </nav><!-- [et_pb_line_break_holder] --> <nav id="function-menu"><!-- [et_pb_line_break_holder] --> <button onclick="dropdownToggle('functionDropdown')" class="dropbtn"><!-- [et_pb_line_break_holder] --> Functions</button><!-- [et_pb_line_break_holder] --> <div id="functionDropdown" class="dropdown-content"></div><!-- [et_pb_line_break_holder] --> </nav><!-- [et_pb_line_break_holder] --> </div><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> <script><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Load Map via Mapbox API<!-- [et_pb_line_break_holder] --> mapboxgl.accessToken = 'pk.eyJ1Ijoib25kcmVqLXZlc2VseSIsImEiOiJjamlhOWo3cnkwMnY3M3ZwZjU5bm54c3BsIn0.69pwP4aK4CmFBlpU8I4giw';<!-- [et_pb_line_break_holder] --> // dont forget to change this accessToken to you own if you use this code<!-- [et_pb_line_break_holder] --> var map = new mapboxgl.Map({<!-- [et_pb_line_break_holder] --> container: 'map',<!-- [et_pb_line_break_holder] --> style: 'mapbox://styles/ondrej-vesely/cjjsritez0dx42ro0vz8l2ks4'<!-- [et_pb_line_break_holder] --> });<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Camera limits<!-- [et_pb_line_break_holder] --> map.setMaxZoom(17);<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Add navigation widget<!-- [et_pb_line_break_holder] --> var nav = new mapboxgl.NavigationControl();<!-- [et_pb_line_break_holder] --> map.addControl(nav,'top-right');<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Add fullscreen toggle button widget<!-- [et_pb_line_break_holder] --> var full = new mapboxgl.FullscreenControl();<!-- [et_pb_line_break_holder] --> map.addControl(full, 'top-right')<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Add map scale widget<!-- [et_pb_line_break_holder] --> var scale = new mapboxgl.ScaleControl({<!-- [et_pb_line_break_holder] --> maxWidth: 250,<!-- [et_pb_line_break_holder] --> unit: 'metric'<!-- [et_pb_line_break_holder] --> });<!-- [et_pb_line_break_holder] --> map.addControl(scale, 'bottom-right');<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // On start wait till map loads,<!-- [et_pb_line_break_holder] --> map.on('load', function() {<!-- [et_pb_line_break_holder] --> // move camera a bit,<!-- [et_pb_line_break_holder] --> map.flyTo({center: [103.84, 1.2680], zoom: 13.8, speed: 0.1, bearing: 4})<!-- [et_pb_line_break_holder] --> // and open welcome popup<!-- [et_pb_line_break_holder] --> helpPopup()<!-- [et_pb_line_break_holder] --> });<!-- [et_pb_line_break_holder] --> <!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // --- The interesting stuff starts here ----<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Dropdowns<!-- [et_pb_line_break_holder] --> // When the user clicks on the button, <!-- [et_pb_line_break_holder] --> // toggle between hiding and showing the dropdown content<!-- [et_pb_line_break_holder] --> function dropdownToggle(id) {<!-- [et_pb_line_break_holder] --> document.getElementById(id).classList.toggle("show");<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> // Layers which include multiple variants and should filtered based on displayed scenario<!-- [et_pb_line_break_holder] --> var scenLayers = [<!-- [et_pb_line_break_holder] --> 'land', 'land2', 'buildings', 'streets', 'trees', 'bridges', 'floors', 'syntax',<!-- [et_pb_line_break_holder] --> 'solar'<!-- [et_pb_line_break_holder] --> ]<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // List of variants included in the data<!-- [et_pb_line_break_holder] --> var scenNames = ['scen1', 'scen3', 'scen5']<!-- [et_pb_line_break_holder] --> var scenNiceNames = ['Green Loop City', 'Garden City', 'Oceanfront']<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Add scenario names to dropdown to chenge scenario filter on click<!-- [et_pb_line_break_holder] --> for (var i = 0; i < scenNames.length; i++) {<!-- [et_pb_line_break_holder] --> var id = scenNames[i];<!-- [et_pb_line_break_holder] --> var name = scenNiceNames[i];<!-- [et_pb_line_break_holder] --> var link = document.createElement('a');<!-- [et_pb_line_break_holder] --> link.href = 'javascript:changeScen("' + id + '")';<!-- [et_pb_line_break_holder] --> link.textContent = name;<!-- [et_pb_line_break_holder] --> var $layerDropdown = document.getElementById('layerDropdown');<!-- [et_pb_line_break_holder] --> $layerDropdown.appendChild(link);<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> // Scenario change - Loops trough list of scenario layers,<!-- [et_pb_line_break_holder] --> // sets variant filter to given scenario name<!-- [et_pb_line_break_holder] --> function changeScen(id) {<!-- [et_pb_line_break_holder] --> for (var i = 0; i < scenLayers.length; i++) {<!-- [et_pb_line_break_holder] --> var layer = scenLayers[i];<!-- [et_pb_line_break_holder] --> filter = map.getFilter(layer); // gets current filter settings<!-- [et_pb_line_break_holder] --> for (var j = 0; j < filter.length; j++) {<!-- [et_pb_line_break_holder] --> if (filter[j][1] == "var") { // Key under which you specify variants<!-- [et_pb_line_break_holder] --> filter[j][2] = id; // change the Value to "id" (scenario name)<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> map.setFilter(layer, filter);<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // For the cameras you want to save, put its position as CameraOptions here<!-- [et_pb_line_break_holder] --> var cameras = [<!-- [et_pb_line_break_holder] --> {center: [103.836607, 1.272156], zoom: 17, bearing: 136, pitch: 60}, <!-- [et_pb_line_break_holder] --> {center: [103.846564, 1.272998], zoom: 16, bearing: -180, pitch: 60}, <!-- [et_pb_line_break_holder] --> {center: [103.832839, 1.259721], zoom: 15, bearing: 0, pitch: 0}];<!-- [et_pb_line_break_holder] --> var cameraNames = ['Station', 'CBD', 'Island']<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Add views to camera dropdown to switch cameras on click<!-- [et_pb_line_break_holder] --> for (var i = 0; i < cameras.length; i++) {<!-- [et_pb_line_break_holder] --> var name = cameraNames[i]<!-- [et_pb_line_break_holder] --> var link = document.createElement('a');<!-- [et_pb_line_break_holder] --> link.href = 'javascript:changeCamera(cameras[' + i + '])';<!-- [et_pb_line_break_holder] --> link.textContent = name;<!-- [et_pb_line_break_holder] --> var $cameraDropdown = document.getElementById('cameraDropdown');<!-- [et_pb_line_break_holder] --> $cameraDropdown.appendChild(link);<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> // View switching<!-- [et_pb_line_break_holder] --> function changeCamera(cameraOptions){<!-- [et_pb_line_break_holder] --> // You can set camera fly speed here<!-- [et_pb_line_break_holder] --> cameraOptions['speed'] = '0.5';<!-- [et_pb_line_break_holder] --> map.flyTo(cameraOptions);<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> <!-- [et_pb_line_break_holder] --> // List of additional functions you want to include as tools<!-- [et_pb_line_break_holder] --> var functions = [<!-- [et_pb_line_break_holder] --> 'toggle3d()', 'toggleFloors()', 'toggleSun()',<!-- [et_pb_line_break_holder] --> 'toggleSyntax()', 'issues()', 'helpPopup()'<!-- [et_pb_line_break_holder] --> ]<!-- [et_pb_line_break_holder] --> var functionNames = [<!-- [et_pb_line_break_holder] --> '☑  3D buildings', '☐  Higher LOD', '☐  Shadow study',<!-- [et_pb_line_break_holder] --> '☐  SpaceSyntax', '☐  Comments', 'Need Help?'<!-- [et_pb_line_break_holder] --> ]<!-- [et_pb_line_break_holder] --> var startToggle = ['On', 'Off', 'Off', 'Off', 'Off', 'On']<!-- [et_pb_line_break_holder] --> // Add functions to dropdown to switch activate on click<!-- [et_pb_line_break_holder] --> for (var i = 0; i < functions.length; i++) {<!-- [et_pb_line_break_holder] --> var id = functions[i];<!-- [et_pb_line_break_holder] --> var name = functionNames[i];<!-- [et_pb_line_break_holder] --> var toggle = startToggle[i]<!-- [et_pb_line_break_holder] --> var link = document.createElement('a');<!-- [et_pb_line_break_holder] --> link.href = 'javascript:' + id<!-- [et_pb_line_break_holder] --> link.textContent = name;<!-- [et_pb_line_break_holder] --> link.id = id<!-- [et_pb_line_break_holder] --> link.classList = toggle<!-- [et_pb_line_break_holder] --> var $layerDropdown = document.getElementById('functionDropdown');<!-- [et_pb_line_break_holder] --> $layerDropdown.appendChild(link);<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> <!-- [et_pb_line_break_holder] --> // 3D buildings toggle<!-- [et_pb_line_break_holder] --> var extrusionHeight = []<!-- [et_pb_line_break_holder] --> map.on("load", function(){<!-- [et_pb_line_break_holder] --> extrusionHeight = map.getPaintProperty("buildings", "fill-extrusion-height")<!-- [et_pb_line_break_holder] --> })<!-- [et_pb_line_break_holder] --> function toggle3d(){<!-- [et_pb_line_break_holder] --> if(document.getElementById("toggle3d()").classList == "On") {<!-- [et_pb_line_break_holder] --> map.setPaintProperty("buildings", "fill-extrusion-height", 8)<!-- [et_pb_line_break_holder] --> map.setPaintProperty('floors', "fill-extrusion-opacity", 0);<!-- [et_pb_line_break_holder] --> document.getElementById("toggle3d()").textContent = "☐  3D buildings"<!-- [et_pb_line_break_holder] --> document.getElementById("toggle3d()").classList = "Off"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> else if(document.getElementById("toggle3d()").classList == "Off") {<!-- [et_pb_line_break_holder] --> map.setPaintProperty("buildings", "fill-extrusion-height", extrusionHeight)<!-- [et_pb_line_break_holder] --> map.setPaintProperty('floors', "fill-extrusion-opacity", 1);<!-- [et_pb_line_break_holder] --> document.getElementById("toggle3d()").textContent = "☑  3D buildings"<!-- [et_pb_line_break_holder] --> document.getElementById("toggle3d()").classList = "On"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Higher LOD -- Floors toggle<!-- [et_pb_line_break_holder] --> function toggleFloors() {<!-- [et_pb_line_break_holder] --> if(document.getElementById("toggleFloors()").classList == "Off") {<!-- [et_pb_line_break_holder] --> // First check if map isnt zoomed out too far<!-- [et_pb_line_break_holder] --> // If map is far, zoom slowly to proper zoom level<!-- [et_pb_line_break_holder] --> if(map.getZoom() < 15) {<!-- [et_pb_line_break_holder] --> map.flyTo({zoom: 15, speed: 0.5})<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> else {<!-- [et_pb_line_break_holder] --> map.flyTo({zoom: map.getZoom()+0.0001})<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> map.once('zoomend', function() {<!-- [et_pb_line_break_holder] --> map.setMinZoom(15)<!-- [et_pb_line_break_holder] --> map.setPaintProperty("buildings", "fill-extrusion-opacity", 0)<!-- [et_pb_line_break_holder] --> map.setLayoutProperty('floors', 'visibility', 'visible');<!-- [et_pb_line_break_holder] --> document.getElementById("toggleFloors()").textContent = "☑  Higher LOD"<!-- [et_pb_line_break_holder] --> document.getElementById("toggleFloors()").classList = "On"<!-- [et_pb_line_break_holder] --> })<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> else if(document.getElementById("toggleFloors()").classList == "On") {<!-- [et_pb_line_break_holder] --> map.setLayoutProperty('floors', 'visibility', 'none');<!-- [et_pb_line_break_holder] --> map.setPaintProperty("buildings", "fill-extrusion-opacity", 1)<!-- [et_pb_line_break_holder] --> document.getElementById("toggleFloors()").textContent = "☐  Higher LOD"<!-- [et_pb_line_break_holder] --> document.getElementById("toggleFloors()").classList = "Off"<!-- [et_pb_line_break_holder] --> map.setMinZoom(0)<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> // Toggle Sun hours / Shadowstudy<!-- [et_pb_line_break_holder] --> function toggleSun(){<!-- [et_pb_line_break_holder] --> if(document.getElementById("toggleSun()").classList == "Off") {<!-- [et_pb_line_break_holder] --> map.setLayoutProperty('solar', "visibility", "visible");<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSun()").textContent = "☑  Shadow study"<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSun()").classList = "On"<!-- [et_pb_line_break_holder] --> <!-- [et_pb_line_break_holder] --> var popup = new mapboxgl.Popup({closeButton: false, closeOnClick: false})<!-- [et_pb_line_break_holder] --> map.on('mousemove', 'solar', function(e) {<!-- [et_pb_line_break_holder] --> map.getCanvas().style.cursor = 'help';<!-- [et_pb_line_break_holder] --> popup.remove(map)<!-- [et_pb_line_break_holder] --> var features = map.queryRenderedFeatures(e.point, {layers: ["solar"]});<!-- [et_pb_line_break_holder] --> var face = features[0];<!-- [et_pb_line_break_holder] --> var hours = face.properties.hours<!-- [et_pb_line_break_holder] --> popup.setLngLat(e.lngLat)<!-- [et_pb_line_break_holder] --> .setHTML(<!-- [et_pb_line_break_holder] --> '<dd>' + hours + ' hours</dd>' +<!-- [et_pb_line_break_holder] --> '<dt> of sunlight <br>on 1st of August.</dt>'<!-- [et_pb_line_break_holder] --> )<!-- [et_pb_line_break_holder] --> .addTo(map);<!-- [et_pb_line_break_holder] --> })<!-- [et_pb_line_break_holder] --> map.on('mouseleave', 'solar', function(){<!-- [et_pb_line_break_holder] --> map.getCanvas().style.cursor = '';<!-- [et_pb_line_break_holder] --> popup.remove(map);<!-- [et_pb_line_break_holder] --> })<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> else if(document.getElementById("toggleSun()").classList == "On") {<!-- [et_pb_line_break_holder] --> map.setLayoutProperty('solar', "visibility", "none");<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSun()").textContent = "☐  Shadow study"<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSun()").classList = "Off"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Toggle SpaceSyntax<!-- [et_pb_line_break_holder] --> function toggleSyntax(){<!-- [et_pb_line_break_holder] --> if(document.getElementById("toggleSyntax()").classList == "Off") {<!-- [et_pb_line_break_holder] --> map.setPaintProperty('syntax', "line-opacity", 1);<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSyntax()").textContent = "☑  SpaceSyntax"<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSyntax()").classList = "On"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> else if(document.getElementById("toggleSyntax()").classList == "On") {<!-- [et_pb_line_break_holder] --> map.setPaintProperty('syntax', "line-opacity", 0);<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSyntax()").textContent = "☐  SpaceSyntax"<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSyntax()").classList = "Off"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Feedback toggle<!-- [et_pb_line_break_holder] --> // Switch between icons visible and hidden<!-- [et_pb_line_break_holder] --> function issues() {<!-- [et_pb_line_break_holder] --> if(document.getElementById("issues()").classList == "Off") {<!-- [et_pb_line_break_holder] --> map.setLayoutProperty("wtp-comments", 'visibility', 'visible');<!-- [et_pb_line_break_holder] --> document.getElementById("issues()").textContent = "☑  Comments"<!-- [et_pb_line_break_holder] --> document.getElementById("issues()").classList = "On"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> else if(document.getElementById("issues()").classList == "On") {<!-- [et_pb_line_break_holder] --> map.setLayoutProperty("wtp-comments", 'visibility', 'none');<!-- [et_pb_line_break_holder] --> document.getElementById("issues()").textContent = "☐  Comments"<!-- [et_pb_line_break_holder] --> document.getElementById("issues()").classList = "Off"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> // on hover open popup with text info<!-- [et_pb_line_break_holder] --> issuePopup = new mapboxgl.Popup({closeButton: false, closeOnClick: false})<!-- [et_pb_line_break_holder] --> map.on('mouseenter', 'wtp-comments', function(e) {<!-- [et_pb_line_break_holder] --> map.getCanvas().style.cursor = 'pointer';<!-- [et_pb_line_break_holder] --> var coordinates = e.features[0].geometry.coordinates.slice();<!-- [et_pb_line_break_holder] --> var text = e.features[0].properties.text;<!-- [et_pb_line_break_holder] --> var author = e.features[0].properties.author;<!-- [et_pb_line_break_holder] --> issuePopup.setLngLat(coordinates)<!-- [et_pb_line_break_holder] --> .setHTML('<dt>' + text + '</dt>' +<!-- [et_pb_line_break_holder] --> '<br><dd>' + author + '</dd>'<!-- [et_pb_line_break_holder] --> )<!-- [et_pb_line_break_holder] --> .addTo(map);<!-- [et_pb_line_break_holder] --> })<!-- [et_pb_line_break_holder] --> // close it on hover end<!-- [et_pb_line_break_holder] --> map.on('mouseleave', 'wtp-comments', function() {<!-- [et_pb_line_break_holder] --> map.getCanvas().style.cursor = '';<!-- [et_pb_line_break_holder] --> issuePopup.remove();<!-- [et_pb_line_break_holder] --> })<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // +++ Other useful functions<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Help popup with controls info<!-- [et_pb_line_break_holder] --> function helpPopup() {<!-- [et_pb_line_break_holder] --> window.popup = new mapboxgl.Popup()<!-- [et_pb_line_break_holder] --> .setLngLat(map.getCenter())<!-- [et_pb_line_break_holder] --> .setHTML( //OLD IE COMPATABLE MUTLILINE STRING<!-- [et_pb_line_break_holder] --> '<dd>How can you explore the model?</dd>' +<!-- [et_pb_line_break_holder] --> '<dt>Click on "Select scenario" to choose between different variants' +<!-- [et_pb_line_break_holder] --> ' or click on buildings to display more information about them.</dt>' +<!-- [et_pb_line_break_holder] --> '<dt><br>To control the camera press Control + Left Mouse Button or use' +<!-- [et_pb_line_break_holder] --> ' one of the preset positions with "Views" menu.</dt>' +<!-- [et_pb_line_break_holder] --> '<dt><br>In the "Functions" menu you can hide the 3D geometry' +<!-- [et_pb_line_break_holder] --> ' and change the Level of Detail or show a demo of feedback system.</dt>'<!-- [et_pb_line_break_holder] --> )<!-- [et_pb_line_break_holder] --> .addTo(map);<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Layer with additional data popup on click<!-- [et_pb_line_break_holder] --> activeLayer = 'buildings'<!-- [et_pb_line_break_holder] --> // change the cursor when hovering over this layer<!-- [et_pb_line_break_holder] --> map.on('mouseenter', activeLayer, function(event) {<!-- [et_pb_line_break_holder] --> map.getCanvas().style.cursor = 'help';<!-- [et_pb_line_break_holder] --> }); <!-- [et_pb_line_break_holder] --> map.on('mouseleave', activeLayer, function() {<!-- [et_pb_line_break_holder] --> map.getCanvas().style.cursor = '';<!-- [et_pb_line_break_holder] --> });<!-- [et_pb_line_break_holder] --> // Open popup with GeoJson properties on click<!-- [et_pb_line_break_holder] --> map.on('click', function(event) {<!-- [et_pb_line_break_holder] --> var features = map.queryRenderedFeatures(event.point, {layers: [activeLayer]});<!-- [et_pb_line_break_holder] --> var building = features[0];<!-- [et_pb_line_break_holder] --> <!-- [et_pb_line_break_holder] --> // Keys you want to include<!-- [et_pb_line_break_holder] --> if (features.length) {<!-- [et_pb_line_break_holder] --> var landUse = building.properties.function <!-- [et_pb_line_break_holder] --> '–';<!-- [et_pb_line_break_holder] --> var height = Math.round(building.properties.height) <!-- [et_pb_line_break_holder] --> '–';<!-- [et_pb_line_break_holder] --> var gfa = Math.round(building.properties.GFA) <!-- [et_pb_line_break_holder] --> '–';<!-- [et_pb_line_break_holder] --> var id = building.properties.build_ID <!-- [et_pb_line_break_holder] --> '–';<!-- [et_pb_line_break_holder] --> <!-- [et_pb_line_break_holder] --> // HTML content of the popup<!-- [et_pb_line_break_holder] --> window.popup = new mapboxgl.Popup()<!-- [et_pb_line_break_holder] --> .setLngLat(event.lngLat)<!-- [et_pb_line_break_holder] --> .setHTML( <!-- [et_pb_line_break_holder] --> '<dl>' +<!-- [et_pb_line_break_holder] --> // '<dt>Land Use</dt>' +<!-- [et_pb_line_break_holder] --> // '<dd>' + landUse + '</dd>' +<!-- [et_pb_line_break_holder] --> '<dt>Building Height</dt>' +<!-- [et_pb_line_break_holder] --> '<dd>' + height + ' m' + '</dd>' +<!-- [et_pb_line_break_holder] --> '<dt>GFA</dt>' +<!-- [et_pb_line_break_holder] --> '<dd>' + gfa + ' sqm' + '</dd>' +<!-- [et_pb_line_break_holder] --> '<dt>ID#</dt>' +<!-- [et_pb_line_break_holder] --> '<dd>' + id + '</dd>' +<!-- [et_pb_line_break_holder] --> '</dl>') //OLD IE COMPATABLE MUTLILINE STRING FORMAT<!-- [et_pb_line_break_holder] --> .addTo(map);<!-- [et_pb_line_break_holder] --> };<!-- [et_pb_line_break_holder] --> });<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> </script>

Acknowledgement The project shown in the example above is a result of interdisciplinary international research project done by the students at the Bauhaus-Universität Weimar (BUW).  We are also grateful to the Singapore-ETH Centre teams Multi-Scale Energy Systems for Low Carbon Cities, Engaging Mobility, and Big Data-Informed Urban Design and Governance for contributing their knowledge, experience and time to the design studio.

Public Transport Isochronal Map

Public Transport Isochronal Map

This page shows a technical demonstration of a tool for visualizing pulbic transport access times as an isochronic map. The tool was developed in the Smart Spatial Planning Systems group at the Austrian Institute of Technology (AIT). The tool is implemented as Grasshopper definition and can be controlled with a simplified user interface from Rhino3D.

The tool makes use of Grasshopper extension Spiderweb 4.2 by Richard Schaffranek.

Research Team: Ondřej Veselý, Reinhard Koenig

The module makes use of existing data on public transport routes, which is openly available from Wiener Linien. However user can easily modify the dataset using CAD-like interface to explore new scenarios, such as construction of additional routes and more frequent or faster connections.

The resulting access time can be mapped to all buildings or streets, or displayed as isochronic curves – an isochrone of time t is the surface at equal time distance from the starting points.

 

The files used in this example are included for internal use by our research partners in protected archive below.

Please enter a password to see the content.


Wrong password, please try again
Parametric assistance for complex urban planning processes

Parametric assistance for complex urban planning processes

In the following we present examples of new parametric urban design techniques that are applied for large-scale urban developments in order to achieve three goals: inclusiveness and transparency; automatization and speed; flexibility and adaptability.

The modular frameworks described below break down the linear sequence of the design process and give opportunities for changes at any stage during an urban planning process without affecting all the decisions made afterwards. Three presented case-studies are showing that parametric interventions can be made in several phases of the project development that include analysis, design generation and re-evaluation loops.

Research Team:   Kateryna Konieva, Iuliia Osintseva, Ondřej Veselý, Abdulmalik Abdulmawla, Katja Knecht, Dr. Reinhard Koenig, Dr. Sven Schneider

SynCity – Connect the Hubs

Burcu Cimenoglu, Christoph Hanisch, Kateryna Konieva

In response to increasing shortage of resources, infrastructure, housing and job offers in due to rapid urbanization overpopulated Ethiopian cities, there is a proposal to disseminate migrating population to large amount (up to 2000 of new developments) of the so-called “10K towns”.

Generative parametric methods were used optimize and repeat multiple actions that are following similar principles at any site. The tool was eventually applied in three topographically diverse locations in the Ethiopia to test its adaptibility. Creation of the new city “skeleton” would always consist of the street network, main facilities distribution, land use and density schemes, and housing typologies. In most cases these modules would be used in similar sequence and consider the same number of conditions for their design. General input data was defined during the phase of analysis: as locations given with a design brief had no built-up surroundings, only terrain geometry and existing main road were used.

SynCity 2020 – Habeshaville

Iuliia Osintseva, Ondrej Vesely, Mahmoud A’dam

The rapid developement of masterplans for hundreds to thousands of new Ethiopian towns in the short timeframe is beyond the capacities of traditional urban planning frameworks. This project is a result of continued collaboration between Bauhaus-Universität Weimar and EiABC, focused on developement of groundbreaking urban planning tools to help with this process.

 

In this aproach, an ideal site is chosen from the possible locations by applying various critiria, such as connection to the existing infrastructure or suitable terrain. After that an optimized street network is proposed, based on the terrain morphology to prevent water errosion and avoid steep streets. In towns that are proposed, four housing typologies are used, ranging from the most “urban” mixed use multistorey houses to simpler “farmer” housing with direct access to the agricultural land on the outskirts of the town. The public facitilites and other important buildings are distributed using a set of criteria and rules for their placement, based on our experience from previous field-trips and participative studies we lead in contemporary rural settlements all across Ethiopia.

Tanjong Pagar Waterfront

Kateryna Konieva, Iuliia Osintseva, Ondrej Vesely

Singapore’s Tanjong Pagar container port, an industrial zone of 400 ha, is planned to be relocated to other part of the island, releasing the land for new mixed-use development located in the wider city centre.

In cooperation with ETH Future Cities Lab, parametric generetive toolbox was developed, that could help designers and urban planners explore possible solutions.

 

 Similar aproach was chosen for the project: to start from the larger scale point of view – by digitally sketching street grids and land use plans and then move towards more detailed aspects such as road setbacks or building morphology. Different rules are set up to handle e.g. building height limits or street widths.

Compared to the projects for Ethiopian rural towns, the parametric methods were in this case used to genarate nd compare mutliple solutions for one very specific context, instead of adapting one solution to multiple locations. The goal was to create several scenarios based on different concepts for how to aproach the site and provide comparative measures on their performance.

Explore the project via our interactive map application.

<style><!-- [et_pb_line_break_holder] --> /*-----CSS style for the layer and view selection widget-----*/<!-- [et_pb_line_break_holder] --> #layer-menu {<!-- [et_pb_line_break_holder] --> position: absolute;<!-- [et_pb_line_break_holder] --> z-index: 1;<!-- [et_pb_line_break_holder] --> top: 10px;<!-- [et_pb_line_break_holder] --> left: 10px;<!-- [et_pb_line_break_holder] --> width: 160px;<!-- [et_pb_line_break_holder] --> font-family: 'Open Sans', sans-serif;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> #camera-menu {<!-- [et_pb_line_break_holder] --> position: absolute;<!-- [et_pb_line_break_holder] --> z-index: 1;<!-- [et_pb_line_break_holder] --> top: 10px;<!-- [et_pb_line_break_holder] --> right: 50px;<!-- [et_pb_line_break_holder] --> width: 80px;<!-- [et_pb_line_break_holder] --> font-family: 'Open Sans', sans-serif;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> #function-menu {<!-- [et_pb_line_break_holder] --> position: absolute;<!-- [et_pb_line_break_holder] --> z-index: 1;<!-- [et_pb_line_break_holder] --> top: 10px;<!-- [et_pb_line_break_holder] --> right: 140px;<!-- [et_pb_line_break_holder] --> width: 140px;<!-- [et_pb_line_break_holder] --> font-family: 'Open Sans', sans-serif;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .dropbtn {<!-- [et_pb_line_break_holder] --> width: 100%;<!-- [et_pb_line_break_holder] --> position: relative;<!-- [et_pb_line_break_holder] --> z-index: 2;<!-- [et_pb_line_break_holder] --> background-color: #31b7bc; /*AIT colors*/;<!-- [et_pb_line_break_holder] --> color: white;<!-- [et_pb_line_break_holder] --> padding: 16px;<!-- [et_pb_line_break_holder] --> font-size: 16px;<!-- [et_pb_line_break_holder] --> border: none;<!-- [et_pb_line_break_holder] --> cursor: pointer;<!-- [et_pb_line_break_holder] --> outline: none;<!-- [et_pb_line_break_holder] --> border-radius: 4px;<!-- [et_pb_line_break_holder] --> box-shadow: 0px 0px 2px 0px rgba(0,0,0,0.5);<!-- [et_pb_line_break_holder] --> font-weight: 500;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .dropbtn:hover, .dropbtn:focus {<!-- [et_pb_line_break_holder] --> background-color: #22a1a1;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .dropdown-content {<!-- [et_pb_line_break_holder] --> border-radius: 5px;<!-- [et_pb_line_break_holder] --> text-align: left;<!-- [et_pb_line_break_holder] --> display: none;<!-- [et_pb_line_break_holder] --> position: absolute;<!-- [et_pb_line_break_holder] --> top: 55px;<!-- [et_pb_line_break_holder] --> background-color: #ffffff;<!-- [et_pb_line_break_holder] --> width: 100%;<!-- [et_pb_line_break_holder] --> overflow: auto;<!-- [et_pb_line_break_holder] --> box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.4);<!-- [et_pb_line_break_holder] --> z-index: 1;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .dropdown-content a {<!-- [et_pb_line_break_holder] --> color: black;<!-- [et_pb_line_break_holder] --> padding: 12px 16px;<!-- [et_pb_line_break_holder] --> text-decoration: none;<!-- [et_pb_line_break_holder] --> display: block;<!-- [et_pb_line_break_holder] --> border-top: 1px solid #ddd;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .dropdown-content a.Off {<!-- [et_pb_line_break_holder] --> color: #6b6b6b;<!-- [et_pb_line_break_holder] --> background: #f9f9f9;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .dropdown-content a:hover {background-color: rgb(240, 240, 240);}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> .show {display: block;} <!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> /*-----CSS style for the element info popup widget-----*/<!-- [et_pb_line_break_holder] --> dd {<!-- [et_pb_line_break_holder] --> margin-left: 0;<!-- [et_pb_line_break_holder] --> margin-bottom: 8px;<!-- [et_pb_line_break_holder] --> font-weight: bold;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> dt {<!-- [et_pb_line_break_holder] --> color: #31b7bc; /*AIT colors*/<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> dl {<!-- [et_pb_line_break_holder] --> margin-bottom: 0;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip{<!-- [et_pb_line_break_holder] --> border-top-color: #31b7bc; /*AIT colors*/<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .mapboxgl-popup-content{<!-- [et_pb_line_break_holder] --> font-size: 14px;<!-- [et_pb_line_break_holder] --> color: white;<!-- [et_pb_line_break_holder] --> background-color: rgba(0, 0, 0, 0.8);<!-- [et_pb_line_break_holder] --> box-shadow: 0 0 0px 2px #31b7bc; /*AIT colors*/<!-- [et_pb_line_break_holder] --> min-width: 120px;<!-- [et_pb_line_break_holder] --> max-width: 300px;<!-- [et_pb_line_break_holder] --> max-height: 170px;<!-- [et_pb_line_break_holder] --> overflow-y: auto;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> .mapboxgl-popup-close-button{<!-- [et_pb_line_break_holder] --> color: white;<!-- [et_pb_line_break_holder] --> font-size: 20px;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> /*-----CSS style for the map scale widget-----*/<!-- [et_pb_line_break_holder] --> .mapboxgl-ctrl-scale {<!-- [et_pb_line_break_holder] --> background-color: rgba(0, 0, 0, 0.75);<!-- [et_pb_line_break_holder] --> font-size: 12px;<!-- [et_pb_line_break_holder] --> border-width: medium 2px 3px;<!-- [et_pb_line_break_holder] --> border-style: none none solid;<!-- [et_pb_line_break_holder] --> border-color: #31b7bc; /*AIT colors*/<!-- [et_pb_line_break_holder] --> padding: 0 5px;<!-- [et_pb_line_break_holder] --> color: white;<!-- [et_pb_line_break_holder] --> box-sizing: border-box;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> /*-----CSS style for copyright-----*/<!-- [et_pb_line_break_holder] --> #copyright {<!-- [et_pb_line_break_holder] --> font-size: 9px;<!-- [et_pb_line_break_holder] --> color:white;<!-- [et_pb_line_break_holder] --> text-align: center;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> #copyright a {<!-- [et_pb_line_break_holder] --> color:#31b7bc; /*AIT colors*/<!-- [et_pb_line_break_holder] --> text-decoration: none;<!-- [et_pb_line_break_holder] --> font-weight: 1000;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> </style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> <div id='map' style='min-height: 500px; min-width: 460px;'> <!-- MapBox container --><!-- [et_pb_line_break_holder] --> <nav id="layer-menu"><!-- [et_pb_line_break_holder] --> <button onclick="dropdownToggle('layerDropdown')" class="dropbtn"><!-- [et_pb_line_break_holder] --> Select scenario</button><!-- [et_pb_line_break_holder] --> <div id="layerDropdown" class="dropdown-content"></div><!-- [et_pb_line_break_holder] --> <div id = "copyright">created at <a target="_blank" <!-- [et_pb_line_break_holder] --> href="https://cities.ait.ac.at/site/">AIT</a><!-- [et_pb_line_break_holder] --> by Ondrej Vesely,  2018</div><!-- [et_pb_line_break_holder] --> </nav><!-- [et_pb_line_break_holder] --> <nav id="camera-menu"><!-- [et_pb_line_break_holder] --> <button onclick="dropdownToggle('cameraDropdown')" class="dropbtn"><!-- [et_pb_line_break_holder] --> Views</button><!-- [et_pb_line_break_holder] --> <div id="cameraDropdown" class="dropdown-content"></div><!-- [et_pb_line_break_holder] --> </nav><!-- [et_pb_line_break_holder] --> <nav id="function-menu"><!-- [et_pb_line_break_holder] --> <button onclick="dropdownToggle('functionDropdown')" class="dropbtn"><!-- [et_pb_line_break_holder] --> Functions</button><!-- [et_pb_line_break_holder] --> <div id="functionDropdown" class="dropdown-content"></div><!-- [et_pb_line_break_holder] --> </nav><!-- [et_pb_line_break_holder] --> </div><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> <script><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Load Map via Mapbox API<!-- [et_pb_line_break_holder] --> mapboxgl.accessToken = 'pk.eyJ1Ijoib25kcmVqLXZlc2VseSIsImEiOiJjamlhOWo3cnkwMnY3M3ZwZjU5bm54c3BsIn0.69pwP4aK4CmFBlpU8I4giw';<!-- [et_pb_line_break_holder] --> var map = new mapboxgl.Map({<!-- [et_pb_line_break_holder] --> container: 'map',<!-- [et_pb_line_break_holder] --> style: 'mapbox://styles/ondrej-vesely/cjjsritez0dx42ro0vz8l2ks4'<!-- [et_pb_line_break_holder] --> });<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Camera limits<!-- [et_pb_line_break_holder] --> map.setMaxZoom(17);<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Add navigation widget<!-- [et_pb_line_break_holder] --> var nav = new mapboxgl.NavigationControl();<!-- [et_pb_line_break_holder] --> map.addControl(nav,'top-right');<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Add fullscreen toggle button widget<!-- [et_pb_line_break_holder] --> var full = new mapboxgl.FullscreenControl();<!-- [et_pb_line_break_holder] --> map.addControl(full, 'top-right')<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Add map scale widget<!-- [et_pb_line_break_holder] --> var scale = new mapboxgl.ScaleControl({<!-- [et_pb_line_break_holder] --> maxWidth: 250,<!-- [et_pb_line_break_holder] --> unit: 'metric'<!-- [et_pb_line_break_holder] --> });<!-- [et_pb_line_break_holder] --> map.addControl(scale, 'bottom-right');<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // On start wait till map loads,<!-- [et_pb_line_break_holder] --> map.on('load', function() {<!-- [et_pb_line_break_holder] --> // move camera a bit,<!-- [et_pb_line_break_holder] --> map.flyTo({center: [103.84, 1.2680], zoom: 13.8, speed: 0.1, bearing: 4})<!-- [et_pb_line_break_holder] --> // and open welcome popup<!-- [et_pb_line_break_holder] --> helpPopup()<!-- [et_pb_line_break_holder] --> });<!-- [et_pb_line_break_holder] --> <!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // --- The interesting stuff starts here ----<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Dropdowns<!-- [et_pb_line_break_holder] --> // When the user clicks on the button, <!-- [et_pb_line_break_holder] --> // toggle between hiding and showing the dropdown content<!-- [et_pb_line_break_holder] --> function dropdownToggle(id) {<!-- [et_pb_line_break_holder] --> document.getElementById(id).classList.toggle("show");<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> // List of layers which include multiple variants and should change between scenarios<!-- [et_pb_line_break_holder] --> var scenLayers = [<!-- [et_pb_line_break_holder] --> 'land', 'land2', 'buildings', 'streets', 'trees', 'bridges', 'floors', 'syntax',<!-- [et_pb_line_break_holder] --> 'solar'<!-- [et_pb_line_break_holder] --> ]<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // List of variants included in the layers<!-- [et_pb_line_break_holder] --> var scenNames = ['scen1', 'scen3', 'scen5']<!-- [et_pb_line_break_holder] --> var scenNiceNames = ['Green Loop City', 'Garden City', 'Oceanfront']<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Add layer names to dropdown to switch layers on click<!-- [et_pb_line_break_holder] --> for (var i = 0; i < scenNames.length; i++) {<!-- [et_pb_line_break_holder] --> var id = scenNames[i];<!-- [et_pb_line_break_holder] --> var name = scenNiceNames[i];<!-- [et_pb_line_break_holder] --> var link = document.createElement('a');<!-- [et_pb_line_break_holder] --> link.href = 'javascript:changeScen("' + id + '")';<!-- [et_pb_line_break_holder] --> link.textContent = name;<!-- [et_pb_line_break_holder] --> var $layerDropdown = document.getElementById('layerDropdown');<!-- [et_pb_line_break_holder] --> $layerDropdown.appendChild(link);<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> // Scenario change - Loops trough list of scenario layers,<!-- [et_pb_line_break_holder] --> // sets variant filter to given scenario name<!-- [et_pb_line_break_holder] --> function changeScen(id) {<!-- [et_pb_line_break_holder] --> for (var i = 0; i < scenLayers.length; i++) {<!-- [et_pb_line_break_holder] --> var layer = scenLayers[i];<!-- [et_pb_line_break_holder] --> filter = map.getFilter(layer);<!-- [et_pb_line_break_holder] --> for (var j = 0; j < filter.length; j++) {<!-- [et_pb_line_break_holder] --> if (filter[j][1] == "var") {<!-- [et_pb_line_break_holder] --> filter[j][2] = id;<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> map.setFilter(layer, filter);<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // For the cameras you want to save, put its position as CameraOptions here<!-- [et_pb_line_break_holder] --> var cameras = [<!-- [et_pb_line_break_holder] --> {center: [103.836607, 1.272156], zoom: 17, bearing: 136, pitch: 60}, <!-- [et_pb_line_break_holder] --> {center: [103.846564, 1.272998], zoom: 16, bearing: -180, pitch: 60}, <!-- [et_pb_line_break_holder] --> {center: [103.832839, 1.259721], zoom: 15, bearing: 0, pitch: 0}];<!-- [et_pb_line_break_holder] --> var cameraNames = ['Station', 'CBD', 'Island']<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Add views to camera dropdown to switch cameras on click<!-- [et_pb_line_break_holder] --> for (var i = 0; i < cameras.length; i++) {<!-- [et_pb_line_break_holder] --> var name = cameraNames[i]<!-- [et_pb_line_break_holder] --> var link = document.createElement('a');<!-- [et_pb_line_break_holder] --> link.href = 'javascript:changeCamera(cameras[' + i + '])';<!-- [et_pb_line_break_holder] --> link.textContent = name;<!-- [et_pb_line_break_holder] --> var $cameraDropdown = document.getElementById('cameraDropdown');<!-- [et_pb_line_break_holder] --> $cameraDropdown.appendChild(link);<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> // View switching<!-- [et_pb_line_break_holder] --> function changeCamera(cameraOptions){<!-- [et_pb_line_break_holder] --> // You can set camera fly speed here<!-- [et_pb_line_break_holder] --> cameraOptions['speed'] = '0.5';<!-- [et_pb_line_break_holder] --> map.flyTo(cameraOptions);<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> <!-- [et_pb_line_break_holder] --> // List of additional functions you want to include as tools<!-- [et_pb_line_break_holder] --> var functions = [<!-- [et_pb_line_break_holder] --> 'toggle3d()', 'toggleFloors()', 'toggleSun()',<!-- [et_pb_line_break_holder] --> 'toggleSyntax()', 'issues()', 'helpPopup()'<!-- [et_pb_line_break_holder] --> ]<!-- [et_pb_line_break_holder] --> var functionNames = [<!-- [et_pb_line_break_holder] --> '?  3D buildings', '     Higher LOD', '     Shadow study',<!-- [et_pb_line_break_holder] --> '     SpaceSyntax', '     Comments', 'Need Help?'<!-- [et_pb_line_break_holder] --> ]<!-- [et_pb_line_break_holder] --> var startToggle = ['On', 'Off', 'Off', 'Off', 'Off', 'On']<!-- [et_pb_line_break_holder] --> // Add functions to dropdown to switch activate on click<!-- [et_pb_line_break_holder] --> for (var i = 0; i < functions.length; i++) {<!-- [et_pb_line_break_holder] --> var id = functions[i];<!-- [et_pb_line_break_holder] --> var name = functionNames[i];<!-- [et_pb_line_break_holder] --> var toggle = startToggle[i]<!-- [et_pb_line_break_holder] --> var link = document.createElement('a');<!-- [et_pb_line_break_holder] --> link.href = 'javascript:' + id<!-- [et_pb_line_break_holder] --> link.textContent = name;<!-- [et_pb_line_break_holder] --> link.id = id<!-- [et_pb_line_break_holder] --> link.classList = toggle<!-- [et_pb_line_break_holder] --> var $layerDropdown = document.getElementById('functionDropdown');<!-- [et_pb_line_break_holder] --> $layerDropdown.appendChild(link);<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> <!-- [et_pb_line_break_holder] --> // 3D buildings toggle<!-- [et_pb_line_break_holder] --> var extrusionHeight = []<!-- [et_pb_line_break_holder] --> map.on("load", function(){<!-- [et_pb_line_break_holder] --> extrusionHeight = map.getPaintProperty("buildings", "fill-extrusion-height")<!-- [et_pb_line_break_holder] --> })<!-- [et_pb_line_break_holder] --> function toggle3d(){<!-- [et_pb_line_break_holder] --> if(document.getElementById("toggle3d()").classList == "On") {<!-- [et_pb_line_break_holder] --> map.setPaintProperty("buildings", "fill-extrusion-height", 8)<!-- [et_pb_line_break_holder] --> map.setPaintProperty('floors', "fill-extrusion-opacity", 0);<!-- [et_pb_line_break_holder] --> document.getElementById("toggle3d()").textContent = "     3D buildings"<!-- [et_pb_line_break_holder] --> document.getElementById("toggle3d()").classList = "Off"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> else if(document.getElementById("toggle3d()").classList == "Off") {<!-- [et_pb_line_break_holder] --> map.setPaintProperty("buildings", "fill-extrusion-height", extrusionHeight)<!-- [et_pb_line_break_holder] --> map.setPaintProperty('floors', "fill-extrusion-opacity", 1);<!-- [et_pb_line_break_holder] --> document.getElementById("toggle3d()").textContent = "?  3D buildings"<!-- [et_pb_line_break_holder] --> document.getElementById("toggle3d()").classList = "On"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Higher LOD -- Floors toggle<!-- [et_pb_line_break_holder] --> function toggleFloors() {<!-- [et_pb_line_break_holder] --> if(document.getElementById("toggleFloors()").classList == "Off") {<!-- [et_pb_line_break_holder] --> // First check if map isnt zoomed out too far<!-- [et_pb_line_break_holder] --> // If map is far, zoom slowly to proper zoom level<!-- [et_pb_line_break_holder] --> if(map.getZoom() < 15) {<!-- [et_pb_line_break_holder] --> map.flyTo({zoom: 15, speed: 0.5})<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> else {<!-- [et_pb_line_break_holder] --> map.flyTo({zoom: map.getZoom()+0.0001})<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> map.once('zoomend', function() {<!-- [et_pb_line_break_holder] --> map.setMinZoom(15)<!-- [et_pb_line_break_holder] --> map.setPaintProperty("buildings", "fill-extrusion-opacity", 0)<!-- [et_pb_line_break_holder] --> map.setLayoutProperty('floors', 'visibility', 'visible');<!-- [et_pb_line_break_holder] --> document.getElementById("toggleFloors()").textContent = "?  Higher LOD"<!-- [et_pb_line_break_holder] --> document.getElementById("toggleFloors()").classList = "On"<!-- [et_pb_line_break_holder] --> })<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> else if(document.getElementById("toggleFloors()").classList == "On") {<!-- [et_pb_line_break_holder] --> map.setLayoutProperty('floors', 'visibility', 'none');<!-- [et_pb_line_break_holder] --> map.setPaintProperty("buildings", "fill-extrusion-opacity", 1)<!-- [et_pb_line_break_holder] --> document.getElementById("toggleFloors()").textContent = "     Higher LOD"<!-- [et_pb_line_break_holder] --> document.getElementById("toggleFloors()").classList = "Off"<!-- [et_pb_line_break_holder] --> map.setMinZoom(0)<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> // Toggle Sun hours / Shadowstudy<!-- [et_pb_line_break_holder] --> function toggleSun(){<!-- [et_pb_line_break_holder] --> if(document.getElementById("toggleSun()").classList == "Off") {<!-- [et_pb_line_break_holder] --> map.setLayoutProperty('solar', "visibility", "visible");<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSun()").textContent = "?  Shadow study"<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSun()").classList = "On"<!-- [et_pb_line_break_holder] --> <!-- [et_pb_line_break_holder] --> var popup = new mapboxgl.Popup({closeButton: false, closeOnClick: false})<!-- [et_pb_line_break_holder] --> map.on('mousemove', 'solar', function(e) {<!-- [et_pb_line_break_holder] --> map.getCanvas().style.cursor = 'help';<!-- [et_pb_line_break_holder] --> popup.remove(map)<!-- [et_pb_line_break_holder] --> var features = map.queryRenderedFeatures(e.point, {layers: ["solar"]});<!-- [et_pb_line_break_holder] --> var face = features[0];<!-- [et_pb_line_break_holder] --> var hours = face.properties.hours<!-- [et_pb_line_break_holder] --> popup.setLngLat(e.lngLat)<!-- [et_pb_line_break_holder] --> .setHTML(<!-- [et_pb_line_break_holder] --> '<dd>' + hours + ' hours</dd>' +<!-- [et_pb_line_break_holder] --> '<dt> of sunlight <br>on 1st of August.</dt>'<!-- [et_pb_line_break_holder] --> )<!-- [et_pb_line_break_holder] --> .addTo(map);<!-- [et_pb_line_break_holder] --> })<!-- [et_pb_line_break_holder] --> map.on('mouseleave', 'solar', function(){<!-- [et_pb_line_break_holder] --> map.getCanvas().style.cursor = '';<!-- [et_pb_line_break_holder] --> popup.remove(map);<!-- [et_pb_line_break_holder] --> })<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> else if(document.getElementById("toggleSun()").classList == "On") {<!-- [et_pb_line_break_holder] --> map.setLayoutProperty('solar', "visibility", "none");<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSun()").textContent = "     Shadow study"<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSun()").classList = "Off"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Toggle SpaceSyntax<!-- [et_pb_line_break_holder] --> function toggleSyntax(){<!-- [et_pb_line_break_holder] --> if(document.getElementById("toggleSyntax()").classList == "Off") {<!-- [et_pb_line_break_holder] --> map.setPaintProperty('syntax', "line-opacity", 1);<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSyntax()").textContent = "?  SpaceSyntax"<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSyntax()").classList = "On"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> else if(document.getElementById("toggleSyntax()").classList == "On") {<!-- [et_pb_line_break_holder] --> map.setPaintProperty('syntax', "line-opacity", 0);<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSyntax()").textContent = "     SpaceSyntax"<!-- [et_pb_line_break_holder] --> document.getElementById("toggleSyntax()").classList = "Off"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Feedback toggle<!-- [et_pb_line_break_holder] --> // Switch between icons visible and hidden<!-- [et_pb_line_break_holder] --> function issues() {<!-- [et_pb_line_break_holder] --> if(document.getElementById("issues()").classList == "Off") {<!-- [et_pb_line_break_holder] --> map.setLayoutProperty("wtp-comments", 'visibility', 'visible');<!-- [et_pb_line_break_holder] --> document.getElementById("issues()").textContent = "?  Comments"<!-- [et_pb_line_break_holder] --> document.getElementById("issues()").classList = "On"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> else if(document.getElementById("issues()").classList == "On") {<!-- [et_pb_line_break_holder] --> map.setLayoutProperty("wtp-comments", 'visibility', 'none');<!-- [et_pb_line_break_holder] --> document.getElementById("issues()").textContent = "     Comments"<!-- [et_pb_line_break_holder] --> document.getElementById("issues()").classList = "Off"<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --> // on hover open popup with text info<!-- [et_pb_line_break_holder] --> issuePopup = new mapboxgl.Popup({closeButton: false, closeOnClick: false})<!-- [et_pb_line_break_holder] --> map.on('mouseenter', 'wtp-comments', function(e) {<!-- [et_pb_line_break_holder] --> map.getCanvas().style.cursor = 'pointer';<!-- [et_pb_line_break_holder] --> var coordinates = e.features[0].geometry.coordinates.slice();<!-- [et_pb_line_break_holder] --> var text = e.features[0].properties.text;<!-- [et_pb_line_break_holder] --> var author = e.features[0].properties.author;<!-- [et_pb_line_break_holder] --> issuePopup.setLngLat(coordinates)<!-- [et_pb_line_break_holder] --> .setHTML('<dt>' + text + '</dt>' +<!-- [et_pb_line_break_holder] --> '<br><dd>' + author + '</dd>'<!-- [et_pb_line_break_holder] --> )<!-- [et_pb_line_break_holder] --> .addTo(map);<!-- [et_pb_line_break_holder] --> })<!-- [et_pb_line_break_holder] --> // close it on hover end<!-- [et_pb_line_break_holder] --> map.on('mouseleave', 'wtp-comments', function() {<!-- [et_pb_line_break_holder] --> map.getCanvas().style.cursor = '';<!-- [et_pb_line_break_holder] --> issuePopup.remove();<!-- [et_pb_line_break_holder] --> })<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // +++ Other useful functions<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Help popup with controls info<!-- [et_pb_line_break_holder] --> function helpPopup() {<!-- [et_pb_line_break_holder] --> window.popup = new mapboxgl.Popup()<!-- [et_pb_line_break_holder] --> .setLngLat(map.getCenter())<!-- [et_pb_line_break_holder] --> .setHTML( //OLD IE COMPATABLE MUTLILINE STRING<!-- [et_pb_line_break_holder] --> '<dd>How can you explore the model?</dd>' +<!-- [et_pb_line_break_holder] --> '<dt>Click on "Select scenario" to choose between different variants' +<!-- [et_pb_line_break_holder] --> ' or click on buildings to display more information about them.</dt>' +<!-- [et_pb_line_break_holder] --> '<dt><br>To control the camera press Control + Left Mouse Button or use' +<!-- [et_pb_line_break_holder] --> ' one of the preset positions with "Views" menu.</dt>' +<!-- [et_pb_line_break_holder] --> '<dt><br>In the "Functions" menu you can hide the 3D geometry' +<!-- [et_pb_line_break_holder] --> ' and change the Level of Detail or show a demo of feedback system.</dt>'<!-- [et_pb_line_break_holder] --> )<!-- [et_pb_line_break_holder] --> .addTo(map);<!-- [et_pb_line_break_holder] --> }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> // Layer with additional data popup on click<!-- [et_pb_line_break_holder] --> activeLayer = 'buildings'<!-- [et_pb_line_break_holder] --> // change the cursor when hovering over this layer<!-- [et_pb_line_break_holder] --> map.on('mouseenter', activeLayer, function(event) {<!-- [et_pb_line_break_holder] --> map.getCanvas().style.cursor = 'help';<!-- [et_pb_line_break_holder] --> }); <!-- [et_pb_line_break_holder] --> map.on('mouseleave', activeLayer, function() {<!-- [et_pb_line_break_holder] --> map.getCanvas().style.cursor = '';<!-- [et_pb_line_break_holder] --> });<!-- [et_pb_line_break_holder] --> // Open popup with GeoJson properties on click<!-- [et_pb_line_break_holder] --> map.on('click', function(event) {<!-- [et_pb_line_break_holder] --> var features = map.queryRenderedFeatures(event.point, {layers: [activeLayer]});<!-- [et_pb_line_break_holder] --> var building = features[0];<!-- [et_pb_line_break_holder] --> <!-- [et_pb_line_break_holder] --> // Keys you want to include<!-- [et_pb_line_break_holder] --> if (features.length) {<!-- [et_pb_line_break_holder] --> var landUse = building.properties.function || '–';<!-- [et_pb_line_break_holder] --> var height = Math.round(building.properties.height) || '–';<!-- [et_pb_line_break_holder] --> var gfa = Math.round(building.properties.GFA) || '–';<!-- [et_pb_line_break_holder] --> var id = building.properties.build_ID || '–';<!-- [et_pb_line_break_holder] --> <!-- [et_pb_line_break_holder] --> // HTML content of the popup<!-- [et_pb_line_break_holder] --> window.popup = new mapboxgl.Popup()<!-- [et_pb_line_break_holder] --> .setLngLat(event.lngLat)<!-- [et_pb_line_break_holder] --> .setHTML( <!-- [et_pb_line_break_holder] --> '<dl>' +<!-- [et_pb_line_break_holder] --> // '<dt>Land Use</dt>' +<!-- [et_pb_line_break_holder] --> // '<dd>' + landUse + '</dd>' +<!-- [et_pb_line_break_holder] --> '<dt>Building Height</dt>' +<!-- [et_pb_line_break_holder] --> '<dd>' + height + ' m' + '</dd>' +<!-- [et_pb_line_break_holder] --> '<dt>GFA</dt>' +<!-- [et_pb_line_break_holder] --> '<dd>' + gfa + ' sqm' + '</dd>' +<!-- [et_pb_line_break_holder] --> '<dt>ID#</dt>' +<!-- [et_pb_line_break_holder] --> '<dd>' + id + '</dd>' +<!-- [et_pb_line_break_holder] --> '</dl>') //OLD IE COMPATABLE MUTLILINE STRING FORMAT<!-- [et_pb_line_break_holder] --> .addTo(map);<!-- [et_pb_line_break_holder] --> };<!-- [et_pb_line_break_holder] --> });<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --> </script>

Acknowledgement

The research background for Syncity design studio was part of the project Integrated Infrastructure (IN³). It is an interdisciplinary international research project at the Bauhaus-Universität Weimar (BUW) and the Ethiopia Institute for Architecture, Building Construction and City Development (EiABC).  We are also grateful to the Singapore-ETH Centre teams Multi-Scale Energy Systems for Low Carbon Cities, Engaging Mobility, and Big Data-Informed Urban Design and Governance for contributing their knowledge, experience and time to our design studio.

Related Publications

Sorry, but the selected Zotpress account can't be found.

Pin It on Pinterest