From 72906377c86fabcbf220ed7f7f2a63a5b5521a5e Mon Sep 17 00:00:00 2001 From: wanli Date: Fri, 18 Nov 2022 21:27:54 +0800 Subject: [PATCH] [Frontend] forge test --- Frontend/forgeTest.html | 53 +++++++ Frontend/forgetAnim1.html | 228 ++++++++++++++++++++++++++++++ Frontend/forgetTest2.html | 241 ++++++++++++++++++++++++++++++++ Frontend/js/forge/forgemodel.js | 170 ++++++++++++++++++++++ 4 files changed, 692 insertions(+) create mode 100644 Frontend/forgeTest.html create mode 100644 Frontend/forgetAnim1.html create mode 100644 Frontend/forgetTest2.html create mode 100644 Frontend/js/forge/forgemodel.js diff --git a/Frontend/forgeTest.html b/Frontend/forgeTest.html new file mode 100644 index 0000000..5f78e4d --- /dev/null +++ b/Frontend/forgeTest.html @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Frontend/forgetAnim1.html b/Frontend/forgetAnim1.html new file mode 100644 index 0000000..883d698 --- /dev/null +++ b/Frontend/forgetAnim1.html @@ -0,0 +1,228 @@ +///////////////////////////////////////////////////////////////////// +// Explorer viewer extension +// by Philippe Leefsma, March 2015 +// +///////////////////////////////////////////////////////////////////// +AutodeskNamespace("Autodesk.ADN.Viewing.Extension"); + + +Autodesk.ADN.Viewing.Extension.Explorer = function (viewer, options) { + + Autodesk.Viewing.Extension.call(this, viewer, options); + + var _self = this; + + var _viewer = viewer; + + ///////////////////////////////////////////////////////////////// + // The Explorer tool + // + ///////////////////////////////////////////////////////////////// + function ExplorerTool(viewer) { + + this.getNames = function() { + + return ["Autodesk.ADN.Viewing.Tool.ExplorerTool"]; + }; + + this.getName = function() { + + return "Autodesk.ADN.Viewing.Tool.ExplorerTool"; + }; + + ///////////////////////////////////////////////////////////// + // called when tool is activated + // + ///////////////////////////////////////////////////////////// + this.activate = function(name) { + + _viewer.navigation.setRequestHomeView(true); + + var position = _viewer.navigation.getPosition(); + var target = _viewer.navigation.getTarget(); + var worldUp = _viewer.navigation.getWorldUpVector(); + + var pt = { + x: position.x - target.x, + y: position.y - target.y, + z: position.z - target.z + } + + this.height = dotProduct(pt, worldUp); + + var rVect = getPerpendicularVector(worldUp); + + this.radius = dotProduct(pt, rVect); + }; + + ///////////////////////////////////////////////////////////// + // called when tool is deactivated + // + ///////////////////////////////////////////////////////////// + this.deactivate = function(name) { + + this.activated = false; + }; + + this.speed = 0.3; + this.phase = "1"; + this.switchPhase = true; + + ///////////////////////////////////////////////////////////// + // update is called by the framework + // t: time elapsed since tool activated in ms + ///////////////////////////////////////////////////////////// + this.update = function(t) { + + var target = _viewer.navigation.getTarget(); + var worldUp = _viewer.navigation.getWorldUpVector(); + + var offset = Math.abs(Math.cos(this.speed * t * 0.001)); + + // create some effect to keep camera near object + // while it orbits for a while + if(offset < 0.01) { + + if(this.switchPhase) { + + this.switchPhase = false; + + if (this.phase === "1") { + this.phase = "2"; + } + else if (this.phase === "2") { + this.phase = "1"; + } + } + } + + if(offset > 0.99) { + this.switchPhase = true; + } + + if(this.phase === "1") + this.offset = offset; + + var height = this.height * (0.5 + 1.5 * this.offset); + + var radius = this.radius * (0.5 + 1.5 * this.offset); + + var center = { + x: target.x + height * worldUp.x, + y: target.y + height * worldUp.y, + z: target.z + height * worldUp.z + } + + var pos = computeCirclularTrajectory( + this.speed * t * 0.001, + radius, + worldUp, + center); + + _viewer.navigation.setPosition(pos); + + return false; + }; + + ///////////////////////////////////////////////////////////// + // utilities + // + ///////////////////////////////////////////////////////////// + function crossProduct(u, v) { + + return { + + x: u.y * v.z - u.z * v.y, + y: u.z * v.x - u.x * v.z, + z: u.x * v.y - u.y * v.x + } + } + + function dotProduct(u, v) { + + return Math.abs( + u.x * v.x + + u.y * v.y + + u.z * v.z); + } + + function norm(v) { + + return Math.sqrt( + v.x * v.x + + v.y * v.y + + v.z * v.z); + } + + function getPerpendicularVector(v) { + + var u = { x: 0, y: 0, z: 0 }; + + if(v.x !== 0) + u = { x: 0, y: 1, z: 0 }; + else if(v.y !== 0) + u = { x: 1, y: 0, z: 0 }; + else + u = { x: 1, y: 0, z: 0 }; + + return crossProduct(v, u); + } + + function computeCirclularTrajectory(t, radius, normal, center) { + + // C: center, n: normal, u: perpendicular to n + // p(t) = r.cos(t).u + r.sin(t).(n x u) + C + + var u = getPerpendicularVector(normal); + + var v = crossProduct(u, normal); + + var pos = { + + x: radius * Math.cos(t) * u.x + radius * Math.sin(t) * v.x + center.x, + y: radius * Math.cos(t) * u.y + radius * Math.sin(t) * v.y + center.y, + z: radius * Math.cos(t) * u.z + radius * Math.sin(t) * v.z + center.z + }; + + return pos; + } + } + + ///////////////////////////////////////////////////////////////// + // load callback + // + ///////////////////////////////////////////////////////////////// + _self.load = function () { + + _self.tool = new ExplorerTool(_viewer); + + _viewer.toolController.registerTool(_self.tool); + + _viewer.toolController.activateTool(_self.tool.getName()); + + console.log('Autodesk.ADN.Viewing.Extension.Explorer loaded'); + return true; + }; + + ///////////////////////////////////////////////////////////////// + // unload callback + // + ///////////////////////////////////////////////////////////////// + _self.unload = function () { + + _viewer.toolController.deactivateTool(_self.tool.getName()); + + console.log('Autodesk.ADN.Viewing.Extension.Explorer unloaded'); + return true; + }; +}; + +Autodesk.ADN.Viewing.Extension.Explorer.prototype = + Object.create(Autodesk.Viewing.Extension.prototype); + +Autodesk.ADN.Viewing.Extension.Explorer.prototype.constructor = + Autodesk.ADN.Viewing.Extension.Explorer; + +Autodesk.Viewing.theExtensionManager.registerExtension( + 'Autodesk.ADN.Viewing.Extension.Explorer', + Autodesk.ADN.Viewing.Extension.Explorer); \ No newline at end of file diff --git a/Frontend/forgetTest2.html b/Frontend/forgetTest2.html new file mode 100644 index 0000000..31b822e --- /dev/null +++ b/Frontend/forgetTest2.html @@ -0,0 +1,241 @@ + + + + + + + + + + + + Showing A360 Shared files + + + + +
+
+
+
+ + +
+ + + + + + + + + + + \ No newline at end of file diff --git a/Frontend/js/forge/forgemodel.js b/Frontend/js/forge/forgemodel.js new file mode 100644 index 0000000..5f538e8 --- /dev/null +++ b/Frontend/js/forge/forgemodel.js @@ -0,0 +1,170 @@ +var viewer; + +const devices = [ + { + id: "Sensor 1", + position: { + x: -22.779729106182415, + y: 5.431043023608719, + z: 4.553068469137088, + }, + type: "combo", + sensorTypes: ["temperature", "co2"], + dbId: 1, + }, + { + id: "Sensor 2", + position: { + x: 0.20752051811882666, + y: 5.431043023608719, + z: 4.553068469137088, + }, + type: "combo", + sensorTypes: ["temperature", "co2"], + dbId: 2, + }, +]; + +var sensorStyleDefinitions = { + co2: { + url: "https://d2zqnmauvnpnnm.cloudfront.net/assets-1/images/co2.svg", + color: 0xffffff, + }, + temperature: { + url: "https://d2zqnmauvnpnnm.cloudfront.net/assets-1/images/thermometer.svg", + color: 0xffffff, + }, + default: { + url: "https://d2zqnmauvnpnnm.cloudfront.net/assets-1/images/circle.svg", + color: 0xffffff, + }, +}; + +// Initialize sensor values +let sensorVals = []; +for (let i = 0; i < devices.length; i++) { + sensorVals[i] = Math.random(); +} + +function launchViewer(urn) { + var options = { + env: 'AutodeskProduction', + getAccessToken: getForgeToken + }; + + Autodesk.Viewing.Initializer(options, () => { + viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer')); + viewer.start(); + var documentId = 'urn:' + urn; + Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure); + + + + //test + for (let i = 0; i < urns.length; i++) { + Autodesk.Viewing.Document.load(urns[i]["urn"], async (doc) => { + let viewables = doc.getRoot().getDefaultGeometry(); + let model = await viewer.loadDocumentNode(doc, viewables, { + preserveView: false, + keepCurrentModels: true, + placementTransform: (new THREE.Matrix4()).setPosition(urns[i]["xform"]), + keepCurrentModels: true, + globalOffset: { + x: 0, + y: 0, + z: 0 + } + }); + + await viewer.waitForLoadDone(); //!<<< Wait for loading materials, properties and geometries for this model (URN) + }); + } + + loadHeatmaps(viewer.getAllModels()[0]); //!<<< equals to viewer.model + + + + }); +} + +function onDocumentLoadSuccess(doc) { + var viewables = doc.getRoot().getDefaultGeometry(); + viewer.loadDocumentNode(doc, viewables).then(i => { + // documented loaded, any action? + }); + +} + +/** + * Autodesk.Viewing.Document.load() failuire callback. + */ +function onDocumentLoadFailure(viewerErrorCode) { + console.error("onDocumentLoadFailure() - errorCode:" + viewerErrorCode); +} + +function getForgeToken(callback) { + fetch('http://localhost:3604/api/forge/oauth/token').then(res => { + res.json().then(data => { + callback(data.dictionary.access_token, data.dictionary.expires_in); + }); + }); + //callback("eyJhbGciOiJSUzI1NiIsImtpZCI6IlU3c0dGRldUTzlBekNhSzBqZURRM2dQZXBURVdWN2VhIn0.eyJzY29wZSI6WyJkYXRhOndyaXRlIiwiZGF0YTpyZWFkIiwiYnVja2V0OnJlYWQiLCJidWNrZXQ6dXBkYXRlIiwiYnVja2V0OmNyZWF0ZSJdLCJjbGllbnRfaWQiOiJUQTNocXNGZnpRYk5PVVhLcGxkS1VLU2V3NFNKMjF3NSIsImF1ZCI6Imh0dHBzOi8vYXV0b2Rlc2suY29tL2F1ZC9hand0ZXhwNjAiLCJqdGkiOiJiemxzWE5qWElvZ2R1UjUzTUJkdlhrTTNTT01qeVB1bHJrMmdTVWJudGNTeDg1b01kRG1xejg3Z05jenJkRzhpIiwiZXhwIjoxNjY4MTgzMDM2fQ.VU3qLwTJ9nlXnomKCdk4y5UcgszGEO_zlvE7w5mWWajeBMwKLo-zw7LJEqUEajRksvssppR9SbVsjLSx-vDVc3DRhCo3jYTWKPT1T3wQrlkOSqLeIrAdnKdBDNBWKgrGJt_xcmXc3dZ3XNKf9L_F6Ex808rUlo6cem1mcPpKl1jCBDqKu1mAX7aDtZ65TTQZbGGhbG4HdnET-d1i5w4LunGN11UAHhDUW3n0SWWIBL27PiiUQONZttajhD5st6IngYLcjr93BYVyJmDF7-wm4WZlHSw2OnXIfbJcFXEd83uVv_Rej4UXjzZ0e6kHwzc2nvGvKSIFu3Nt7CabdR8CkA", 3599); +} + +async function loadHeatmaps(model) { + + const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization"); + + // Given a model loaded from Forge + const structureInfo = new Autodesk.DataVisualization.Core.ModelStructureInfo(model); + + const devices = [ + { + id: "Oficina 6", + name: "Oficina-", + position: { x: 22.475382737884104, y: 7.4884431474006163, z: 3.0 }, + sensorTypes: ["temperature", "humidity"] + } + ]; + + var offset = Autodesk.viewer.model.getGlobalOffset(); + removeOffset(devices[0], offset) + + // Generates `SurfaceShadingData` after assigning each device to a room. + + const shadingData = await Autodesk.structureInfo.generateSurfaceShadingData(devices); + + // Use the resulting shading data to generate heatmap from. + await dataVizExtn.setupSurfaceShading(model, shadingData); + + // Register color stops for the heatmap. Along with the normalized sensor value + // in the range of [0.0, 1.0], `renderSurfaceShading` will interpolate the final + // heatmap color based on these specified colors. + const sensorColors = [0x0000ff, 0x00ff00, 0xffff00, 0xff0000]; + + // Set heatmap colors for temperature + const sensorType = "temperature"; + dataVizExtn.registerSurfaceShadingColors(sensorType, sensorColors); + + // Function that provides sensor value in the range of [0.0, 1.0] + + function getSensorValue(surfaceShadingPoint, sensorType) { + // The `SurfaceShadingPoint.id` property matches one of the identifiers passed + // to `generateSurfaceShadingData` function. In our case above, this will either + // be "cafeteria-entrace-01" or "cafeteria-exit-01". + const deviceId = surfaceShadingPoint.id; + + // Read the sensor data, along with its possible value range + let sensorValue = readSensorValue(deviceId, sensorType); + const maxSensorValue = getMaxSensorValue(sensorType); + const minSensorValue = getMinSensorValue(sensorType); + + // Normalize sensor value to [0, 1.0] + sensorValue = (sensorValue - minSensorValue) / (maxSensorValue - minSensorValue); + return clamp(sensorValue, 0.0, 1.0); + } + + // This value can also be a room instead of a floor + const floorName = "01 - Entry Level"; + dataVizExtn.renderSurfaceShading(floorName, sensorType, getSensorValue); +}