var coordinatesBB = [] //var url = "https://simstadt-api.iaf-ex.hft-stuttgart.de:8080/workflow/execute" //old link var url = "http://vm24.fkc.hft-stuttgart.de:8080/workflow/execute" // URL to API /*TODO#1: -get current data from the api and create local test data (apiData foler) -add connection handeling (error messages when there isnt a connection and then using the local test data) */ var buildingFunctionSort var constructionYearSortPick var heightSortPick var heatedVolumeSortPick var totalSurfaceAreaSortPick var roofTypeSortPick var uValueSortPick async function fetchDataJSON() { var bottomLat = coordinatesBB[1] var leftLng = coordinatesBB[0] var rightLng = coordinatesBB[2] var topLat = coordinatesBB[3]// const response = await fetch(url, { method: "POST", body: JSON.stringify({ "boundingBox": { "bottomLat": bottomLat, //48.779004965, "leftLng": leftLng, //9.1686843081, "lodType": "LOD2", "rightLng": rightLng, //9.175336684, "topLat": topLat //48.7822869656 }, "cityGMLRef": "campusLOD2", "interestedAttributes": [ "uValue", "volume", "height", "heatedVolume", "yearOfConstruction", "buildingFunction", "monthlyHeating", "monthlyCooling", "pvPotential", "roofType", "totalSurfaceArea" ], "properies": { "physicsUseScenario": false } }), headers: { "Content-Type": "application/json", "Authorization": "Basic YWRtaW46YWRtaW4xMjM=" } }) const data = await response.json() return data } document.getElementById("loader").style.visibility = "hidden" function processData() { console.log(coordinatesBB) console.log("Waiting for data....") fetchDataJSON().then(data => { console.log(data); document.getElementById("cesiumContainer").style.opacity = "1"; document.getElementById("loader").style.visibility = "hidden" console.log("....received data") var buildingsMAP = new Map() data.buildings.forEach(bu => { var partsArray = [] var surefacesArray = [] bu.parts.forEach(p => p.surfaces.forEach(s => surefacesArray.push(new Surface(s.id, s.attributes.uValue, s.attributes.totalSurfaceArea)))) bu.parts.forEach(p => partsArray.push(new Part(p.id, surefacesArray, p.attributes.volume, p.attributes.height, p.attributes.heatedVolume, p.attributes.yearOfConstruction, p.attributes.buildingFunction, p.attributes.monthlyHeating, p.attributes.monthlyCooling, p.attributes.roofType))) buildingsMAP.set(bu.id, new Building(bu.id, partsArray)) //puts buildings with parts and surfaces in a map }) var partHeightMAP = new Map() var partVolumeMAP = new Map() var partHeatedVolumeMAP = new Map() var partConstructionYearMAP = new Map() var partBuildingTypeMAP = new Map() var partMonthlyHeatingMAP = new Map() var partMonthlyCoolingMAP = new Map() var surfaceUValueMAP = new Map() var partRoofTypeMAP = new Map() var surfaceTotalSurfaceAreaMAP = new Map() //fill height, heated volume and construction year map buildingsMAP.forEach(b => { b.parts.forEach(part => { if (part.height !== undefined) { partHeightMAP.set(part.id, part.height) } if (part.volume !== undefined) { partVolumeMAP.set(part.id, part.volume) } if (part.heatedVolume !== undefined) { partHeatedVolumeMAP.set(part.id, part.heatedVolume) } if (part.yearOfConstruction !== undefined && part.yearOfConstruction <= "2020") { partConstructionYearMAP.set(part.id, part.yearOfConstruction) } if (part.buildingFunction !== undefined) { partBuildingTypeMAP.set(part.id, part.buildingFunction) } if (part.monthlyHeating !== undefined) { partMonthlyHeatingMAP.set(part.id, part.monthlyHeating) } if (part.monthlyCooling !== undefined) { partMonthlyCoolingMAP.set(part.id, part.monthlyCooling) } if (part.roofType !== undefined) { partRoofTypeMAP.set(part.id, part.roofType) } part.surfaces.forEach(s => { if (s.uValue !== undefined) { surfaceUValueMAP.set(s.id, s.uValue) } }) //totalSurfaceArea surfaceTotalSurfaceAreaMAP.set(part.id, part.surfaces) }) }) //sort maps const heightSort = new Map([...partHeightMAP.entries()].sort((a, b) => b[1] - a[1])); const heatedVolumeSort = new Map([...partHeatedVolumeMAP.entries()].sort((a, b) => b[1] - a[1])); const constructionYearSort = new Map([...partConstructionYearMAP.entries()].sort((a, b) => a[1] - b[1])); const uValueSort = new Map([...surfaceUValueMAP.entries()].sort((a, b) => b[1] - a[1])); //for Properties Single Buildings buildingFunctionSortPick = new Map([...partBuildingTypeMAP.entries()].sort((a, b) => b[1] - a[1])); constructionYearSortPick = new Map([...partConstructionYearMAP.entries()].sort((a, b) => a[1] - b[1])); heightSortPick = new Map([...partHeightMAP.entries()].sort((a, b) => b[1] - a[1])); heatedVolumeSortPick = new Map([...partHeatedVolumeMAP.entries()].sort((a, b) => b[1] - a[1])); totalSurfaceAreaSortPick = new Map([...surfaceTotalSurfaceAreaMAP.entries()].sort((a, b) => b[1] - a[1])); roofTypeSortPick = new Map([...partRoofTypeMAP.entries()].sort((a, b) => b[1] - a[1])); uValueSortPick = new Map([...surfaceUValueMAP.entries()].sort((a, b) => b[1] - a[1])); //fill arrays needed for charts heightSort.forEach((value, key) => addHeightInfosToArrays(key, value)) heatedVolumeSort.forEach((value, key) => addHeatedVolumeInfosToArrays(key, value)) constructionYearSort.forEach((value) => yearOfConstructionValues.push(value)) partBuildingTypeMAP.forEach((value) => buildingTypeValues.push(value)) partMonthlyHeatingMAP.forEach((valueArray, key) => yearlyHeatingDemand(key, valueArray)) partMonthlyCoolingMAP.forEach((valueArray, key) => yearlyCoolingDemand(key, valueArray)) uValueSort.forEach((value, key) => { uValueSurfaces(key, value) uValuesAll.push(value) }) partMonthlyHeatingMAP.forEach((value, key) => addmonthlyHeatingInfosToArrays(key, value)) partMonthlyCoolingMAP.forEach((value, key) => addmonthlyCoolingInfosToArrays(key, value)) partVolumeMAP.forEach((value, key) => addVolumeValues(key, value)) //calculates year of construction frequency yearFrequency() //calculates building type frequency buildingTypeFrequency() //calculates uValue frequency uValueFrequency() //sorts yearly heating & cooling demand for charts sortMap() //disables attributes in chart without values availableAttributes() //color buildings with heating demand document.getElementById("checkbox2").addEventListener("change", function () { if (this.checked) { tileContent.forEach(t => { let tileID = t.getProperty("gml_parent_id") let tileColor = heatingIDColorMAP.get(tileID) if (tileColor !== undefined) { t.color = Cesium.Color.fromCssColorString(tileColor) } else { t.color = new Cesium.Color(1, 1, 1, 1) } }) console.log("colored") } else { tileContent.forEach(t => t.color = new Cesium.Color(1, 1, 1, 1)) console.log("not colored") } }) //color surfaces with uValue document.getElementById("checkbox1").addEventListener("change", function () { if (this.checked) { tileContent.forEach(t => { let tileID = t.getProperty("gml_id") let tileColor = surfaceIDColorMAP.get(tileID) if (tileColor !== undefined) { t.color = Cesium.Color.fromCssColorString(tileColor) } else { t.color = new Cesium.Color(1, 1, 1, 1) } }) console.log("colored") } else { tileContent.forEach(t => t.color = new Cesium.Color(1, 1, 1, 1)) console.log("not colored") } }) }).catch((err) => { console.log(err) }) } function showAllUVales() { this.parts.forEach(p => p.surfaces.forEach(s => console.log(s.uValue))) } function Building(id, parts) { this.id = id this.parts = parts this.showAllUVales = showAllUVales } function Part(id, surfaces, volume, height, heatedVolume, yearOfConstruction, buildingFunction, monthlyHeating, monthlyCooling, roofType) { this.id = id; this.surfaces = surfaces this.volume = volume this.height = height this.heatedVolume = heatedVolume this.yearOfConstruction = yearOfConstruction this.buildingFunction = buildingFunction this.monthlyHeating = monthlyHeating this.monthlyCooling = monthlyCooling this.roofType = roofType } function Surface(id, uValue, totalSurfaceArea) { this.id = id; this.uValue = uValue this.totalSurfaceArea = totalSurfaceArea } let tileContent = [] // When the user clicks the button, open the modal var elemurlevt = document.getElementById("submitID"); elemurlevt.addEventListener("click", loadTileset); //Get the modal var modal = document.getElementById("myModal"); var span = document.getElementsByClassName("close")[0]; //close the modal span.onclick = function () { modal.style.display = "none"; deleteTilesetButtons() } // modal closes, when the user clicks anywhere outside of the modal window.onclick = function (event) { if (event.target == modal) { modal.style.display = "none"; deleteTilesetButtons() } } //------------------------------------------------------------------------------- var tileData = null; var tileset = null; var tilesetURL = 'http://vm24.fkc.hft-stuttgart.de:8081/CampusLOD2/CityModel/tileset.json'; var localTestTileset = '/3dclient4simstadtapi/public/test/tileset/gmlTileset_v1.json'; const controller = new AbortController(); //used to abort the request when it takes too long const timeoutId = setTimeout(() => controller.abort(), 3000); // 3 second timeout: //fetching the tileset and handling the connection async function fetchTileset(){ fetch(tilesetURL,{signal:controller.signal}).then((response)=>{ //fetch request with the abort controller if(response.status >= 200 && response.status<=299){ //successful connection //const tilesetJSON = response.json(); loadAndZoomToTileset(tilesetURL); swal({text:"",timer:100}); //used to remove the waiting alert }else{ throw Error(response.statusText); //throwing an error when a connection is not possible } clearTimeout(timeoutId); //timeout the request }).then((jsonResponse)=>{ console.log("Tileset"+jsonResponse); }).catch((error)=>{ //catching the error and displaying an alert for the user var errorString = error["stack"]+"\n"+error["message"]; // formatting the error array swal("Could not connect to Server",errorString , "error"); console.log("Using local test data"); loadAndZoomToTileset(localTestTileset); //TODO#3: fix the link so the local tileset can be loaded }) swal({text:"Connecting to Server ... Please wait !",icon:"info" ,buttons: false}); //displays waiting alert } /* NOTE #1: -load the models but the are in the too high in the "air" -building view doesn´t work because all buildings are grouped together -surfaces are also broken -->this fixme is the problem of the backendteam ! ? maybe add old menu back and the option to also load the new ones */ //loads tileset after submit button is clicked function loadTileset() { viewer.scene.primitives.remove(tileset); tileContent = []; modal.style.display = "block"; fetchTileset(); //var userurl = document.getElementById("3Durl").value; //returns the chosen area from the dropdown } //loads the tileset from the url into the cesium viewer and zooms to it function loadAndZoomToTileset(url){ tileset=viewer.scene.primitives.add(new Cesium.Cesium3DTileset({ url: url })); viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0, -0.5, 0)); modal.style.display = "none"; saveTilesetContent(tileset) deleteTilesetButtons() } function useContent(content) { content.forEach(cont => { var element = document.createElement("input") element.type = "button" element.value = cont.title element.value = cont.title element.name = "individualTileset" document.getElementById("myList").appendChild(element); element.onclick = function () { tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({ url: cont.href })); viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0, -0.5, 0)); modal.style.display = "none"; saveTilesetContent(tileset) deleteTilesetButtons() }; }) } function saveTilesetContent(tileset) { tileset.tileLoad.addEventListener(tile => { const content = tile.content; for (let i = 0; i < content.featuresLength; i++) { let f = content.getFeature(i); tileContent.push(f) } }) } function deleteTilesetButtons() { var x = document.getElementsByName("individualTileset") var len = x.length //checking if there are even tileset to delete if(x.length>0){ parentNode = x[0].parentNode; for (var i = 0; i < len; i++) { parentNode.removeChild(x[0]); } } }