Files
qt5-legatus-legacy/Lts/Tools/EsriHTML/3D_Verwundungsmodell_JM_2021-08-17/main.js
T
2026-08-13 18:33:10 +02:00

709 lines
27 KiB
JavaScript
Executable File

class InitializationHandler {
constructor() {
}
async generateMap() {
return new Promise((res) => {
require([
"esri/Map",
"esri/views/SceneView",
"esri/layers/GraphicsLayer",
"esri/Graphic",
"esri/geometry/Point",
"esri/geometry/projection",
"dojo",
],
(
Map,
SceneView,
GraphicsLayer,
Graphic,
Point,
Projection,
) => {
// console.log(L);
const map = new Map({
basemap: "dark-gray"
});
const view = new SceneView({
container: "mapDiv",
map,
scale: 1000,
camera: {
position: {
x: 8.896638,
y: 53.054441,
z: 400
}
}
});
const graphicLayer = new GraphicsLayer();
map.add(graphicLayer);
res({ map, view, graphicLayer, Projection, Graphic, Point });
});
})
}
}
class FileManager {
constructor() {
this.resultXML;
this.fileReader = new FileReader();
this.domParser = new DOMParser();
}
loadFileContent(file) {
return new Promise(res => {
this.fileReader.readAsText(file);
this.fileReader.onloadend = () => {
this.resultXML = this.domParser.parseFromString(this.fileReader.result, "application/xml");
res();
}
})
}
getFileAsJson() {
return this.xmlToJson(this.resultXML);
}
xmlToJson(xml) {
// Create the return object
var obj = {};
if (xml.nodeType == 1) { // element
// do attributes
if (xml.attributes.length > 0) {
obj["@attributes"] = {};
for (var j = 0; j < xml.attributes.length; j++) {
var attribute = xml.attributes.item(j);
obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
}
}
} else if (xml.nodeType == 3) { // text
obj = xml.nodeValue;
}
// do children
if (xml.hasChildNodes()) {
for (var i = 0; i < xml.childNodes.length; i++) {
var item = xml.childNodes.item(i);
var nodeName = item.nodeName;
if (typeof (obj[nodeName]) == "undefined") {
obj[nodeName] = this.xmlToJson(item);
} else {
if (typeof (obj[nodeName].push) == "undefined") {
var old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push(old);
}
obj[nodeName].push(this.xmlToJson(item));
}
}
}
return obj;
};
cleanBuildingJson(dirtyJson, remove_duplicates = true, fix_esri_bug = true) {
let building = {};
building.name = dirtyJson.BuildingVulnerability.BuildingName["#text"];
building.isExpanded = false;
building.rooms = [];
if (!Array.isArray(dirtyJson.BuildingVulnerability.Rooms.Room)){
dirtyJson.BuildingVulnerability.Rooms.Room = [dirtyJson.BuildingVulnerability.Rooms.Room]
}
dirtyJson.BuildingVulnerability.Rooms.Room.forEach(room => {
let room_tmp = {};
room_tmp.name = room.RoomId["#text"];
room_tmp.isExpanded = false;
room_tmp.walls = [];
if (room.RoomOuterWalls.OuterWall && Array.isArray(room.RoomOuterWalls.OuterWall)) {
let wallCounter = 0;
room.RoomOuterWalls.OuterWall.forEach(wall => {
let wall_tmp = {}
wall_tmp.isSelected = false;
wall_tmp.name = wallCounter;
wall_tmp.points = [];
if (wall.OuterWallAreaElement.PolygonPoint) {
wall.OuterWallAreaElement.PolygonPoint.forEach(point => {
wall_tmp.points.push({ "x": +point.X["#text"], "y": +point.Y["#text"], "z": +point.Z["#text"] });
});
}
room_tmp.walls.push(wall_tmp);
wallCounter++;
});
}
building.rooms.push(room_tmp);
});
if (!remove_duplicates) return building
building.rooms.forEach(room => {
room.walls = room.walls.filter(wall => {
let counter = 0;
building.rooms.forEach(room_ => {
room_.walls.forEach(wall_ => {
if (JSON.stringify(wall.points) === JSON.stringify(wall_.points)) {
counter++;
}
});
});
if (counter > 1) return false;
return true;
})
});
if (!fix_esri_bug) return building;
building.rooms.forEach(room => {
room.walls.map((wall) => {
let lowest_point = wall.points[0].z;
wall.points.forEach(point => {
if (point.z < lowest_point) lowest_point = point.z;
});
wall.points.forEach(point => {
if (point.z > lowest_point) point.y += 0.0001;
if (point.z > lowest_point) point.x += 0.0001;
});
})
});
return building;
}
cleanEquipmentJson(dirtyJson) {
let equipment = {};
equipment.referencePoints = [];
//streif/header/group/group/[1]/switch/[0]/group/externalReferences
console.log(dirtyJson.STREIF.Header.Group.Group);
let groups = dirtyJson.STREIF.Header.Group.Group;
groups.shift();
console.log(groups)
groups.forEach(group => {
console.log(group)
if (!Array.isArray(group.Switch)) return;
group.Switch.forEach(_switch => {
if (!Array.isArray(_switch.Group.External_Reference)){
_switch.Group.External_Reference = [_switch.Group.External_Reference]
}
_switch.Group.External_Reference.forEach(external_reference => {
equipment.referencePoints.push({
isExternal: false,
name: external_reference.Name["#text"],
coords: {
x: +external_reference.Coord["@attributes"].X,
y: +external_reference.Coord["@attributes"].Y,
z: +external_reference.Coord["@attributes"].Z
}
})
console.log(external_reference.Name);
});
});
});
const referencePoints = dirtyJson.STREIF.Header.Group.External_Reference;
referencePoints.forEach(referencePoint => {
equipment.referencePoints.push({
isExternal: true,
name: referencePoint.Name["#text"],
coords: {
x: +referencePoint.Coord["@attributes"].X,
y: +referencePoint.Coord["@attributes"].Y,
z: +referencePoint.Coord["@attributes"].Z
}
})
});
return equipment;
}
}
class DataProvider {
constructor() {
this.data = [];
this.equipment = [];
}
addBuilding(building) {
this.data.push(building);
}
getCurrentData() {
return this.data;
}
addEquipment(equipment) {
console.log(equipment);
this.equipment.push(equipment);
}
getCurrentEquipment() {
return this.equipment;
}
}
class UIHandler {
constructor(dataProvider) {
this.dataProvider = dataProvider;
this.rootElement = document.getElementById("myUL");
}
makeBuildingRow(building) {
let row = document.createElement('div');
row.classList.add("row");
row.onclick = () => {
building.isExpanded = !building.isExpanded;
this.render();
}
let outerContainer = document.createElement('div');
outerContainer.classList.add('col-12');
outerContainer.classList.add('bg-light');
row.appendChild(outerContainer);
let fluidContainer = document.createElement('div');
fluidContainer.classList.add('container-fluid');
outerContainer.appendChild(fluidContainer);
let innerRow = document.createElement('div');
innerRow.classList.add('row');
innerRow.classList.add("row-hover");
fluidContainer.appendChild(innerRow);
let segOne = document.createElement('div');
segOne.classList.add('col-1');
let segThree = document.createElement('div');
segThree.classList.add('col-11');
segThree.classList.add('p-2');
segThree.classList.add('treeStruct');
let segThreeInner_one = document.createElement('div');
if (building.isExpanded) segThreeInner_one.classList.add('buildingTreeRight');
let segThreeInner_two = document.createElement('div');
if (building.isExpanded) segThreeInner_two.classList.add('buildingTreeBottom');
segThree.innerText = 'Building ' + building.name;
segThree.appendChild(segThreeInner_one);
segThree.appendChild(segThreeInner_two);
innerRow.appendChild(segOne);
innerRow.appendChild(segThree);
return row;
}
makeRoomRow(room) {
let row = document.createElement('div');
row.classList.add("row");
row.onclick = () => {
room.isExpanded = !room.isExpanded;
this.render();
}
let outerContainer = document.createElement('div');
outerContainer.classList.add('col-12');
outerContainer.classList.add('bg-light');
row.appendChild(outerContainer);
let fluidContainer = document.createElement('div');
fluidContainer.classList.add('container-fluid');
outerContainer.appendChild(fluidContainer);
let innerRow = document.createElement('div');
innerRow.classList.add('row');
innerRow.classList.add("row-hover");
fluidContainer.appendChild(innerRow);
let segOne = document.createElement('div');
segOne.classList.add('col-1');
let segTwo = document.createElement('div');
segTwo.classList.add('col-1');
segTwo.classList.add('border-dark');
segTwo.classList.add('border-end');
let segThree = document.createElement('div');
segThree.classList.add('col-10');
segThree.classList.add('p-2');
segThree.classList.add('treeStruct');
let segThreeInner_one = document.createElement('div');
segThreeInner_one.classList.add('roomTreeRight');
let segThreeInner_two = document.createElement('div');
if (room.isExpanded) segThreeInner_two.classList.add('roomTreeBottom');
segThree.innerText = 'Room ' + room.name;
segThree.appendChild(segThreeInner_one);
segThree.appendChild(segThreeInner_two);
innerRow.appendChild(segOne);
innerRow.appendChild(segTwo);
innerRow.appendChild(segThree);
return row;
}
makeWallRow(wall) {
let row = document.createElement('div');
row.classList.add("row");
let outerContainer = document.createElement('div');
outerContainer.classList.add('col-12');
outerContainer.classList.add('bg-light');
row.appendChild(outerContainer);
let fluidContainer = document.createElement('div');
fluidContainer.classList.add('container-fluid');
if (wall.isSelected) fluidContainer.classList.add("selectedWall");
outerContainer.appendChild(fluidContainer);
let innerRow = document.createElement('div');
innerRow.classList.add('row');
innerRow.classList.add("row-hover");
fluidContainer.appendChild(innerRow);
let segOne = document.createElement('div');
segOne.classList.add('col-1');
let segTwo = document.createElement('div');
segTwo.classList.add('col-2');
segTwo.classList.add('border-dark');
segTwo.classList.add('border-end');
let segThree = document.createElement('div');
segThree.classList.add('col-9');
segThree.classList.add('p-2');
segThree.classList.add('treeStruct');
let segThreeInner = document.createElement('div');
segThreeInner.classList.add('wallTreeRight');
segThree.innerText = 'Wall ' + wall.name;
segThree.appendChild(segThreeInner);
innerRow.appendChild(segOne);
innerRow.appendChild(segTwo);
innerRow.appendChild(segThree);
return row;
}
render() {
while (this.rootElement.firstChild) {
this.rootElement.removeChild(this.rootElement.firstChild);
}
let buildingArray = this.dataProvider.getCurrentData();
buildingArray.forEach(building => {
this.createBuilding(building);
});
}
createBuilding(buildingConfig) {
let buildingListEntry = document.createElement("li");
let buildingListEntrySpan = document.createElement("SPAN");
buildingListEntrySpan.classList.add("caret");
buildingListEntrySpan.appendChild(this.makeBuildingRow(buildingConfig));
buildingListEntry.appendChild(buildingListEntrySpan);
buildingListEntry.appendChild(this.createRoomList(buildingConfig.rooms, buildingConfig.isExpanded));
document.getElementById('myUL').appendChild(buildingListEntry);
}
createRoomList(roomArray, isExpanded) {
let roomList = document.createElement("ul");
roomList.classList.add("nested");
if (isExpanded) roomList.classList.add("active");
roomArray.forEach(room => {
let roomListEntry = document.createElement("li");
let roomListEntrySpan = document.createElement("SPAN");
roomListEntrySpan.classList.add("caret");
roomListEntrySpan.appendChild(this.makeRoomRow(room));
roomListEntry.appendChild(roomListEntrySpan);
roomListEntry.appendChild(this.createWallList(room.walls, room.isExpanded));
roomList.appendChild(roomListEntry);
});
return roomList;
}
createWallList(wallArray, isExpanded) {
let wallList = document.createElement("ul");
wallList.classList.add("nested");
if (isExpanded) wallList.classList.add("active");
wallArray.forEach(wall => {
let wallListEntry = document.createElement("li");
let wallListEntrySpan = document.createElement("SPAN");
wallListEntrySpan.appendChild(this.makeWallRow(wall));
wallListEntry.appendChild(wallListEntrySpan);
wallList.appendChild(wallListEntry);
});
return wallList;
}
}
class DrawingHandler {
constructor(dataProvider, uiHandler, graphicLayer, Point, Projection, Graphic, view, map) {
this.dataProvider = dataProvider;
this.uiHandler = uiHandler;
this.graphicLayer = graphicLayer;
this.Point = Point;
this.Projection = Projection;
this.Graphic = Graphic;
this.view = view;
this.map = map
this.fillActive = true;
this.view.on("click", (e) => {
if (e.button === 0) {
this.view.hitTest(e).then((res) => {
if (res.results[0].graphic.geometry.type == "polygon") res.results[0].graphic.clickCallback()
});
}
})
const [r, g, b] = [Math.floor(Math.random() * 50) + 100, Math.floor(Math.random() * 50) + 150, 255];
this.r = r;
this.g = g;
this.b = b;
this.fillSymbol = {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: [this.r, this.g, this.b, 0.8],
outline: {
// autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 2
}
};
this.nonFillSymbol = {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: [this.r, this.g, this.b, 0.8],
style: "none",
outline: {
// autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 2
}
};
}
draw() {
this.Projection.load().then(() => {
let buildings = this.dataProvider.getCurrentData();
buildings.forEach(building => {
building.rooms.forEach(room => {
room.walls.forEach(wall => {
const wallGeometry = {
type: "polygon",
rings: [],
}
const markerSymbol = {
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
color: [this.r, this.g, this.b],
size: "5px"
};
wall.points.forEach(point => {
let p = {
type: "point", // autocasts as new Point()
x: 493063.5202829816 + point.x,
y: 5878330.672506552 + point.y,
z: 0 + point.z,
spatialReference: {
wkid: 32632
}
}
let p_transformed = this.Projection.project(p, this.view.spatialReference);
wallGeometry.rings.push([p_transformed.longitude, p_transformed.latitude, p_transformed.z]);
const pointGraphic = new this.Graphic({
geometry: p_transformed,
symbol: markerSymbol
});
this.graphicLayer.add(pointGraphic);
});
wallGeometry.rings.push(wallGeometry.rings[0]);
wallGeometry.rings = wallGeometry.rings.reverse();
let wallCoordTableContent = ``;
wall.points.forEach(vertex => {
wallCoordTableContent +=
`<tr>
<td>${parseFloat(vertex.x).toFixed(3)}</td>
<td>${parseFloat(vertex.y).toFixed(3)}</td>
<td>${parseFloat(vertex.z).toFixed(3)}</td>
</tr>`
});
const wallCoordTable = `<table style="width:100%">
<tr>
<th>X</th>
<th>Y</th>
<th>Z</th>
</tr>
${wallCoordTableContent}
</table>`
let logVertices = {
title: "Log Vertices",
id: `log${room.name}${wall.name}`,
};
const wallAttributes = {
name: `Room ${room.name} - Wall ${wall.name}`,
ringSize: wallGeometry.rings.length,
vertices: wallCoordTable
}
const wallPopupTemplate = {
title: "{name}",
content: [
{
type: "fields",
fieldInfos: [
{
fieldName: "ringSize"
},
{
fieldName: "vertices"
},
]
}
],
actions: [logVertices]
}
this.view.popup.on("trigger-action", (event) => {
if (event.action.id === `log${room.name}${wall.name}`) {
let array = [];
wall.points.forEach(point => {
array.push([point.x, point.y, point.z * 100]);
});
console.log(JSON.stringify(array));
debugger;
}
});
const polygonGraphic = new this.Graphic({
geometry: wallGeometry,
symbol: this.fillActive ? this.fillSymbol : this.nonFillSymbol,
attributes: wallAttributes,
popupTemplate: wallPopupTemplate
});
polygonGraphic.clickCallback = () => {
buildings.forEach(building_ => {
building_.isExpanded = false;
building_.rooms.forEach(room_ => {
room_.isExpanded = false;
room_.walls.forEach(wall_ => {
wall_.isSelected = false;
});
});
});
building.isExpanded = true;
room.isExpanded = true;
wall.isSelected = true;
this.uiHandler.render();
}
this.graphicLayer.add(polygonGraphic);
});
});
});
const externalMarkerSymbol = {
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
color: [255, 0, 0],
size: "15px"
};
const internalMarkerSymbol = {
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
color: [0, 255, 0],
size: "15px"
};
let equipments = this.dataProvider.getCurrentEquipment();
equipments.forEach(equipment => {
equipment.referencePoints.forEach(referencePoint => {
let p = {
type: "point", // autocasts as new Point()
x: 493063.5202829816 + referencePoint.coords.x,
y: 5878330.672506552 + referencePoint.coords.y,
z: 0 + referencePoint.coords.z,
spatialReference: {
wkid: 32632
}
}
let p_transformed = this.Projection.project(p, this.view.spatialReference);
const referencePointAttribute = {
name: referencePoint.name,
coords: `<table style="width:100%">
<tr>
<th>X</th>
<th>Y</th>
<th>Z</th>
</tr>
<tr>
<td>${parseFloat(referencePoint.coords.x).toFixed(3)}</td>
<td>${parseFloat(referencePoint.coords.y).toFixed(3)}</td>
<td>${parseFloat(referencePoint.coords.z).toFixed(3)}</td>
</tr>
</table>`
}
const referencePointAttributeTemplate = {
title: "{name}",
content: [
{
type: "fields",
fieldInfos: [
{
fieldName: "coords"
}
]
}
],
}
const pointGraphic = new this.Graphic({
geometry: p_transformed,
symbol: referencePoint.isExternal ? externalMarkerSymbol : internalMarkerSymbol,
attributes: referencePointAttribute,
popupTemplate: referencePointAttributeTemplate
});
this.graphicLayer.add(pointGraphic);
});
});
})
}
toggleFill() {
let useFill = !this.fillActive;
this.fillActive = !this.fillActive;
let symbol = useFill ? this.fillSymbol : this.nonFillSymbol;
this.graphicLayer.graphics.forEach(graphic => {
if (graphic.geometry.type == "polygon") graphic.set('symbol', symbol);
});
}
}
//This is the main
(() => {
const fileManager = new FileManager();
const dataProvider = new DataProvider();
const uiHandler = new UIHandler(dataProvider);
let drawingHandler;
const initializationHandler = new InitializationHandler();
initializationHandler.generateMap().then((esriLoad) => {
esriObjects = esriLoad;
drawingHandler = new DrawingHandler(dataProvider,
uiHandler,
esriObjects.graphicLayer,
esriObjects.Point,
esriObjects.Projection,
esriObjects.Graphic,
esriObjects.view,
esriObjects.map
);
});
document.getElementById("flexSwitchCheckDefault").addEventListener("click", () => {
drawingHandler.toggleFill();
})
const buildingFile = document.getElementById('exampleFormControlFile1');
buildingFile.onchange = async () => {
const file = buildingFile.files[0];
await fileManager.loadFileContent(file);
dataProvider.addBuilding(fileManager.cleanBuildingJson(fileManager.getFileAsJson()));
uiHandler.render();
drawingHandler.draw();
document.getElementById('modal-close-button').click();
}
const equipmentFile = document.getElementById('exampleFormControlFile2');
equipmentFile.onchange = async () => {
const file = equipmentFile.files[0];
await fileManager.loadFileContent(file);
console.log(fileManager.getFileAsJson());
dataProvider.addEquipment(fileManager.cleanEquipmentJson(fileManager.getFileAsJson()));
drawingHandler.draw();
document.getElementById('modal-close-button').click();
}
})();