diff --git a/src/index.js b/src/index.js
index f17074053aaaaae18bcd79943151dccda353d39e..858aee80f32744975863462a8dcc1f0b5abb80c7 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,11 +1,20 @@
-import { ToolboxType, WindowSlot, NotificationType } from '@vcmap/ui';
-import { Cesium3DTileStyle, Math as CMath, Ellipsoid, Cartesian3, ConstantProperty, Transforms, HeadingPitchRoll, Cesium3DTileset, Matrix4 } from '@vcmap-cesium/engine';
-import { AbstractInteraction, EventType } from '@vcmap/core';
-import { name, version, mapVersion } from '../package.json';
-import BIMOptions, { bimOptionsId } from './upload.vue';
-import objectList, { objectListId } from './objectList.vue';
-import scaleControl, { scaleControlId } from './scaleControl.vue';
-import * as Cesium from "@vcmap-cesium/engine";
+import {NotificationType, ToolboxType, WindowSlot} from '@vcmap/ui';
+import * as Cesium from '@vcmap-cesium/engine';
+import {
+ Cartesian3,
+ Cesium3DTileset,
+ Cesium3DTileStyle,
+ ConstantProperty,
+ Ellipsoid,
+ HeadingPitchRoll,
+ Math as CMath,
+ Transforms
+} from '@vcmap-cesium/engine';
+import {AbstractInteraction, EventType} from '@vcmap/core';
+import {mapVersion, name, version} from '../package.json';
+import BIMOptions, {bimOptionsId} from './upload.vue';
+import objectList, {loadCatalogModel, objectListId} from './objectList.vue';
+import scaleControl, {scaleControlId} from './scaleControl.vue';
let model;
@@ -56,6 +65,7 @@ function setScale(scaleValue) {
const position = currentlyScaledModel.position.getValue();
const orientation = currentlyScaledModel.orientation;
const uri = currentlyScaledModel.model.uri;
+ const fromCatalog = currentlyScaledModel.fromCatalog;
vcMap.getEntities().remove(currentlyScaledModel);
removePlacedModel(currentlyScaledModel);
@@ -70,6 +80,7 @@ function setScale(scaleValue) {
scale: scaleValue,
show: true,
},
+ fromCatalog: fromCatalog,
});
placedModels.push({
model: newModel,
@@ -102,6 +113,7 @@ function saveObjects() {
position: [wgs84X, wgs84Y, height],
heading: heading,
scale: m.model.model.scale.getValue(),
+ fromCatalog: m.model.fromCatalog.valueOf(),
});
}
outputObject.placedObjects = outputArray;
@@ -127,7 +139,7 @@ function saveFile(fileName, urlFile){
}
-function setupModel(vcsApp, windowPos, url, name) {
+function setupModel(vcsApp, windowPos, url, name, fromCatalog) {
const vcMap = vcsApp.maps.activeMap;
const scene = vcMap.getScene();
const ray = scene.camera.getPickRay(windowPos);
@@ -141,6 +153,7 @@ function setupModel(vcsApp, windowPos, url, name) {
show: true,
scale: 1,
},
+ fromCatalog: fromCatalog,
});
placedModels.push({
model: model,
@@ -180,7 +193,6 @@ class MoveInteraction extends AbstractInteraction {
let xDif = pickResult.x - initialPickResult.x;
let yDif = pickResult.y - initialPickResult.y;
let zDif = pickResult.z - initialPickResult.z;
- // pickResult.z = pickResult.z + heightDif;
let pos = initialPosition.clone();
pos.x = pos.x + xDif;
pos.y = pos.y + yDif;
@@ -289,8 +301,7 @@ class RotateAction extends AbstractInteraction {
if (hpRoll.heading < 0.0) {
hpRoll.heading += CMath.TWO_PI;
}
- const orientation = new ConstantProperty(Transforms.headingPitchRollQuaternion(modelPos, hpRoll));
- model.orientation = orientation;
+ model.orientation = new ConstantProperty(Transforms.headingPitchRollQuaternion(modelPos, hpRoll));
}
return event;
}
@@ -343,7 +354,7 @@ export default function smartVillagesPlugin(config, baseUrl) {
const objects = JSON.parse(content);
const vcMap = app.maps.activeMap;
for (const loadingObject of objects.placedObjects) {
- let objectUrl = undefined;
+ let objectUrl;
for (const loadedObject of pluginState.objects) {
if (loadedObject.name === loadingObject.name) {
objectUrl = loadedObject.url;
@@ -351,12 +362,29 @@ export default function smartVillagesPlugin(config, baseUrl) {
}
}
if (objectUrl === undefined) {
- app.notifier.add({
- type: NotificationType.ERROR,
- message: "Objekt mit dem namen: " + loadingObject.name + " konnte nicht in den geladenen Objekten gefunden werden. Konfiguration konnte nicht vollständig geladen werden.",
- });
- // abort
- return;
+ if (loadingObject.fromCatalog === true){
+ // Load the model into memory
+ const model = await loadCatalogModel(loadingObject.name).catch(e => {
+ console.error(e);
+ app.notifier.add({
+ type: NotificationType.ERROR,
+ message: "Katalogobject: " + loadingObject.name + " konnte nicht geladenen werden. Konfiguration konnte nicht vollständig geladen werden.",
+ });
+ return undefined;
+ });
+ if (model === undefined) {
+ return;
+ } else {
+ objectUrl = model.url;
+ }
+ }else {
+ app.notifier.add({
+ type: NotificationType.ERROR,
+ message: "Objekt mit dem namen: " + loadingObject.name + " konnte nicht in den geladenen Objekten gefunden werden. Konfiguration konnte nicht vollständig geladen werden.",
+ });
+ // abort
+ return;
+ }
}
const cartPos = Cartesian3.fromDegrees(loadingObject.position[0], loadingObject.position[1], loadingObject.position[2]);
// Add the model to the viewer
@@ -367,13 +395,13 @@ export default function smartVillagesPlugin(config, baseUrl) {
uri: objectUrl,
scale: loadingObject.scale,
show: true,
+ fromCatalog: loadingObject.fromCatalog,
},
});
const roll = new HeadingPitchRoll();
hpRollMap.set(model, roll);
roll.heading = loadingObject.heading;
- const orientation = new ConstantProperty(Transforms.headingPitchRollQuaternion(model.position.getValue(), roll));
- model.orientation = orientation;
+ model.orientation = new ConstantProperty(Transforms.headingPitchRollQuaternion(model.position.getValue(), roll));
placedModels.push({
model: model,
@@ -527,11 +555,6 @@ export default function smartVillagesPlugin(config, baseUrl) {
}
const map = vcsApp.maps.getByType("CesiumVisualisationType");
- console.log(map);
-
- // tileset.allTilesLoaded.addEventListener(function() {
- // console.log('All tiles are loaded');
- // });
const bimGroup = {
id: 'bim-functions',
diff --git a/src/objectList.vue b/src/objectList.vue
index 7045585a936dd38db584f79f9e287b12ed9e14f7..1b896716ad1d0b61f34da0e4e30f0ddc7b49c226 100644
--- a/src/objectList.vue
+++ b/src/objectList.vue
@@ -6,10 +6,9 @@
Die Objektbibliothek.
-
-
- {{ categoryName }}
-
+
+
+
{{subCategory}}
@@ -17,7 +16,7 @@
-
+
@@ -113,7 +112,7 @@ import {
VcsTreeview,
VcsTreeviewTitle,
} from '@vcmap/ui';
-import {VCard, VCol, VContainer, VDialog, VForm, VRow, VSheet, VSwitch,} from 'vuetify/components';
+import {VCard, VCol, VContainer, VDialog, VForm, VRow, VSheet, VSwitch, VExpansionPanels} from 'vuetify/components';
import {computed, inject, onMounted, ref} from 'vue';
import {name} from '../package.json';
import * as THREE from 'three';
@@ -126,21 +125,21 @@ const preloadedModels = ref({});
const defaultItems = [];
const items = ref(defaultItems);
-let setupModelFunction = undefined;
-let app = undefined;
-let projectStateObject = undefined;
+let setupModelFunction;
+let app;
+let projectStateObject;
-async function loadCataloguesFromConfig(config) {
+async function loadCatalogsFromConfig(config) {
const configJson = JSON.parse(JSON.stringify(config));
const catalogues = Object.values(configJson.objectCatalogues);
for (const cat of catalogues) {
- const catJson = await retrieveCatalogueJson(cat.url);
+ const catJson = await retrieveCatalogJson(cat.url);
if (!catJson) continue;
const category = cat.category.toString();
const linkPrefix = cat.url.replace(/\/[^/]*catalog\.json$/, '/');
- const entries = getCatalogueEntries(catJson, linkPrefix);
+ const entries = getCatalogEntries(catJson, linkPrefix);
if (!objLib.value[category]) {
objLib.value[category] = entries;
@@ -152,21 +151,22 @@ async function loadCataloguesFromConfig(config) {
}
-async function retrieveCatalogueJson(link) {
+async function retrieveCatalogJson(link) {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000);
try {
const response = await fetch(link, { signal: controller.signal });
if (!response.ok) {
- throw new Error(`HTTP error ${response.status} for ${link}`);
+ console.error(`Received HTTP error ${response.status} for ${link}`);
+ return null;
}
return await response.json();
} catch (error) {
if (error.name === 'AbortError') {
- console.warn(`Fetch aborted (timeout) for: ${link}`);
- } else {
- console.error(`Fetch failed for ${link}:`, error);
+ console.error(`Catalog.json request timed out: ${link}`);
+ }else{
+ console.error(`Encountered error during catalog.json request: ${link}`, error);
}
return null;
} finally {
@@ -174,7 +174,7 @@ async function retrieveCatalogueJson(link) {
}
}
-function getCatalogueEntries(json, linkPrefix) {
+function getCatalogEntries(json, linkPrefix) {
const part = {};
@@ -210,72 +210,75 @@ function getCatalogueEntries(json, linkPrefix) {
return part;
}
-async function retrieveCatalogModel(modelLink){
- if(preloadedModels.value[modelLink] != null){
- const catModel = preloadedModels.value[modelLink];
+async function placeCatalogModel(modelLink){
+ loadCatalogModel(modelLink).then(model => {
+ const catModel = model;
const x = window.innerWidth / 2;
const y = window.innerHeight / 2;
const cart = new Cartesian2(x, y);
- setupModelFunction(app, cart, catModel.url, catModel.modelLink);
- } else {
- const loader = new GLTFLoader();
- loader.load(
- modelLink,
- function (gltf) {
- const bounds = new THREE.Box3().setFromObject(gltf.scene);
- const x = bounds.min.x + (bounds.max.x - bounds.min.x) / 2;
- const z = bounds.min.z + (bounds.max.z - bounds.min.z) / 2;
- const m = new THREE.Matrix4().makeTranslation(-x, -bounds.min.y, -z);
- gltf.scene.applyMatrix4(m);
-
- const exporter = new GLTFExporter();
- const options = {
- binary: true,
- animations: gltf.animations,
- };
+ setupModelFunction(app, cart, catModel.url, catModel.modelLink, true);
+ }).catch(error => {
+ console.error(error);
+ app.notifier.add({
+ type: NotificationType.ERROR,
+ message:
+ 'Ein Fehler ist beim Laden des Katalogobjektes aufgetreten.',
+ timeout: 20000,
+ });
+ });
+}
- exporter.parse(
- gltf.scene,
- function (output) {
- const blob = new Blob([output], { type: 'application/octet-stream' });
- const url = URL.createObjectURL(blob);
-
- projectStateObject.objects.push({
- name: modelLink,
- url: url,
- });
- const x = window.innerWidth / 2;
- const y = window.innerHeight / 2;
- const cart = new Cartesian2(x, y);
- setupModelFunction(app, cart, url, modelLink);
- preloadedModels.value[modelLink] = {
- url: url,
- modelLink: modelLink,
- };
- },
- function (error) {
- app.notifier.add({
- type: NotificationType.ERROR,
- message:
- 'Ein Fehler ist beim Laden der glTF Datei aufgetreten. Bitte vergewissern Sie sich, dass es sich um eine gültige glTF2.0 Datei handelt.',
- timeout: 20000,
- });
- },
- options
- );
- },
- undefined,
- function (error) {
- app.notifier.add({
- type: NotificationType.ERROR,
- message:
- 'Ein Fehler ist beim Laden der glTF Datei aufgetreten. Bitte vergewissern Sie sich, dass es sich um eine gültige glTF2.0 Datei handelt.' +
- ' Fehlermeldung: ' + error.message,
- timeout: 20000,
- });
- }
- );
- }
+export async function loadCatalogModel(modelLink){
+ return new Promise( (resolve, reject) => {
+ if(preloadedModels.value[modelLink] != null){
+ // Model is already in memory
+ resolve(preloadedModels.value[modelLink]);
+ } else{
+ const loader = new GLTFLoader();
+ loader.load(
+ modelLink,
+ function (gltf) {
+ const bounds = new THREE.Box3().setFromObject(gltf.scene);
+ const x = bounds.min.x + (bounds.max.x - bounds.min.x) / 2;
+ const z = bounds.min.z + (bounds.max.z - bounds.min.z) / 2;
+ const m = new THREE.Matrix4().makeTranslation(-x, -bounds.min.y, -z);
+ gltf.scene.applyMatrix4(m);
+
+ const exporter = new GLTFExporter();
+ const options = {
+ binary: true,
+ animations: gltf.animations,
+ };
+
+ exporter.parse(
+ gltf.scene,
+ function (output) {
+ const blob = new Blob([output], { type: 'application/octet-stream' });
+ const url = URL.createObjectURL(blob);
+
+ projectStateObject.objects.push({
+ name: modelLink,
+ url: url,
+ });
+ preloadedModels.value[modelLink] = {
+ url: url,
+ modelLink: modelLink,
+ };
+ resolve(preloadedModels.value[modelLink]);
+ },
+ function (error) {
+ reject(error);
+ },
+ options
+ );
+ },
+ undefined,
+ function (error) {
+ reject(error);
+ }
+ );
+ }
+ })
}
function uploadModel() {
@@ -303,8 +306,6 @@ function uploadModel() {
});
let url = URL.createObjectURL(blob);
-
-
const loader = new GLTFLoader();
loader.load(url, function(gltf) {
let bounds = new THREE.Box3().setFromObject(gltf.scene);
@@ -337,7 +338,7 @@ function uploadModel() {
const x = window.innerWidth / 2;
const y = window.innerHeight / 2;
const cart = new Cartesian2(x, y);
- setupModelFunction(app, cart, url, name);
+ setupModelFunction(app, cart, url, name, false);
},
}
]
@@ -346,10 +347,11 @@ function uploadModel() {
},
// called when there is an error in the generation
- function ( error ) {
+ function ( error ) {
app.notifier.add({
type: NotificationType.ERROR,
- message: "Ein Fehler ist beim Laden der glTF Datei aufgetreten. Bitte vergewissern Sie sich, dass es sich um eine gültige glTF2.0 Datei handelt.",
+ message: "Ein Fehler ist beim Laden der glTF Datei aufgetreten. Bitte vergewissern Sie sich, dass es sich um eine gültige glTF2.0 Datei handelt." +
+ " Fehlermeldung: " + error.message,
timeout: 20000,
});
}, options);
@@ -362,8 +364,6 @@ function uploadModel() {
});
});
}
-
-
reader.readAsArrayBuffer(file);
}
});
@@ -403,6 +403,7 @@ function uploadModel() {
VContainer,
VRow,
VCol,
+ VExpansionPanels,
},
setup() {
app = inject('vcsApp');
@@ -430,8 +431,7 @@ function uploadModel() {
const dialog = ref(false);
setupModelFunction = setupModel;
projectStateObject = pluginState;
- // loadCataloguesFromConfig(config).then(response => {console.log(objLib);});
- onMounted(()=>loadCataloguesFromConfig(config).then(response => {console.log(objLib)}));
+ onMounted(()=>loadCatalogsFromConfig(config).then(() => {console.log("Object library loaded")}));
return {
draggable,
selectable,
@@ -525,8 +525,8 @@ function uploadModel() {
loadModel() {
uploadModel();
},
- fetchCatalogueModel(modelLink) {
- retrieveCatalogModel(modelLink);
+ placeCatalogModel(modelLink) {
+ placeCatalogModel(modelLink);
},
loadConfiguration() {
loadObjects(app);