Commit a34b5f3c authored by Mukhtar's avatar Mukhtar
Browse files

Upload New File

parent 5fd8f08e
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="https://cesium.com/downloads/cesiumjs/releases/1.80/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.80/Build/Cesium/Widgets/widgets.css"
rel="stylesheet" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css"
integrity="sha384-4LISF5TTJX/fLmGSxO53rV4miRxdg84mZsxmO8Rx5jGtp/LbrixFETvWa5a6sESd" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="webmap">
<div id="cesiumContainer"></div>
<div class="menu">
<div class="menubuttons">
<div class="menuDiv">
<div>
<b>Select the Attribute to Visualize Statistics</b>
</div>
<div>
<div class="options">
<input type="radio" id="yearOfCo" name="attribute" value="Year_of_co" checked />
<label for="yearOfCo">Year of Construction</label>
</div>
<div class="options">
<input type="radio" id="primaryUsa" name="attribute" value="PrimaryUsa" />
<label for="primaryUsa">Primary Usage</label>
</div>
<div class="options">
<input type="radio" id="specificS" name="attribute" value="Specific_s" />
<label for="specificS">Heating demand in [kWh/m².year]</label>
</div>
</div>
</div>
</div>
<div class="chartContainer">
<div class="chartCanvas">
<canvas id="quant-chart"></canvas>
</div>
</div>
<div id="individualStatsChart" class="individualStatsChart">
<p id="stats-tag">Select a building to show statistics...</p>
<canvas id="buildingStats"></canvas>
</div>
</div>
</div>
<div class="backdrop" id="menu">
<h3>Stoeckach Energy Dashboard</h3>
<div id="legend"">
<div class=" my-legend" id="legendcontainer">
<div class="legend-title">Sp. Heating Demand (kWh/m<sup>2</sup>.a)</div>
<div class="legend-scale">
<ul class="legend-labels">
<li><span style="background: #771f02"></span>Demand >= 250 </li>
<li><span style="background: #be4400"></span>Demand >= 200 </li>
<li><span style="background: #ee5c00"></span>Demand >= 150 </li>
<li><span style="background: #ef8d00"></span>Demand >= 125 </li>
<li><span style="background: #f0ba00"></span>Demand >= 100 </li>
<li><span style="background: #f1d700"></span>Demand >= 75 </li>
<li><span style="background: #e4f200"></span>Demand >= 50 </li>
<li><span style="background: #b8fe00"></span>Demand >= 25 </li>
<li><span style="background: #4cbb00"></span>Demand < 25 </li>
<li><span style="background: #000000"></span>None Heated / No Data</li>
</ul>
</div>
</div>
</div>
</div>
<i class="bi bi-info-circle-fill icon" id="toggleIcon"></i>
<script>
Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIwNTg4NmUwZS0wZTk5LTQ0MTMtYTcwMS05OTU4NzcxZGIyZTMiLCJpZCI6MjE3MzI3LCJpYXQiOjE3MTY0NzAyMjB9.DxT60vd_gLj7WGPyNbsNP8mKOy40UKMe-av2z5mvE1E";
var viewer = new Cesium.Viewer("cesiumContainer", {
baseLayerPicker: true,
vrButton: true,
geocoder: true,
navigationHelpButton: false,
selectionIndicator: true,
shadows: true,
timeline: true,
sceneModePicker: true,
});
var tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: "./tileset.json",
})
);
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["Number(${Specific_s}) >= 250", "color('#771f02')"],
["Number(${Specific_s}) >= 200", "color('#be4400')"],
["Number(${Specific_s}) >= 150", "color('#ee5c00')"],
["Number(${Specific_s}) >= 125", "color('#ef8d00')"],
["Number(${Specific_s}) >= 100", "color('#4cbb00')"],
["Number(${Specific_s}) >= 75", "color('#f0ba00')"],
["Number(${Specific_s}) >= 50", "color('#f1d700')"],
["Number(${Specific_s}) >= 25", "color('#e4f200')"],
["true", "color('#000000')"],
],
},
});
let lineChartInstance;
//Selecting a Building
var Pickers_3DTile_Activated = true;
function active3DTilePicker() {
var element = document.getElementById('individualStatsChart');
if (element) {
element.style.display = 'block';
}
var highlighted = {
feature: undefined,
originalColor: new Cesium.Color()
};
// Information about the currently selected feature
var selected = {
feature: undefined,
originalColor: new Cesium.Color()
};
// An entity object which will hold info about the currently selected feature for infobox display
var selectedEntity = new Cesium.Entity();
// Get default left click handler for when a feature is not picked on left click
var clickHandler = viewer.screenSpaceEventHandler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
// Color a feature GREY on hover.
viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
if (Pickers_3DTile_Activated) {
// If a feature was previously highlighted, undo the highlight
if (Cesium.defined(highlighted.feature)) {
highlighted.feature.color = highlighted.originalColor;
highlighted.feature = undefined;
}
// Pick a new feature
var picked3DtileFeature = viewer.scene.pick(movement.endPosition);
if (!Cesium.defined(picked3DtileFeature)) {
return;
}
// Highlight the feature if it's not already selected.
if (picked3DtileFeature !== selected.feature) {
highlighted.feature = picked3DtileFeature;
Cesium.Color.clone(picked3DtileFeature.color, highlighted.originalColor);
picked3DtileFeature.color = Cesium.Color.GREY;
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// Color a feature AQUA on selection and show info in the InfoBox.
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
if (Pickers_3DTile_Activated) {
// If a feature was previously selected, undo the highlight
if (Cesium.defined(selected.feature)) {
selected.feature.color = selected.originalColor;
selected.feature = undefined;
var options = null;
lineChartInstance.destroy();
lineChartInstance = null;
document.getElementById('stats-tag').style.display = 'block';
}
// Pick a new feature
var picked3DtileFeature = viewer.scene.pick(movement.position);
if (!Cesium.defined(picked3DtileFeature)) {
clickHandler(movement);
return;
}
// Select the feature if it's not already selected
if (selected.feature === picked3DtileFeature) {
return;
}
selected.feature = picked3DtileFeature;
// Save the selected feature's original color
if (picked3DtileFeature === highlighted.feature) {
Cesium.Color.clone(highlighted.originalColor, selected.originalColor);
highlighted.feature = undefined;
} else {
Cesium.Color.clone(picked3DtileFeature.color, selected.originalColor);
}
// Highlight newly selected feature
picked3DtileFeature.color = Cesium.Color.AQUA;
// Set feature infobox description
var featureName = "Building Attributes";
selectedEntity.name = featureName;
selectedEntity.description = 'Loading <div class="cesium-infoBox-loading"></div>';
viewer.selectedEntity = selectedEntity;
selectedEntity.description =
'<table class="cesium-infoBox-defaultTable"><tbody>' +
'<tr><th>GML ID</th><td>' + picked3DtileFeature.getProperty('gml_id') + '</td></tr>' +
'<tr><th>GML Parent ID</th><td>' + picked3DtileFeature.getProperty('gml_parent_id') + '</td></tr>' +
'<tr><th>Sp. Heating Demand</th><td>' + picked3DtileFeature.getProperty('Specific_s') + ' ' + 'kWh/m²' + '</td></tr>' +
'</tbody></table>';
document.getElementById('stats-tag').style.display = 'none';
} else {
document.getElementById('stats-tag').style.display = 'block';
}
// Fetch GeoJSON data - please install CORS plugin otherwise this will not work
fetch('https://ugl.hft-stuttgart.de/leaflet-stoeckach-heatdemand/building_data.json')
.then(response => response.json())
.then(data => {
// var picked3DtileFeature = viewer.scene.pick(movement.position);
var gml_id = picked3DtileFeature.getProperty('gml_id');
var buildingData = data.features.find(feature => feature.properties.gml_id == gml_id)
if (buildingData) {
var properties = buildingData.properties;
var months = [
'January_He', 'February_H', 'March_Heat', 'April_Heat', 'May_Heatin',
'June_Heati', 'July_Heati', 'August_Hea', 'September_', 'October_He',
'November_H', 'December_H'
];
var monthlyValues = months.map(month => {
// Handle potential formatting issues
var value = properties[month];
if (typeof value === 'string') {
value = parseFloat(value.replace(',', '.'));
}
return value;
});
// Create the building year of construction distribution chart using Chart.js
var ctx1 = document.getElementById('buildingStats').getContext('2d');
// Destroy the previous chart instance if it exists
if (lineChartInstance) {
lineChartInstance.destroy();
}
lineChartInstance = new Chart(ctx1, {
type: 'line',
data: {
labels: [
'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'
],
datasets: [{
label: 'Heat Demand Per Month',
data: monthlyValues,
backgroundColor: 'rgba(75, 192, 192, 0.5)',
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 1
}]
},
options: {
responsive: true,
scales: {
x: {
title: {
display: true,
text: "Month",
font: {
size: 8,
family: "Inter",
weight: 600,
},
},
grid: {
color: "#edf2f4",
lineWidth: 0.5, // Change grid line color to light shade
},
ticks: {
font: {
size: 7,
family: "Inter",
weight: 500,
},
color: "#2C2C2C",
},
},
y: {
title: {
display: true,
text: "Heating demand in [kWh/m².month]",
font: {
size: 8,
family: "Inter",
weight: 600,
},
},
grid: {
color: "#edf2f4",
lineWidth: 0.5, // Change grid line color to light shade
},
beginAtZero: true,
ticks: {
font: {
size: 8,
family: "Inter",
weight: 500,
},
color: "#2C2C2C",
},
},
},
plugins: {
legend: {
labels: {
font: {
size: 9, // Font size for legend labels
family: "Inter",
weight: 500,
},
color: "#2C2C2C",
},
display: false,
},
title: {
font: {
size: 13,
family: "Inter",
weight: 600,
},
display: true,
text: 'Heating Demand for Building (GML_ID: ' + gml_id + ')'
},
},
},
});
}
})
},
Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
active3DTilePicker();
document.addEventListener('DOMContentLoaded', function () {
// Get the element and close button by their IDs
var element = document.getElementById('individualStatsChart');
var closeButton = document.getElementById('closeStats');
// Check if the elements exist
if (element && closeButton) {
// Add click event listener to the close button
closeButton.addEventListener('click', function () {
// Hide the element
element.style.display = 'none';
});
}
});
// Charts and Visualization
let chart;
Cesium.when(tileset.readyPromise).then(function (tileset) {
viewer.flyTo(tileset);
var processedTiles = new Set();
var yearFrequency = {};
var primaryUsaFrequency = {};
var specificSFrequency = {
"0-25": 0,
"26-50": 0,
"51-75": 0,
"76-100": 0,
"101-125": 0,
"126-150": 0,
"151-200": 0,
"201-250": 0,
"251+": 0,
};
tileset.tileVisible.addEventListener(function (tile) {
if (!processedTiles.has(tile)) {
processedTiles.add(tile);
var content = tile.content;
var featuresLength = content.featuresLength;
for (var i = 0; i < featuresLength; i++) {
var feature = content.getFeature(i);
var year = feature.getProperty("Year_of_co");
if (year) {
if (yearFrequency[year]) {
yearFrequency[year]++;
} else {
yearFrequency[year] = 1;
}
}
var primaryUsa = feature.getProperty("PrimaryUsa");
if (primaryUsa) {
if (primaryUsaFrequency[primaryUsa]) {
primaryUsaFrequency[primaryUsa]++;
} else {
primaryUsaFrequency[primaryUsa] = 1;
}
}
var specific_s = feature.getProperty("Specific_s");
if (specific_s) {
specific_s = Number(specific_s);
if (specific_s >= 0 && specific_s <= 25) {
specificSFrequency["0-25"]++;
} else if (specific_s > 25 && specific_s <= 50) {
specificSFrequency["26-50"]++;
} else if (specific_s > 50 && specific_s <= 75) {
specificSFrequency["51-75"]++;
} else if (specific_s > 75 && specific_s <= 100) {
specificSFrequency["76-100"]++;
} else if (specific_s > 100 && specific_s <= 125) {
specificSFrequency["101-125"]++;
} else if (specific_s > 125 && specific_s <= 150) {
specificSFrequency["126-150"]++;
} else if (specific_s > 150 && specific_s <= 200) {
specificSFrequency["151-200"]++;
} else if (specific_s > 200 && specific_s <= 250) {
specificSFrequency["201-250"]++;
} else if (specific_s > 250) {
specificSFrequency["251+"]++;
}
}
}
// Draw initial chart based on the default selection
updateChart();
}
});
const drawChart = (labels, data, type, label) => {
var ctx = document.getElementById("quant-chart").getContext("2d");
// Destroy existing chart instance if it exists
if (chart) {
chart.destroy();
}
var options = {
responsive: true,
plugins: {
legend: {
labels: {
font: {
family: "Inter", // Set font family
size: 11, // Set font size
weight: "bold", // Set font weight
},
},
},
},
scales: {
x: {
ticks: {
font: {
family: "Inter", // Set font family
size: 9, // Set font size
weight: "normal", // Set font weight
},
},
},
y: {
ticks: {
font: {
family: "Inter", // Set font family
size: 9, // Set font size
weight: "normal", // Set font weight
},
},
},
},
};
var backgroundColors = "rgba(75, 192, 192, 0.2)";
var borderColors = "rgba(75, 192, 192, 1)";
if (type === "doughnut") {
// Custom colors for doughnut chart
backgroundColors = [
"#FF6384",
"#36A2EB",
"#FFCE56",
"#FF9F40",
"#4BC0C0",
"#9966FF",
"#FF6384",
"#36A2EB",
];
// Convert labels to Init Case
labels = labels.map((label) =>
label.replace(/\b\w/g, (char) => char.toUpperCase())
);
options = {
...options,
plugins: {
tooltip: {
callbacks: {
label: function (tooltipItem) {
let value = data[tooltipItem.dataIndex];
let total = data.reduce((acc, val) => acc + val, 0);
let percentage = ((value / total) * 100).toFixed(2);
return `${labels[tooltipItem.dataIndex]
}: ${percentage}% (${value})`;
},
},
},
legend: {
labels: {
generateLabels: function (chart) {
var data = chart.data;
if (data.labels.length && data.datasets.length) {
return data.labels.map((label, i) => {
var value = data.datasets[0].data[i];
var total = data.datasets[0].data.reduce(
(acc, val) => acc + val,
0
);
var percentage = ((value / total) * 100).toFixed(2);
return {
text: `${label} (${percentage}%)`,
fillStyle: data.datasets[0].backgroundColor[i],
hidden: false,
lineCap: "butt",
lineDash: [],
lineDashOffset: 0,
lineJoin: "miter",
strokeStyle: "rgba(0,0,0,0.1)",
pointStyle: "circle",
rotation: 0,
};
});
}
return [];
},
},
},
},
};
} else if (
type === "bar" &&
label === "Heating demand in [kWh/m².year]"
) {
// Custom colors for specific_s bar chart
backgroundColors = [
"#4cbb00",
"#b8fe00",
"#e4f200",
"#f1d700",
"#f0ba00",
"#ef8d00",
"#ee5c00",
"#be4400",
];
borderColors = backgroundColors;
options.plugins = {
legend: {
display: true,
},
};
}
chart = new Chart(ctx, {
type: type,
data: {
labels: labels,
datasets: [
{
label: label,
data: data,
backgroundColor: Array.isArray(backgroundColors)
? backgroundColors
: [backgroundColors],
borderColor:
type === "doughnut"
? "transparent"
: Array.isArray(borderColors)
? borderColors
: [borderColors],
borderWidth: 1,
},
],
},
options: options,
});
};
const updateChart = () => {
var selectedAttribute = document.querySelector(
'input[name="attribute"]:checked'
).value;
if (selectedAttribute === "Year_of_co") {
var labels = Object.keys(yearFrequency);
var data = Object.values(yearFrequency);
drawChart(labels, data, "bar", "Building Count");
} else if (selectedAttribute === "PrimaryUsa") {
var labels = Object.keys(primaryUsaFrequency);
var data = Object.values(primaryUsaFrequency);
drawChart(labels, data, "doughnut", "Primary Use Percentage");
} else if (selectedAttribute === "Specific_s") {
var labels = Object.keys(specificSFrequency);
var data = Object.values(specificSFrequency);
drawChart(labels, data, "bar", "Heating demand in [kWh/m².year]");
}
};
// Add event listeners to radio buttons
document
.querySelectorAll('input[name="attribute"]')
.forEach((radio) => {
radio.addEventListener("change", updateChart);
});
});
document.getElementById('toggleIcon').addEventListener('click', function() {
var menu = document.getElementById('menu');
var icon = document.getElementById('toggleIcon');
// Toggle the menu display
if (menu.style.display === 'none' || menu.style.display === '') {
menu.style.display = 'block';
} else {
menu.style.display = 'none';
}
// Toggle the icon position
icon.classList.toggle('moved');
});
</script>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment