Commit 9a755383 authored by Sven Schneider's avatar Sven Schneider
Browse files

added new demo around churchtower in Stoeckach

parent fa3cf353
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->
<head>
<meta charset="utf-8">
<title>Stuttgart</title>
<link rel="stylesheet" href="css/myCesiumStyle.css">
<link rel="stylesheet" href="css/legend.css">
<link href="https://cesium.com/downloads/cesiumjs/releases/1.69/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"
integrity="sha256-1A78rJEdiWTzco6qdn3igTBv9VupN3Q1ozZNTR4WE/Y=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"
integrity="sha256-0rguYS0qgS6L4qVzANq4kjxPLtvnp5nn2nB5G1lWRv4=" crossorigin="anonymous"></script>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.69/Build/Cesium/Cesium.js"></script>
<script src="https://d3js.org/d3-dsv.v1.min.js"></script>
<script src="https://d3js.org/d3-fetch.v1.min.js"></script>
</head>
<body>
<header>
<img src="imgs/icity.png" class="titleFigure">
<h2> TP2.4 - Prototyp 5: Webbasierte Visualisierung von CFD Simulationsdaten </h2>
</header>
<script src="Kirchturm1.js"></script>
<div id="cesiumContainer" class="pagecesium">
<div id="legend">
<table>
<tr style="height: 30px;vertical-align: top;">
<td colspan="2">Wind speed (m/s) </td>
<td></td>
</tr>
<tr>
<td rowspan="1" style="height:100px;text-align:right;"><img src="imgs/colorbarJET.png" height="100"
width="20"> </td>
<td>- 3.5<p style="margin-top: 78px;">
<p> - 0
</td>
</tr>
</table>
</div>
</div>
<footer>
<p align="center">
<h5>Copyright &copy; 2018 - 2020, HFT-Stuttgart. All rights reserved</h5>
</p>
</footer>
</body>
</html>
\ No newline at end of file
$(function () {
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5ODI4ZTYyZS1mMTg2LTQ5NGEtYjdiOS02ODg2NzVhNjc0MTAiLCJpZCI6MjkwNCwiaWF0IjoxNTM1MTA5OTAzfQ.kyDX_0ScvJBkYnvXI0DW5NfZbiaRL5ezwtAUhxYnk1Y';
var imageryViewModels = [];
imageryViewModels.push(new Cesium.ProviderViewModel({
name: 'Sentinel-2',
iconUrl: Cesium.buildModuleUrl('Widgets/Images/ImageryProviders/sentinel-2.png'),
tooltip: 'Sentinel-2 cloudless.',
creationFunction: function () {
return new Cesium.IonImageryProvider({ assetId: 3954 });
}
}));
imageryViewModels.push(new Cesium.ProviderViewModel({
name: 'Blue Marble',
iconUrl: Cesium.buildModuleUrl('Widgets/Images/ImageryProviders/blueMarble.png'),
tooltip: 'Blue Marble Next Generation July, 2004 imagery from NASA.',
creationFunction: function () {
return new Cesium.IonImageryProvider({ assetId: 3845 });
}
}));
var viewer = new Cesium.Viewer('cesiumContainer',
{
imageryProvider: new Cesium.IonImageryProvider({ assetId: 3954 }),
terrainProvider : new Cesium.CesiumTerrainProvider({
url: Cesium.IonResource.fromAssetId(1)
}),
scene3DOnly: false,
shouldAnimate: true,
animation: true,
infoBox: true,
baseLayerPicker: true,
fullscreenButton: false,
timeline: false,
navigationHelpButton: true,
navigationInstructionsInitiallyVisible: false,
homeButton: false,
selectionIndicator: true,
geocoder: true,
// imageryProviderViewModels: imageryViewModels
});
var layer = viewer.imageryLayers.addImageryProvider(
new Cesium.IonImageryProvider({ assetId: 2 })
);
// var imageryLayer = viewer.imageryLayers.addImageryProvider(
// new Cesium.IonImageryProvider({ assetId: 3954 })
// );
var canvas = viewer.canvas;
canvas.setAttribute('tabindex', '0'); // needed to put focus on the canvas
canvas.addEventListener('click', function() {
canvas.focus();
});
canvas.focus();
var scene = viewer.scene;
var osmBuildings = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: Cesium.IonResource.fromAssetId(96188),
})
);
const buildingHeightOffset = 60; //53
///////////////////// STOECKACH LOD 1
// var stoeckach = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
// url: 'buildingTiles/StoeckachLOD1/tileset.json',
// show: true
// }));
// stoeckach.readyPromise.then(function (stoeckach) {
// var R = 0; // roll
// var P = 0; // pitch
// var Yaw = 0; // yaw
// var height = buildingHeightOffset;
// var cartographic = Cesium.Cartographic.fromCartesian(stoeckach.boundingSphere.center);
// var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
// var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
// var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
// //var rotMat = new Cesium.Matrix3();
// var rotation = new Cesium.Matrix3.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(Yaw, P, R));
// stoeckach.modelMatrix = Cesium.Matrix4.fromRotationTranslation(rotation,translation);
// return zoomAll(stoeckach);
// });
// stoeckach.readyPromise.then(function(stoeckach){
// stoeckach.style = new Cesium.Cesium3DTileStyle({
// color: "color('white',0.5)",
// })
// });
///////////////////////////// Target //////////////////////////
var target_tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: 'buildingTiles/circularTiles/target_black/tileset.json',
show: true
}));
target_tileset.readyPromise.then(function (target_tileset) {
var R = 0; // roll
var P = 0; // pitch
var Yaw = 0; // yaw
var height = buildingHeightOffset;
var cartographic = Cesium.Cartographic.fromCartesian(target_tileset.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
//var rotMat = new Cesium.Matrix3();
var rotation = new Cesium.Matrix3.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(Yaw, P, R));
target_tileset.modelMatrix = Cesium.Matrix4.fromRotationTranslation(rotation,translation);
return zoomAll(target_tileset);
});
target_tileset.readyPromise.then(function(target_tileset){
target_tileset.style = new Cesium.Cesium3DTileStyle({
color: "color('black',0.5)",
})
});
///////////////////////////// Layer one //////////////////////////
var L1 = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: 'buildingTiles/circularTiles/L1_yellow/tileset.json',
show: true,
}));
L1.readyPromise.then(function (L1) {
return zoomAll(L1);
});
L1.readyPromise.then(function (L1) {
var R = 0; // roll
var P = 0; // pitch
var Yaw = 0; // yaw
var height = buildingHeightOffset;
var cartographic = Cesium.Cartographic.fromCartesian(L1.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
//var rotMat = new Cesium.Matrix3();
var rotation = new Cesium.Matrix3.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(Yaw, P, R));
L1.modelMatrix = Cesium.Matrix4.fromRotationTranslation(rotation,translation);
return zoomAll(L1);
});
L1.readyPromise.then(function(L1){
L1.style = new Cesium.Cesium3DTileStyle({
color: "color('yellow',1)",
})
});
///////////////////////////// Layer 2 //////////////////////////
var L2 = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: 'buildingTiles/circularTiles/L2_red/tileset.json',
show: true,
}));
L2.readyPromise.then(function (L2) {
return zoomAll(L2);
});
L2.readyPromise.then(function (L2) {
var R = 0; // roll
var P = 0; // pitch
var Yaw = 0; // yaw
var height = buildingHeightOffset;
var cartographic = Cesium.Cartographic.fromCartesian(L2.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
//var rotMat = new Cesium.Matrix3();
var rotation = new Cesium.Matrix3.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(Yaw, P, R));
L2.modelMatrix = Cesium.Matrix4.fromRotationTranslation(rotation,translation);
return zoomAll(L2);
});
L2.readyPromise.then(function(L2){
L2.style = new Cesium.Cesium3DTileStyle({
color: "color('red',1)",
})
});
///////////////////////////// Layer 3 //////////////////////////
var L3 = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: 'buildingTiles/circularTiles/L3_green/tileset.json',
show: true,
}));
L3.readyPromise.then(function (L3) {
return zoomAll(L3);
});
L3.readyPromise.then(function (L3) {
var R = 0; // roll
var P = 0; // pitch
var Yaw = 0; // yaw
var height = buildingHeightOffset;
var cartographic = Cesium.Cartographic.fromCartesian(L3.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
//var rotMat = new Cesium.Matrix3();
var rotation = new Cesium.Matrix3.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(Yaw, P, R));
L3.modelMatrix = Cesium.Matrix4.fromRotationTranslation(rotation,translation);
return zoomAll(L3);
});
L3.readyPromise.then(function(L3){
L3.style = new Cesium.Cesium3DTileStyle({
color: "color('green',1)",
})
});
///////////////////////////// Layer 3 //////////////////////////
var L4 = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: 'buildingTiles/circularTiles/L4_brown/tileset.json',
show: true,
}));
L4.readyPromise.then(function (L4) {
return zoomAll(L4);
});
L4.readyPromise.then(function (L4) {
var R = 0; // roll
var P = 0; // pitch
var Yaw = 0; // yaw
var height = buildingHeightOffset;
var cartographic = Cesium.Cartographic.fromCartesian(L4.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
//var rotMat = new Cesium.Matrix3();
var rotation = new Cesium.Matrix3.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(Yaw, P, R));
L4.modelMatrix = Cesium.Matrix4.fromRotationTranslation(rotation,translation);
return zoomAll(L4);
});
L4.readyPromise.then(function(L4){
L4.style = new Cesium.Cesium3DTileStyle({
color: "color('CORAL',1)",
})
});
var camera = viewer.camera;
var controller = scene.screenSpaceCameraController;
var r = 0;
var center = new Cesium.Cartesian3();
var hpRoll = new Cesium.HeadingPitchRoll();
var hpRange = new Cesium.HeadingPitchRange();
var speed = 0.1;
var deltaRadians = Cesium.Math.toRadians(3.0);
var position = Cesium.Cartesian3.fromDegrees(9.190471, 48.786782, 0.0);
var speedVector = new Cesium.Cartesian3();
var fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator('north', 'west');
viewer.scene.globe.enableLighting = true; // set lighting to true
var zoomAll = function (tileset) {
return new Promise(function (resolve, reject) {
if (!tileset) { reject("Tileset is undifined"); }
viewer.camera.viewBoundingSphere(tileset.boundingSphere, new Cesium.HeadingPitchRange(0, -0.5, 1500));
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
resolve();
});
}
//////////////////////////////////////////
//////////////////////////////////////////
// load streamline data from text file and parse it to polyline with multiple colors.
var pos = [];
var cols = [];
var streamID = [];
var Velocity = [];
var pt_to_pt_dist = [];
var avgVelocity = [];
function get_date_time_dt(deltaTime) {
// deltaTime should be given in SECONDS and is then converted to milliseconds
// set deltaTime to 0 if you want to get current date and time
// set to +60000 to get date and time of 60 seconds = 60000 milliseconds in the future
return (currentdate = new Date(
new Date().getTime() + deltaTime * 1000
).toISOString());
}
d3.dsv(",", "results/Kirchturm1.csv").then(function (text) {
const particleDuration = 90; // units in seconds the particle / point should take to move from start to finish
//define the czml structure
var particle_czml = [
{
id: "document",
name: "CZML Point - Time Dynamic",
version: "1.0",
clock: {
interval: get_date_time_dt(0) + "/" + get_date_time_dt(particleDuration), // This is the time range of our simulation
currentTime: '', // This is the time associated with the start view
currentTime: get_date_time_dt(0),
multiplier: 5,
// range: 'LOOP_STOP',
}
},
{
id: "point",
availability: get_date_time_dt(0) + "/" + get_date_time_dt(particleDuration),
position: {
epoch: get_date_time_dt(0),
cartographicDegrees: [
// use 4 coordinates / values : (t,x,y,z) or rather (t,lon,lat,alt)
],
//"interpolationAlgorithm": "LAGRANGE",
//"interpolationDegree": 1
},
point: {
color: {
rgba: [0, 0, 0, 250],
},
outlineColor: {
rgba: [255, 0, 0, 128],
},
outlineWidth: 1,
pixelSize: 6,
},
},
];
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
let package_time_faktor = 6.0;
// create an array of deep copies of the original czml data structure, to be modified below.
let czmlArr = [];
for (c=0; c < package_time_faktor; c++){
czmlArr.push(JSON.parse(JSON.stringify(particle_czml)));
czmlArr[c][1].id = "point_arr_" + String(c);
}
var temp = text;
for (var i = 0; i < temp.length; i++) {
// use i+=7 when parsed as d3.text(...)
pos.push([
parseFloat(text[i].x),
parseFloat(text[i].y),
parseFloat(text[i].z),
]);
cols.push([
parseInt(text[i].R),
parseInt(text[i].G),
parseInt(text[i].B),
]);
streamID.push(parseInt(text[i].ID));
Velocity.push(parseFloat(text[i].velocity));
avgVelocity.push(parseFloat(text[i].AverageVelocity));
pt_to_pt_dist.push(parseFloat(text[i].pt_to_pt_dist));
// use these lines if parsed as text. i.e. using d3.text(...)
//pos.push([parseFloat(temp[i+0]), parseFloat(temp[i+1]), parseFloat(temp[i+2])]);
//colors.push([parseFloat(temp[i+3]),parseFloat(temp[i+4]),parseFloat(temp[i+5])])
//streamID.push([parseFloat(temp[i+6])]);
}
const maxID = streamID.reduce(function (a, b) {
return Math.max(a, b);
});
//find out the unique ids within the streamID array
const uniqueStreamID = Array.from(new Set(streamID)); // const uniqueStreamID = [...new Set(streamID)]; // same can be done with spread operator
//get index of each unique id, first element of those
let sIDidx = [];
for (var i = 0; i <= maxID; i++) {
var tmpIdx = streamID.indexOf(i);
if (tmpIdx !== -1) sIDidx.push(tmpIdx);
}
/////////////////////////////////////////////////
// Create and draw a polyline with per vertex colors
/////////////////////////////////////////////////
const heightOffset = 70;
for (var line = 0; line < uniqueStreamID.length; line++) {
let positions = [];
let positionsInDegrees = [];
let colors = [];
let individual_particle_velo = [];
let individual_particle_pt_distance = [];
let individual_particle_avg_velo = [];
curr_pos = sIDidx[line];
for (i = curr_pos; i < streamID.length; ++i) {
if (line === streamID[i]){
positions.push(
Cesium.Cartesian3.fromDegrees(
pos[i][0],
pos[i][1],
pos[i][2] + heightOffset
)
);
positionsInDegrees.push([
pos[i][0],
pos[i][1],
pos[i][2] + heightOffset,
]);
colors.push(
Cesium.Color.fromBytes(cols[i][0], cols[i][1], cols[i][2], 180)
);
individual_particle_avg_velo.push(avgVelocity[i]);
individual_particle_pt_distance.push(pt_to_pt_dist[i]);
individual_particle_velo.push(Velocity[i]);
} // if end brace
}
// For per segment coloring, supply the colors option with
// an array of colors for each vertex. Also set the
// colorsPerVertex option to true.
viewer.scene.primitives.add(
new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.PolylineGeometry({
positions: positions,
width: 5.0,
vertexFormat: Cesium.PolylineColorAppearance.VERTEX_FORMAT,
colors: colors,
colorsPerVertex: true,
}),
}),
appearance: new Cesium.PolylineColorAppearance(),
})
);
////////////////////////////////////////////////
// Create and prepare particles for movement
/////////////////////////////////////////////////
let streamDist = individual_particle_pt_distance.reduce(function (a, b) {
return a + b;
}, 0);
// console.log(streamDist);
let t = 0;
let dt = (individual_particle_pt_distance[1] / individual_particle_avg_velo[0]) / 20;
// let dt = streamDist / individual_particle_avg_velo[0] / 500;
/////////////////////////////////////
var temp_pos = [];
for (i = 0; i < positionsInDegrees.length; i++) {
if (i === 0) {
temp_pos.push(
0,
positionsInDegrees[i][0],
positionsInDegrees[i][1],
positionsInDegrees[i][2]
);
} else {
temp_pos.push(
t,
positionsInDegrees[i][0],
positionsInDegrees[i][1],
positionsInDegrees[i][2]
);
dt = individual_particle_pt_distance[i] /individual_particle_avg_velo[0] / 20; // avg_velo is always the same per streamline
// console.log(individual_particle_pt_distance[i] + "/" + individual_particle_avg_velo[i] );
// console.log(dt);
}
t += dt;
}
particle_czml[1].id = "point" + String(line);
particle_czml[1].position.cartographicDegrees = temp_pos;
viewer.dataSources.add(Cesium.CzmlDataSource.load(particle_czml));
////////////////////////////////////////////////
dt = (individual_particle_pt_distance[1] / individual_particle_avg_velo[0]) / 20;
for (c=0; c < czmlArr.length ; c++){
temp_pos = [];
for (i = 0; i < positionsInDegrees.length; i++) {
if (i === 0) {
temp_pos.push(
t,
positionsInDegrees[i][0],
positionsInDegrees[i][1],
positionsInDegrees[i][2]
);
} else {
temp_pos.push(
t,
positionsInDegrees[i][0],
positionsInDegrees[i][1],
positionsInDegrees[i][2]
);
dt = individual_particle_pt_distance[i] /individual_particle_avg_velo[0] / 20;
// console.log(individual_particle_pt_distance[i] + "/" + individual_particle_avg_velo[i] );
// console.log(dt);
}
t += dt;
}
czmlArr[c][1].position.cartographicDegrees = temp_pos;
czmlArr[c][1].id = "point_set_" + String(c) + "_" + String(line);
czmlArr[c][1].position.epoch = get_date_time_dt(0);
viewer.dataSources.add(Cesium.CzmlDataSource.load(czmlArr[c]));
}
} // end bracket for: for (var line = 0; line < uniqueStreamID.length; line++) {
}); // end bracket for: d3.dsv(...).then(...
// HTML overlay for showing feature name on mouseover
var nameOverlay = document.createElement('div');
viewer.container.appendChild(nameOverlay);
nameOverlay.className = 'backdrop';
nameOverlay.style.display = 'none';
nameOverlay.style.position = 'absolute';
nameOverlay.style.bottom = '0';
nameOverlay.style.left = '0';
nameOverlay.style['pointer-events'] = 'none';
nameOverlay.style.padding = '4px';
nameOverlay.style.backgroundColor = 'green';
// Information about the currently selected feature
var selected = {
feature: undefined,
originalColor: new Cesium.Color()
};
// Information about the currently highlighted feature
var highlighted = {
feature: undefined,
originalColor: new Cesium.Color()
};
var selectedEntity = new Cesium.Entity();
// Color a feature yellow on hover.
viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
// 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 pickedFeature = viewer.scene.pick(movement.endPosition);
if (!Cesium.defined(pickedFeature)) {
nameOverlay.style.display = 'none';
return;
}
// A feature was picked, so show it's overlay content
nameOverlay.style.display = 'block';
nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + 'px';
nameOverlay.style.left = movement.endPosition.x + 'px';
var name = pickedFeature.getProperty('name');
if (!Cesium.defined(name)) {
name = pickedFeature.getProperty('id');
}
nameOverlay.textContent = name;
// Highlight the feature if it's not already selected.
if (pickedFeature !== selected.feature) {
highlighted.feature = pickedFeature;
Cesium.Color.clone(pickedFeature.color, highlighted.originalColor);
pickedFeature.color = Cesium.Color.AQUA;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// Color a feature on selection and show metadata in the InfoBox.
var clickHandler = viewer.screenSpaceEventHandler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
// If a feature was previously selected, undo the highlight
if (Cesium.defined(selected.feature)) {
selected.feature.color = selected.originalColor;
selected.feature = undefined;
}
// Pick a new feature
var pickedFeature = viewer.scene.pick(movement.position);
if (!Cesium.defined(pickedFeature)) {
clickHandler(movement);
return;
}
// Select the feature if it's not already selected
if (selected.feature === pickedFeature) {
return;
}
selected.feature = pickedFeature;
// Save the selected feature's original color
if (pickedFeature === highlighted.feature) {
Cesium.Color.clone(highlighted.originalColor, selected.originalColor);
highlighted.feature = undefined;
} else {
Cesium.Color.clone(pickedFeature.color, selected.originalColor);
}
// Highlight newly selected feature
pickedFeature.color = Cesium.Color.WHITE;
// Set feature infobox description
var featureName = pickedFeature.getProperty('name');
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>Bld function</th><td>' + pickedFeature.getProperty('Function') + '</td></tr>' +
'<tr><th>gmlID</th><td>' + pickedFeature.getProperty('gmlIDStr') + '</td></tr>' +
'<tr><th>Dachgeschossausbau</th><td>' + pickedFeature.getProperty('dachgeschossausbau') + '</td></tr>' +
'<tr><th>Lon</th><td>' + pickedFeature.getProperty('Longitude') + '</td></tr>' +
'<tr><th>Lat</th><td>' + pickedFeature.getProperty('Latitude') + '</td></tr>' +
'<tr><th>Geschossflaeche (sqm)</th><td>' + pickedFeature.getProperty('geschossflaeche') + '</td></tr>' +
'<tr><th>YearOfConstruction</th><td>' + pickedFeature.getProperty('YearOfConstruction') + '</td></tr>' +
'<tr><th>MeasuredHeight (m):</th><td>' + pickedFeature.getProperty('MeasuredHeight') + '</td></tr>' +
'<tr><th>HoeheFirst (m)</th><td>' + pickedFeature.getProperty('hoeheFirst') + '</td></tr>' +
'<tr><th>HoeheTrauf (m)</th><td>' + pickedFeature.getProperty('hoeheTrauf') + '</td></tr>' +
'<tr><th>Grundflaeche (sqm)</th><td>' + pickedFeature.getProperty('grundflaeche') + '</td></tr>' +
'<tr><th>StoreysAboveGround: </th><td>' + pickedFeature.getProperty('StoreysAboveGround') + '</td></tr>' +
'<tr><th>StoreysBelowGround: </th><td>' + pickedFeature.getProperty('StoreysBelowGround') + '</td></tr>' +
'<tr><th>Durchfahrtsstr.: </th><td>' + pickedFeature.getProperty('ThoroughfareName') + '</td></tr>' +
'<tr><th>Hausnummer.: </th><td>' + pickedFeature.getProperty('ThoroughfareNumber') + '</td></tr>' +
'</tbody></table>';
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
var scene = viewer.scene;
var longitude;
var latitude;
var fid;
var featuretype;
var gmlid;
var selID = new Array();
var cnt = 0;
var lastPickedObject;
var viewModel = {
rightClickAction: 'properties',
middleClickAction: 'hide'
};
Cesium.knockout.track(viewModel);
var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function (movement) {
// makes camera go to a certain position given by the coordinates below
var feature = viewer.scene.pick(movement.position);
if (!Cesium.defined(feature)) {
console.log("no feature defined")
return;
}
var propertyNames = feature.getPropertyNames();
var lat = feature.getProperty("Latitude");
var lon = feature.getProperty("Longitude");
var tmp = feature.getProperty("YearOfConstruction");
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(lon, lat, 900),
maximumHeight: 1500.0,
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(45.0)
},
duration: 2
}); }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(function (movement) {
var feature = viewer.scene.pick(movement.position);
if (!Cesium.defined(feature)) {
return;
}
var action = viewModel.rightClickAction;
action === 'properties'
printProperties(movement, feature)
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
function printProperties(movement, feature) {
console.log('Properties:');
var propertyNames = feature.getPropertyNames();
var length = propertyNames.length;
for (var i = 0; i < length; ++i) {
var propertyName = propertyNames[i];
if (propertyName == 'gmlIdALKISLageBezeichnung_1' ||
propertyName == 'gmlIdALKISLageBezeichnung_2' ||
propertyName == 'gmlIdALKISLageBezeichnung_3' ||
propertyName == 'gmlIdALKISLageBezeichnung_4' ||
propertyName == 'gmlIdALKISLageBezeichnung_5' ||
propertyName == 'gmlIdALKISLageBezeichnung_6')
console.log(' ' + propertyName + ': ' + 'zensiert');
else
console.log(' ' + propertyName + ': ' + feature.getProperty(propertyName));
}
// Evaluate feature description
//console.log('Description : ' + tileset.style.meta.description.evaluate(scene.frameState, feature));
}
handler.setInputAction(function (movement) {
var feature = viewer.scene.pick(movement.position);
if (!Cesium.defined(feature)) {
return;
}
var action = viewModel.middleClickAction;
if (action === 'hide') {
feature.show = false;
}
}, Cesium.ScreenSpaceEventType.MIDDLE_CLICK);
/*
return Cesium.when(tileset.readyPromise).then(function (tileset) {
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["${Latitude} >= 48.8170", "color('purple', 0.5)"],
["${Latitude} >= 48.7950", "color('red')"],
["${Latitude} >= 48.7830", "color('orange')"],
["${Latitude} >= 48.7710", "color('yellow')"],
["${Latitude} >= 48.7690", "color('lime')"],
["${Latitude} >= 48.7570", "color('cyan')"],
["${Latitude} >= 48.7470", "color('CORNFLOWERBLUE')"],
["${Latitude} >= 48.7370", "color('DARKMAGENTA')"],
["true", "color('lightblue')"]
]
}
});
});
*/
function showLegend() {
$("#legend").css("display", "block");
}
function hideLegend() {
$("#legend").css("display", "none");
}
// Legend - Colour Table
function emptyColourTable() {
$(".inner").empty();
}
/*
function setHeightTable() {
$(".inner").append( "<table>" +
"<tr><td class='outlined' bgcolor='red'>&nbsp;&nbsp;&nbsp;&nbsp;</td><td> 113007 </td></tr>" +
"<tr><td class='outlined' bgcolor='#ff6b21'></td><td> 113001 </td></tr>" +
"<tr><td class='outlined' bgcolor='#ffb400'></td><td> 112996 </td></tr>" +
"<tr><td class='outlined' bgcolor='yellow'></td><td> 112991</td></tr>" +
"<tr><td class='outlined' bgcolor='#00ff00'></td><td> 112986 </td></tr>" +
"<tr><td class='outlined' bgcolor='cyan'></td><td> 112981 </td></tr>" +
"<tr><td class='outlined' bgcolor='blue'></td><td> 112976 </td></tr>" +
"</table>" );
}
*/
/*
function setHeightTable() {
$(".inner").append( "<table>" +
"<tr><td class='outlined' bgcolor='red'>&nbsp;&nbsp;&nbsp;&nbsp;</td><td> x </td></tr>" +
"<tr><td class='outlined' bgcolor='green'></td><td> y </td></tr>" +
"<tr><td class='outlined' bgcolor='blue'></td><td> z </td></tr>" +
"</table>" );
}
*/
function setHeightTable() {
$(".inner").append( "<table>" +
"<tr><td class='outlined' bgcolor='red'>&nbsp;&nbsp;&nbsp;&nbsp;</td><td> >30 </td></tr>" +
"<tr><td class='outlined' bgcolor='#ff6b21'></td><td> 24 </td></tr>" +
"<tr><td class='outlined' bgcolor='#FFB300'></td><td> 18</td></tr>" +
"<tr><td class='outlined' bgcolor='#BFBF00'></td><td> 12 </td></tr>" +
"<tr><td class='outlined' bgcolor='#0080FF',0)'></td><td> 6 </td></tr>" +
"<tr><td class='outlined' bgcolor='#0000FF',0)'></td><td> 0 </td></tr>" +
"</table>" );
}
// return Cesium.when(target_tileset.readyPromise).then(function (target_tileset) {
// target_tileset.style = new Cesium.Cesium3DTileStyle({
// color: "color('black',1)",
// /*color: {
// conditions: [
// ['Number(${MeasuredHeight}) >= 40', 'rgb(255,0,0)'],
// ['Number(${MeasuredHeight}) >= 30.', 'rgb(255, 93 , 0)'],
// ['Number(${MeasuredHeight}) >= 25', 'rgb(255, 180, 0)'],
// ['Number(${MeasuredHeight}) >= 20', 'rgb(255,255,0)'],
// ['Number(${MeasuredHeight}) >= 15', 'rgb(0,255,0)'],
// ['Number(${MeasuredHeight}) >= 10', 'rgb(0,0,255)'],
// ['Number(${MeasuredHeight}) >= 7.5', 'rgb(75, 0, 130)'],
// ['Number(${MeasuredHeight}) >= 4', 'rgb(248, 100, 221)'],
// ['Number(${MeasuredHeight}) >= 0.1', 'rgb(248, 100, 221)'],
// ['true', 'color("lightblue")']
// ]
// }
// */
// });
// showLegend();
// setHeightTable();
// });
/*
return Cesium.when(tileset.readyPromise).then(function (tileset) {
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
['Number(${YearOfConstruction}) >= 2015', 'rgb(127,201,127)'],
['Number(${YearOfConstruction}) >= 2005', 'rgb(190,174,212)'],
['Number(${YearOfConstruction}) >= 1990', 'rgb(253,192,134)'],
['Number(${YearOfConstruction}) >= 1975', 'rgb(255,255,153)'],
['Number(${YearOfConstruction}) >= 1950', 'rgb(56,108,176)'],
['Number(${YearOfConstruction}) >= 1920', 'rgb(240,2,127)'],
['Number(${YearOfConstruction}) >= 1900', 'rgb(191,91,23)'],
['Number(${YearOfConstruction}) >= 1800', 'rgb(102,102,102)'],
['true', 'color("lightblue")']
]
}
});
}); */
});
\ No newline at end of file
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->
<head>
<meta charset="utf-8">
<title>Stuttgart</title>
<link rel="stylesheet" href="css/myCesiumStyle.css">
<link rel="stylesheet" href="css/legend.css">
<link href="https://cesium.com/downloads/cesiumjs/releases/1.69/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"
integrity="sha256-1A78rJEdiWTzco6qdn3igTBv9VupN3Q1ozZNTR4WE/Y=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"
integrity="sha256-0rguYS0qgS6L4qVzANq4kjxPLtvnp5nn2nB5G1lWRv4=" crossorigin="anonymous"></script>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.69/Build/Cesium/Cesium.js"></script>
<script src="https://d3js.org/d3-dsv.v1.min.js"></script>
<script src="https://d3js.org/d3-fetch.v1.min.js"></script>
</head>
<body>
<header>
<img src="imgs/icity.png" class="titleFigure">
<h2> TP2.4 - Prototyp 5: Webbasierte Visualisierung von CFD Simulationsdaten </h2>
</header>
<script src="Kirchturm2.js"></script>
<div id="cesiumContainer" class="pagecesium">
<div id="legend">
<table>
<tr style="height: 30px;vertical-align: top;">
<td colspan="2">Wind speed (m/s) </td>
<td></td>
</tr>
<tr>
<td rowspan="1" style="height:100px;text-align:right;"><img src="imgs/colorbarJET.png" height="100"
width="20"> </td>
<td>- 3.5<p style="margin-top: 78px;">
<p> - 0
</td>
</tr>
</table>
</div>
</div>
<footer>
<p align="center">
<h5>Copyright &copy; 2018 - 2020, HFT-Stuttgart. All rights reserved</h5>
</p>
</footer>
</body>
</html>
\ No newline at end of file
$(function () {
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5ODI4ZTYyZS1mMTg2LTQ5NGEtYjdiOS02ODg2NzVhNjc0MTAiLCJpZCI6MjkwNCwiaWF0IjoxNTM1MTA5OTAzfQ.kyDX_0ScvJBkYnvXI0DW5NfZbiaRL5ezwtAUhxYnk1Y';
var imageryViewModels = [];
imageryViewModels.push(new Cesium.ProviderViewModel({
name: 'Sentinel-2',
iconUrl: Cesium.buildModuleUrl('Widgets/Images/ImageryProviders/sentinel-2.png'),
tooltip: 'Sentinel-2 cloudless.',
creationFunction: function () {
return new Cesium.IonImageryProvider({ assetId: 3954 });
}
}));
imageryViewModels.push(new Cesium.ProviderViewModel({
name: 'Blue Marble',
iconUrl: Cesium.buildModuleUrl('Widgets/Images/ImageryProviders/blueMarble.png'),
tooltip: 'Blue Marble Next Generation July, 2004 imagery from NASA.',
creationFunction: function () {
return new Cesium.IonImageryProvider({ assetId: 3845 });
}
}));
var viewer = new Cesium.Viewer('cesiumContainer',
{
imageryProvider: new Cesium.IonImageryProvider({ assetId: 3954 }),
terrainProvider : new Cesium.CesiumTerrainProvider({
url: Cesium.IonResource.fromAssetId(1)
}),
scene3DOnly: false,
shouldAnimate: true,
animation: true,
infoBox: true,
baseLayerPicker: true,
fullscreenButton: false,
timeline: false,
navigationHelpButton: true,
navigationInstructionsInitiallyVisible: false,
homeButton: false,
selectionIndicator: true,
geocoder: true,
// imageryProviderViewModels: imageryViewModels
});
var layer = viewer.imageryLayers.addImageryProvider(
new Cesium.IonImageryProvider({ assetId: 2 })
);
// var imageryLayer = viewer.imageryLayers.addImageryProvider(
// new Cesium.IonImageryProvider({ assetId: 3954 })
// );
var canvas = viewer.canvas;
canvas.setAttribute('tabindex', '0'); // needed to put focus on the canvas
canvas.addEventListener('click', function() {
canvas.focus();
});
canvas.focus();
var scene = viewer.scene;
var osmBuildings = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: Cesium.IonResource.fromAssetId(96188),
})
);
const buildingHeightOffset = 60; //53
///////////////////// STOECKACH LOD 1
// var stoeckach = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
// url: 'buildingTiles/StoeckachLOD1/tileset.json',
// show: true
// }));
// stoeckach.readyPromise.then(function (stoeckach) {
// var R = 0; // roll
// var P = 0; // pitch
// var Yaw = 0; // yaw
// var height = buildingHeightOffset;
// var cartographic = Cesium.Cartographic.fromCartesian(stoeckach.boundingSphere.center);
// var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
// var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
// var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
// //var rotMat = new Cesium.Matrix3();
// var rotation = new Cesium.Matrix3.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(Yaw, P, R));
// stoeckach.modelMatrix = Cesium.Matrix4.fromRotationTranslation(rotation,translation);
// return zoomAll(stoeckach);
// });
// stoeckach.readyPromise.then(function(stoeckach){
// stoeckach.style = new Cesium.Cesium3DTileStyle({
// color: "color('white',0.5)",
// })
// });
///////////////////////////// Target //////////////////////////
var target_tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: 'buildingTiles/circularTiles/target_black/tileset.json',
show: true
}));
target_tileset.readyPromise.then(function (target_tileset) {
var R = 0; // roll
var P = 0; // pitch
var Yaw = 0; // yaw
var height = buildingHeightOffset;
var cartographic = Cesium.Cartographic.fromCartesian(target_tileset.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
//var rotMat = new Cesium.Matrix3();
var rotation = new Cesium.Matrix3.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(Yaw, P, R));
target_tileset.modelMatrix = Cesium.Matrix4.fromRotationTranslation(rotation,translation);
return zoomAll(target_tileset);
});
target_tileset.readyPromise.then(function(target_tileset){
target_tileset.style = new Cesium.Cesium3DTileStyle({
color: "color('black',0.5)",
})
});
///////////////////////////// Layer one //////////////////////////
var L1 = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: 'buildingTiles/circularTiles/L1_yellow/tileset.json',
show: true,
}));
L1.readyPromise.then(function (L1) {
return zoomAll(L1);
});
L1.readyPromise.then(function (L1) {
var R = 0; // roll
var P = 0; // pitch
var Yaw = 0; // yaw
var height = buildingHeightOffset;
var cartographic = Cesium.Cartographic.fromCartesian(L1.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
//var rotMat = new Cesium.Matrix3();
var rotation = new Cesium.Matrix3.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(Yaw, P, R));
L1.modelMatrix = Cesium.Matrix4.fromRotationTranslation(rotation,translation);
return zoomAll(L1);
});
L1.readyPromise.then(function(L1){
L1.style = new Cesium.Cesium3DTileStyle({
color: "color('yellow',1)",
})
});
///////////////////////////// Layer 2 //////////////////////////
var L2 = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: 'buildingTiles/circularTiles/L2_red/tileset.json',
show: true,
}));
L2.readyPromise.then(function (L2) {
return zoomAll(L2);
});
L2.readyPromise.then(function (L2) {
var R = 0; // roll
var P = 0; // pitch
var Yaw = 0; // yaw
var height = buildingHeightOffset;
var cartographic = Cesium.Cartographic.fromCartesian(L2.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
//var rotMat = new Cesium.Matrix3();
var rotation = new Cesium.Matrix3.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(Yaw, P, R));
L2.modelMatrix = Cesium.Matrix4.fromRotationTranslation(rotation,translation);
return zoomAll(L2);
});
L2.readyPromise.then(function(L2){
L2.style = new Cesium.Cesium3DTileStyle({
color: "color('red',1)",
})
});
///////////////////////////// Layer 3 //////////////////////////
var L3 = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: 'buildingTiles/circularTiles/L3_green/tileset.json',
show: true,
}));
L3.readyPromise.then(function (L3) {
return zoomAll(L3);
});
L3.readyPromise.then(function (L3) {
var R = 0; // roll
var P = 0; // pitch
var Yaw = 0; // yaw
var height = buildingHeightOffset;
var cartographic = Cesium.Cartographic.fromCartesian(L3.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
//var rotMat = new Cesium.Matrix3();
var rotation = new Cesium.Matrix3.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(Yaw, P, R));
L3.modelMatrix = Cesium.Matrix4.fromRotationTranslation(rotation,translation);
return zoomAll(L3);
});
L3.readyPromise.then(function(L3){
L3.style = new Cesium.Cesium3DTileStyle({
color: "color('green',1)",
})
});
///////////////////////////// Layer 3 //////////////////////////
var L4 = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: 'buildingTiles/circularTiles/L4_brown/tileset.json',
show: true,
}));
L4.readyPromise.then(function (L4) {
return zoomAll(L4);
});
L4.readyPromise.then(function (L4) {
var R = 0; // roll
var P = 0; // pitch
var Yaw = 0; // yaw
var height = buildingHeightOffset;
var cartographic = Cesium.Cartographic.fromCartesian(L4.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
//var rotMat = new Cesium.Matrix3();
var rotation = new Cesium.Matrix3.fromHeadingPitchRoll(new Cesium.HeadingPitchRoll(Yaw, P, R));
L4.modelMatrix = Cesium.Matrix4.fromRotationTranslation(rotation,translation);
return zoomAll(L4);
});
L4.readyPromise.then(function(L4){
L4.style = new Cesium.Cesium3DTileStyle({
color: "color('CORAL',1)",
})
});
var camera = viewer.camera;
var controller = scene.screenSpaceCameraController;
var r = 0;
var center = new Cesium.Cartesian3();
var hpRoll = new Cesium.HeadingPitchRoll();
var hpRange = new Cesium.HeadingPitchRange();
var speed = 0.1;
var deltaRadians = Cesium.Math.toRadians(3.0);
var position = Cesium.Cartesian3.fromDegrees(9.190471, 48.786782, 0.0);
var speedVector = new Cesium.Cartesian3();
var fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator('north', 'west');
viewer.scene.globe.enableLighting = true; // set lighting to true
var zoomAll = function (tileset) {
return new Promise(function (resolve, reject) {
if (!tileset) { reject("Tileset is undifined"); }
viewer.camera.viewBoundingSphere(tileset.boundingSphere, new Cesium.HeadingPitchRange(0, -0.5, 1500));
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
resolve();
});
}
//////////////////////////////////////////
//////////////////////////////////////////
// load streamline data from text file and parse it to polyline with multiple colors.
var pos = [];
var cols = [];
var streamID = [];
var Velocity = [];
var pt_to_pt_dist = [];
var avgVelocity = [];
function get_date_time_dt(deltaTime) {
// deltaTime should be given in SECONDS and is then converted to milliseconds
// set deltaTime to 0 if you want to get current date and time
// set to +60000 to get date and time of 60 seconds = 60000 milliseconds in the future
return (currentdate = new Date(
new Date().getTime() + deltaTime * 1000
).toISOString());
}
d3.dsv(",", "results/Kirchturm2.csv").then(function (text) {
const particleDuration = 70; // units in seconds the particle / point should take to move from start to finish
//define the czml structure
var particle_czml = [
{
id: "document",
name: "CZML Point - Time Dynamic",
version: "1.0",
clock: {
interval: get_date_time_dt(0) + "/" + get_date_time_dt(particleDuration), // This is the time range of our simulation
currentTime: '', // This is the time associated with the start view
currentTime: get_date_time_dt(0),
multiplier: 5,
// range: 'LOOP_STOP',
}
},
{
id: "point",
availability: get_date_time_dt(0) + "/" + get_date_time_dt(particleDuration),
position: {
epoch: get_date_time_dt(0),
cartographicDegrees: [
// use 4 coordinates / values : (t,x,y,z) or rather (t,lon,lat,alt)
],
//"interpolationAlgorithm": "LAGRANGE",
//"interpolationDegree": 1
},
point: {
color: {
rgba: [0, 0, 0, 250],
},
outlineColor: {
rgba: [255, 0, 0, 128],
},
outlineWidth: 1,
pixelSize: 6,
},
},
];
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
let package_time_faktor = 6.0;
// create an array of deep copies of the original czml data structure, to be modified below.
let czmlArr = [];
for (c=0; c < package_time_faktor; c++){
czmlArr.push(JSON.parse(JSON.stringify(particle_czml)));
czmlArr[c][1].id = "point_arr_" + String(c);
}
var temp = text;
for (var i = 0; i < temp.length; i++) {
// use i+=7 when parsed as d3.text(...)
pos.push([
parseFloat(text[i].x),
parseFloat(text[i].y),
parseFloat(text[i].z),
]);
cols.push([
parseInt(text[i].R),
parseInt(text[i].G),
parseInt(text[i].B),
]);
streamID.push(parseInt(text[i].ID));
Velocity.push(parseFloat(text[i].velocity));
avgVelocity.push(parseFloat(text[i].AverageVelocity));
pt_to_pt_dist.push(parseFloat(text[i].pt_to_pt_dist));
// use these lines if parsed as text. i.e. using d3.text(...)
//pos.push([parseFloat(temp[i+0]), parseFloat(temp[i+1]), parseFloat(temp[i+2])]);
//colors.push([parseFloat(temp[i+3]),parseFloat(temp[i+4]),parseFloat(temp[i+5])])
//streamID.push([parseFloat(temp[i+6])]);
}
const maxID = streamID.reduce(function (a, b) {
return Math.max(a, b);
});
//find out the unique ids within the streamID array
const uniqueStreamID = Array.from(new Set(streamID)); // const uniqueStreamID = [...new Set(streamID)]; // same can be done with spread operator
//get index of each unique id, first element of those
let sIDidx = [];
for (var i = 0; i <= maxID; i++) {
var tmpIdx = streamID.indexOf(i);
if (tmpIdx !== -1) sIDidx.push(tmpIdx);
}
/////////////////////////////////////////////////
// Create and draw a polyline with per vertex colors
/////////////////////////////////////////////////
const heightOffset = 70;
for (var line = 0; line < uniqueStreamID.length; line++) {
let positions = [];
let positionsInDegrees = [];
let colors = [];
let individual_particle_velo = [];
let individual_particle_pt_distance = [];
let individual_particle_avg_velo = [];
curr_pos = sIDidx[line];
for (i = curr_pos; i < streamID.length; ++i) {
if (line === streamID[i]){
positions.push(
Cesium.Cartesian3.fromDegrees(
pos[i][0],
pos[i][1],
pos[i][2] + heightOffset
)
);
positionsInDegrees.push([
pos[i][0],
pos[i][1],
pos[i][2] + heightOffset,
]);
colors.push(
Cesium.Color.fromBytes(cols[i][0], cols[i][1], cols[i][2], 180)
);
individual_particle_avg_velo.push(avgVelocity[i]);
individual_particle_pt_distance.push(pt_to_pt_dist[i]);
individual_particle_velo.push(Velocity[i]);
} // if end brace
}
// For per segment coloring, supply the colors option with
// an array of colors for each vertex. Also set the
// colorsPerVertex option to true.
viewer.scene.primitives.add(
new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.PolylineGeometry({
positions: positions,
width: 5.0,
vertexFormat: Cesium.PolylineColorAppearance.VERTEX_FORMAT,
colors: colors,
colorsPerVertex: true,
}),
}),
appearance: new Cesium.PolylineColorAppearance(),
})
);
////////////////////////////////////////////////
// Create and prepare particles for movement
/////////////////////////////////////////////////
let streamDist = individual_particle_pt_distance.reduce(function (a, b) {
return a + b;
}, 0);
// console.log(streamDist);
let t = 0;
let dt = (individual_particle_pt_distance[1] / individual_particle_avg_velo[0]) / 20;
// let dt = streamDist / individual_particle_avg_velo[0] / 500;
/////////////////////////////////////
var temp_pos = [];
for (i = 0; i < positionsInDegrees.length; i++) {
if (i === 0) {
temp_pos.push(
0,
positionsInDegrees[i][0],
positionsInDegrees[i][1],
positionsInDegrees[i][2]
);
} else {
temp_pos.push(
t,
positionsInDegrees[i][0],
positionsInDegrees[i][1],
positionsInDegrees[i][2]
);
dt = individual_particle_pt_distance[i] /individual_particle_avg_velo[0] / 20; // avg_velo is always the same per streamline
// console.log(individual_particle_pt_distance[i] + "/" + individual_particle_avg_velo[i] );
// console.log(dt);
}
t += dt;
}
particle_czml[1].id = "point" + String(line);
particle_czml[1].position.cartographicDegrees = temp_pos;
viewer.dataSources.add(Cesium.CzmlDataSource.load(particle_czml));
////////////////////////////////////////////////
dt = (individual_particle_pt_distance[1] / individual_particle_avg_velo[0]) / 20;
for (c=0; c < czmlArr.length ; c++){
temp_pos = [];
for (i = 0; i < positionsInDegrees.length; i++) {
if (i === 0) {
temp_pos.push(
t,
positionsInDegrees[i][0],
positionsInDegrees[i][1],
positionsInDegrees[i][2]
);
} else {
temp_pos.push(
t,
positionsInDegrees[i][0],
positionsInDegrees[i][1],
positionsInDegrees[i][2]
);
dt = individual_particle_pt_distance[i] /individual_particle_avg_velo[0] / 20;
// console.log(individual_particle_pt_distance[i] + "/" + individual_particle_avg_velo[i] );
// console.log(dt);
}
t += dt;
}
czmlArr[c][1].position.cartographicDegrees = temp_pos;
czmlArr[c][1].id = "point_set_" + String(c) + "_" + String(line);
czmlArr[c][1].position.epoch = get_date_time_dt(0);
viewer.dataSources.add(Cesium.CzmlDataSource.load(czmlArr[c]));
}
} // end bracket for: for (var line = 0; line < uniqueStreamID.length; line++) {
}); // end bracket for: d3.dsv(...).then(...
// HTML overlay for showing feature name on mouseover
var nameOverlay = document.createElement('div');
viewer.container.appendChild(nameOverlay);
nameOverlay.className = 'backdrop';
nameOverlay.style.display = 'none';
nameOverlay.style.position = 'absolute';
nameOverlay.style.bottom = '0';
nameOverlay.style.left = '0';
nameOverlay.style['pointer-events'] = 'none';
nameOverlay.style.padding = '4px';
nameOverlay.style.backgroundColor = 'green';
// Information about the currently selected feature
var selected = {
feature: undefined,
originalColor: new Cesium.Color()
};
// Information about the currently highlighted feature
var highlighted = {
feature: undefined,
originalColor: new Cesium.Color()
};
var selectedEntity = new Cesium.Entity();
// Color a feature yellow on hover.
viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
// 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 pickedFeature = viewer.scene.pick(movement.endPosition);
if (!Cesium.defined(pickedFeature)) {
nameOverlay.style.display = 'none';
return;
}
// A feature was picked, so show it's overlay content
nameOverlay.style.display = 'block';
nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + 'px';
nameOverlay.style.left = movement.endPosition.x + 'px';
var name = pickedFeature.getProperty('name');
if (!Cesium.defined(name)) {
name = pickedFeature.getProperty('id');
}
nameOverlay.textContent = name;
// Highlight the feature if it's not already selected.
if (pickedFeature !== selected.feature) {
highlighted.feature = pickedFeature;
Cesium.Color.clone(pickedFeature.color, highlighted.originalColor);
pickedFeature.color = Cesium.Color.AQUA;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// Color a feature on selection and show metadata in the InfoBox.
var clickHandler = viewer.screenSpaceEventHandler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
// If a feature was previously selected, undo the highlight
if (Cesium.defined(selected.feature)) {
selected.feature.color = selected.originalColor;
selected.feature = undefined;
}
// Pick a new feature
var pickedFeature = viewer.scene.pick(movement.position);
if (!Cesium.defined(pickedFeature)) {
clickHandler(movement);
return;
}
// Select the feature if it's not already selected
if (selected.feature === pickedFeature) {
return;
}
selected.feature = pickedFeature;
// Save the selected feature's original color
if (pickedFeature === highlighted.feature) {
Cesium.Color.clone(highlighted.originalColor, selected.originalColor);
highlighted.feature = undefined;
} else {
Cesium.Color.clone(pickedFeature.color, selected.originalColor);
}
// Highlight newly selected feature
pickedFeature.color = Cesium.Color.WHITE;
// Set feature infobox description
var featureName = pickedFeature.getProperty('name');
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>Bld function</th><td>' + pickedFeature.getProperty('Function') + '</td></tr>' +
'<tr><th>gmlID</th><td>' + pickedFeature.getProperty('gmlIDStr') + '</td></tr>' +
'<tr><th>Dachgeschossausbau</th><td>' + pickedFeature.getProperty('dachgeschossausbau') + '</td></tr>' +
'<tr><th>Lon</th><td>' + pickedFeature.getProperty('Longitude') + '</td></tr>' +
'<tr><th>Lat</th><td>' + pickedFeature.getProperty('Latitude') + '</td></tr>' +
'<tr><th>Geschossflaeche (sqm)</th><td>' + pickedFeature.getProperty('geschossflaeche') + '</td></tr>' +
'<tr><th>YearOfConstruction</th><td>' + pickedFeature.getProperty('YearOfConstruction') + '</td></tr>' +
'<tr><th>MeasuredHeight (m):</th><td>' + pickedFeature.getProperty('MeasuredHeight') + '</td></tr>' +
'<tr><th>HoeheFirst (m)</th><td>' + pickedFeature.getProperty('hoeheFirst') + '</td></tr>' +
'<tr><th>HoeheTrauf (m)</th><td>' + pickedFeature.getProperty('hoeheTrauf') + '</td></tr>' +
'<tr><th>Grundflaeche (sqm)</th><td>' + pickedFeature.getProperty('grundflaeche') + '</td></tr>' +
'<tr><th>StoreysAboveGround: </th><td>' + pickedFeature.getProperty('StoreysAboveGround') + '</td></tr>' +
'<tr><th>StoreysBelowGround: </th><td>' + pickedFeature.getProperty('StoreysBelowGround') + '</td></tr>' +
'<tr><th>Durchfahrtsstr.: </th><td>' + pickedFeature.getProperty('ThoroughfareName') + '</td></tr>' +
'<tr><th>Hausnummer.: </th><td>' + pickedFeature.getProperty('ThoroughfareNumber') + '</td></tr>' +
'</tbody></table>';
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
var scene = viewer.scene;
var longitude;
var latitude;
var fid;
var featuretype;
var gmlid;
var selID = new Array();
var cnt = 0;
var lastPickedObject;
var viewModel = {
rightClickAction: 'properties',
middleClickAction: 'hide'
};
Cesium.knockout.track(viewModel);
var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function (movement) {
// makes camera go to a certain position given by the coordinates below
var feature = viewer.scene.pick(movement.position);
if (!Cesium.defined(feature)) {
console.log("no feature defined")
return;
}
var propertyNames = feature.getPropertyNames();
var lat = feature.getProperty("Latitude");
var lon = feature.getProperty("Longitude");
var tmp = feature.getProperty("YearOfConstruction");
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(lon, lat, 900),
maximumHeight: 1500.0,
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(45.0)
},
duration: 2
}); }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(function (movement) {
var feature = viewer.scene.pick(movement.position);
if (!Cesium.defined(feature)) {
return;
}
var action = viewModel.rightClickAction;
action === 'properties'
printProperties(movement, feature)
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
function printProperties(movement, feature) {
console.log('Properties:');
var propertyNames = feature.getPropertyNames();
var length = propertyNames.length;
for (var i = 0; i < length; ++i) {
var propertyName = propertyNames[i];
if (propertyName == 'gmlIdALKISLageBezeichnung_1' ||
propertyName == 'gmlIdALKISLageBezeichnung_2' ||
propertyName == 'gmlIdALKISLageBezeichnung_3' ||
propertyName == 'gmlIdALKISLageBezeichnung_4' ||
propertyName == 'gmlIdALKISLageBezeichnung_5' ||
propertyName == 'gmlIdALKISLageBezeichnung_6')
console.log(' ' + propertyName + ': ' + 'zensiert');
else
console.log(' ' + propertyName + ': ' + feature.getProperty(propertyName));
}
// Evaluate feature description
//console.log('Description : ' + tileset.style.meta.description.evaluate(scene.frameState, feature));
}
handler.setInputAction(function (movement) {
var feature = viewer.scene.pick(movement.position);
if (!Cesium.defined(feature)) {
return;
}
var action = viewModel.middleClickAction;
if (action === 'hide') {
feature.show = false;
}
}, Cesium.ScreenSpaceEventType.MIDDLE_CLICK);
/*
return Cesium.when(tileset.readyPromise).then(function (tileset) {
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["${Latitude} >= 48.8170", "color('purple', 0.5)"],
["${Latitude} >= 48.7950", "color('red')"],
["${Latitude} >= 48.7830", "color('orange')"],
["${Latitude} >= 48.7710", "color('yellow')"],
["${Latitude} >= 48.7690", "color('lime')"],
["${Latitude} >= 48.7570", "color('cyan')"],
["${Latitude} >= 48.7470", "color('CORNFLOWERBLUE')"],
["${Latitude} >= 48.7370", "color('DARKMAGENTA')"],
["true", "color('lightblue')"]
]
}
});
});
*/
function showLegend() {
$("#legend").css("display", "block");
}
function hideLegend() {
$("#legend").css("display", "none");
}
// Legend - Colour Table
function emptyColourTable() {
$(".inner").empty();
}
/*
function setHeightTable() {
$(".inner").append( "<table>" +
"<tr><td class='outlined' bgcolor='red'>&nbsp;&nbsp;&nbsp;&nbsp;</td><td> 113007 </td></tr>" +
"<tr><td class='outlined' bgcolor='#ff6b21'></td><td> 113001 </td></tr>" +
"<tr><td class='outlined' bgcolor='#ffb400'></td><td> 112996 </td></tr>" +
"<tr><td class='outlined' bgcolor='yellow'></td><td> 112991</td></tr>" +
"<tr><td class='outlined' bgcolor='#00ff00'></td><td> 112986 </td></tr>" +
"<tr><td class='outlined' bgcolor='cyan'></td><td> 112981 </td></tr>" +
"<tr><td class='outlined' bgcolor='blue'></td><td> 112976 </td></tr>" +
"</table>" );
}
*/
/*
function setHeightTable() {
$(".inner").append( "<table>" +
"<tr><td class='outlined' bgcolor='red'>&nbsp;&nbsp;&nbsp;&nbsp;</td><td> x </td></tr>" +
"<tr><td class='outlined' bgcolor='green'></td><td> y </td></tr>" +
"<tr><td class='outlined' bgcolor='blue'></td><td> z </td></tr>" +
"</table>" );
}
*/
function setHeightTable() {
$(".inner").append( "<table>" +
"<tr><td class='outlined' bgcolor='red'>&nbsp;&nbsp;&nbsp;&nbsp;</td><td> >30 </td></tr>" +
"<tr><td class='outlined' bgcolor='#ff6b21'></td><td> 24 </td></tr>" +
"<tr><td class='outlined' bgcolor='#FFB300'></td><td> 18</td></tr>" +
"<tr><td class='outlined' bgcolor='#BFBF00'></td><td> 12 </td></tr>" +
"<tr><td class='outlined' bgcolor='#0080FF',0)'></td><td> 6 </td></tr>" +
"<tr><td class='outlined' bgcolor='#0000FF',0)'></td><td> 0 </td></tr>" +
"</table>" );
}
// return Cesium.when(target_tileset.readyPromise).then(function (target_tileset) {
// target_tileset.style = new Cesium.Cesium3DTileStyle({
// color: "color('black',1)",
// /*color: {
// conditions: [
// ['Number(${MeasuredHeight}) >= 40', 'rgb(255,0,0)'],
// ['Number(${MeasuredHeight}) >= 30.', 'rgb(255, 93 , 0)'],
// ['Number(${MeasuredHeight}) >= 25', 'rgb(255, 180, 0)'],
// ['Number(${MeasuredHeight}) >= 20', 'rgb(255,255,0)'],
// ['Number(${MeasuredHeight}) >= 15', 'rgb(0,255,0)'],
// ['Number(${MeasuredHeight}) >= 10', 'rgb(0,0,255)'],
// ['Number(${MeasuredHeight}) >= 7.5', 'rgb(75, 0, 130)'],
// ['Number(${MeasuredHeight}) >= 4', 'rgb(248, 100, 221)'],
// ['Number(${MeasuredHeight}) >= 0.1', 'rgb(248, 100, 221)'],
// ['true', 'color("lightblue")']
// ]
// }
// */
// });
// showLegend();
// setHeightTable();
// });
/*
return Cesium.when(tileset.readyPromise).then(function (tileset) {
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
['Number(${YearOfConstruction}) >= 2015', 'rgb(127,201,127)'],
['Number(${YearOfConstruction}) >= 2005', 'rgb(190,174,212)'],
['Number(${YearOfConstruction}) >= 1990', 'rgb(253,192,134)'],
['Number(${YearOfConstruction}) >= 1975', 'rgb(255,255,153)'],
['Number(${YearOfConstruction}) >= 1950', 'rgb(56,108,176)'],
['Number(${YearOfConstruction}) >= 1920', 'rgb(240,2,127)'],
['Number(${YearOfConstruction}) >= 1900', 'rgb(191,91,23)'],
['Number(${YearOfConstruction}) >= 1800', 'rgb(102,102,102)'],
['true', 'color("lightblue")']
]
}
});
}); */
});
\ No newline at end of file
......@@ -264,6 +264,72 @@
</div>
</div>
<div class="col-md-4">
<div class="card mb-4 shadow-sm extension">
<h5>Kirchturm Stoeckach </h5>
<!-- <svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: Thumbnail"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c"/><text x="50%" y="50%" fill="#eceeef" dy=".3em">Thumbnail</text></svg> -->
<img class="thumbimg" src="imgs/thumbnails/Kirchturm.JPG" alt="">
<div class="card-body">
<p class="card-text">Wind visualization around a church tower in Stoeckach, Stuttgart </p>
<!-- <small class="text-muted">9 mins</small> -->
</div>
<div class="d-flex justify-content-between align-items-center btnGroupDiv">
<div class="btn-group">
<form action="circularData.html" class="form-signin" method="GET">
<button type="submit" class="btn btn-sm btn-outline-secondary ">Explore</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- zeile 4 mit gallery -->
<div class="album py-5 bg-light topDownPadding">
<div class="container">
<div class="row">
<div class="col-md-4">
<div class="card mb-4 shadow-sm extension">
<h5>Kirchturm Stoeckach (Partikel), ver 1</h5>
<!-- <svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: Thumbnail"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c"/><text x="50%" y="50%" fill="#eceeef" dy=".3em">Thumbnail</text></svg> -->
<img class="thumbimg" src="imgs/thumbnails/Kirchturm1.JPG" alt="">
<div class="card-body">
<p class="card-text">Wind visualization with particles around a church tower in Stoeckach, Stuttgart </p>
<!-- <small class="text-muted">9 mins</small> -->
</div>
<div class="d-flex justify-content-between align-items-center btnGroupDiv">
<div class="btn-group">
<form action="Kirchturm1.html" class="form-signin" method="GET">
<button type="submit" class="btn btn-sm btn-outline-secondary ">Explore</button>
</form>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card mb-4 shadow-sm extension">
<h5>Kirchturm Stoeckach Version 2</h5>
<!-- <svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: Thumbnail"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c"/><text x="50%" y="50%" fill="#eceeef" dy=".3em">Thumbnail</text></svg> -->
<img class="thumbimg" src="imgs/thumbnails/Kirchturm2.JPG" alt="">
<div class="card-body">
<p class="card-text">Wind visualization with particles around a church tower in Stoeckach, Stuttgart </p>
<!-- <small class="text-muted">9 mins</small> -->
</div>
<div class="d-flex justify-content-between align-items-center btnGroupDiv">
<div class="btn-group">
<form action="Kirchturm2.html" class="form-signin" method="GET">
<button type="submit" class="btn btn-sm btn-outline-secondary ">Explore</button>
</form>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card mb-4 shadow-sm extension">
<h5>Under construction</h5>
......@@ -286,7 +352,6 @@
</div>
</div>
</div>
<!-- <br>
<div class="d-flex justify-content-between align-items-center btnGroupDiv">
......
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