ibms-dome/Frontend/js/forge/forgemodel.js

1019 lines
34 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

var viewer;
let fragProxy;
var targetFloorZ;
var elevatorSpeed;
var selector = "#forgeViewer";
let myDataList;
var levels;//剖面用
var lowerIdx;//剖面的下方樓層
var upperIdx;//剖面的上方樓層
function launchViewer(urn, callback, _selector = "#forgeViewer") {
selector = _selector;
var options = {
env: 'AutodeskProduction',
getAccessToken: getForgeToken
};
Autodesk.Viewing.Initializer(options, () => {
viewer = new Autodesk.Viewing.GuiViewer3D($(selector)[0]);
//viewer = new Autodesk.Viewing.Viewer3D(document.getElementById('forgeViewer'));
viewer.start();
var documentId = 'urn:' + urn;
Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
$(selector).on("autodesk:loaded", function (e, nodeIds) {
callback ? callback(viewer, nodeIds) : "";
})
//test
// for (let i = 0; i < urn.length; i++) {
// Autodesk.Viewing.Document.load(urn[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(urn[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 launchViewerForHotspot(urn, callback, _selector = "#forgeViewer") {
selector = _selector;
var av = Autodesk.Viewing;
var options = {
env: 'AutodeskProduction',
getAccessToken: getForgeToken
};
Autodesk.Viewing.Initializer(options, () => {
viewer = new Autodesk.Viewing.GuiViewer3D($(selector)[0]);
viewer.start();
var documentId = 'urn:' + urn;
viewer.addEventListener(av.GEOMETRY_LOADED_EVENT, addHotPoint, {
once: true,
});
Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
$(selector).on("autodesk:loaded", function (e, nodeIds) {
callback ? callback(viewer, nodeIds) : "";
})
});
}
function launchViewerNoTools(urn, callback) {
var options = {
env: 'AutodeskProduction',
getAccessToken: getForgeToken
};
Autodesk.Viewing.Initializer(options, () => {
//viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer'));
viewer = new Autodesk.Viewing.Viewer3D($(selector)[0]);
viewer.start();
var documentId = 'urn:' + urn;
Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
$(selector).on("autodesk:loaded", function (e, nodeIds) {
callback ? callback(viewer, nodeIds) : "";
})
});
}
function getAllLeafComponents(viewer, callback) {
var cbCount = 0;
var tree;
var jsData = []
function getLeafComponentsRec(current, parent) {
cbCount++;
if (tree.getChildCount(current) != 0) {
tree.enumNodeChildren(current, function (children) {
getLeafComponentsRec(children, current);
}, false);
}
var nodeName = viewer.model.getInstanceTree().getNodeName(current)
jsData.push({ id: current, parent: parent, text: nodeName })
if (--cbCount == 0) callback(jsData);
}
viewer.getObjectTree(function (objectTree) {
tree = objectTree;
var rootId = tree.getRootId()
var nodeName = viewer.model.getInstanceTree().getNodeName(rootId)
jsData.push({ id: rootId, parent: '#', text: nodeName })
var allLeafComponents = getLeafComponentsRec(rootId, '#');
});
}
class elevator3D {
constructor(option = {}) {
this.ele = option.element;
this.viewer = option.viewer;
this.nodeId = option.nodeId;
this.speed = option.speed ?? 0.03;
this.fragProxys = [];
this.fragProxy = null;
this.initCallback = option.inited ?? null;
this.movStatus = 0;
this.targetFloorZ = 0;
this.floorHeight = option.floorHeight ?? [{}];
this.init();
}
setTreeFrag = function (callback) {
let tree = this.viewer?.model?.getData().instanceTree;
if (!tree) {
return;
}
let nodeId = this.nodeId;
if (nodeId) {
let childCnt = tree.getChildCount(nodeId);
let curIdx = 1;
this.fragProxys.filter(x => x.nodeId == nodeId).forEach((x) => {
let idx = this.fragProxys.indexOf(x);
this.fragProxys.splice(idx, 1);
})
tree.enumNodeFragments(nodeId, (frag) => {
let fragProxy = this.viewer.impl.getFragmentProxy(this.viewer.model, frag);
this.fragProxys.push({ nodeId: nodeId, fragId: frag, frag: fragProxy });
fragProxy.getAnimTransform();
let fragPosition = new THREE.Vector3(0, 0, 0);// 一樓0 二樓15 三樓 26
fragProxy.position = fragPosition;
fragProxy.updateAnimTransform();
if (childCnt == curIdx) {
this.initCallback ? this.initCallback() : "";
callback ? callback() : "";
}
curIdx++;
}, true);
}
this.viewer.impl.sceneUpdated(true);
if (typeof $(this.ele)[0]._elevator3D == "undefined") {
$(this.ele)[0]._elevator3D = [];
}
$(this.ele)[0]._elevator3D.push({ nodeId: nodeId, obj: this });
}
init = function (callback = null) {
this.setTreeFrag(callback);
}
setElevatorFloor = function (floor) {
this.targetFloorZ = this.floorHeight.filter(x => x.floor == floor)[0]?.height ?? 0;
}
setElevatorSpeed = function (speed) { //0.01 ~ 1
this.speed = speed;
}
movElevator = function () {
let tree = this.viewer.model.getData().instanceTree;
let nodeId = this.nodeId;
let fragProxyZ = 0;
let fragProxy = this.fragProxys.filter(x => x.nodeId == nodeId)[0]?.frag;
if (!fragProxy) {
return;
}
changeColor(nodeId);
if ((this.movStatus == 2 && fragProxy.position.z.roundDecimal(2) < this.targetFloorZ.roundDecimal(2)) ||
(this.movStatus == 1 && fragProxy.position.z.roundDecimal(2) > this.targetFloorZ.roundDecimal(2)) ||
fragProxy.position.z.roundDecimal(2) == this.targetFloorZ.roundDecimal(2)) {
stoped(this);
}
//if (movStatus == 0) {
// recoverTransparentBuilding();
// return;
//}
if (fragProxy.position.z.roundDecimal(2) > this.targetFloorZ.roundDecimal(2)) {
this.movStatus = 2;
}
else if (fragProxy.position.z.roundDecimal(2) < this.targetFloorZ.roundDecimal(2)) {
this.movStatus = 1;
}
tree.enumNodeFragments(nodeId, (frag) => {
let fragProxy = this.viewer.impl.getFragmentProxy(this.viewer.model, frag);
fragProxy.getAnimTransform();
//let fragPosition = new THREE.Vector3(0, 0, 15);// 一樓0 二樓15 三樓 26
if (this.movStatus == 2) {
fragProxy.position.z -= this.speed;
}
else if (this.movStatus == 1) {
fragProxy.position.z += this.speed;
}
this.fragProxys.filter(x => x.nodeId == nodeId && x.fragId == frag)[0].frag.position.z = fragProxy.position.z;
fragProxyZ = fragProxy.position.z;
fragProxy.updateAnimTransform()
}, true);
this.viewer.impl.sceneUpdated(true);
/*setTransparentBuilding();*/
let movElevator = $(this.ele)[0]._elevator3D.filter(x => x.nodeId == this.nodeId)[0]?.obj.movElevator.bind(this);
if (this.movStatus == 2) {
if (fragProxyZ >= this.targetFloorZ) {
requestAnimationFrame(() => {
movElevator();
});
} else {
stoped(this);
}
}
else if (this.movStatus == 1) {
if (fragProxyZ <= this.targetFloorZ) {
requestAnimationFrame(() => {
movElevator();
});
} else {
stoped(this);
}
} else {
stoped(this);
}
function stoped(obj) {
obj.movStatus = 0;
/*recoverTransparentBuilding();*/
hideColor(nodeId);
return;
}
//let fragPosition = new THREE.Vector3(position);// 一樓0 二樓15 三樓 26
//fragProxy.position = fragPosition;
//fragProxy.updateAnimTransform();
//viewer.impl.sceneUpdated(true);
}
}
function onDocumentLoadSuccess(doc, eleOption) {
var viewables = doc.getRoot().getDefaultGeometry();
viewer.loadDocumentNode(doc, viewables).then(i => {
// documented loaded, any action?
});
// viewer.addEventListener(Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT, (args) => {
// var currSelection = viewer.getSelection();
// var domElem = document.getElementById('id_printer');
// domElem.innerText = currSelection[0];
// });
viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, function () {
let instanceTree = viewer.model.getData().instanceTree;
console.log(instanceTree.nodeAccess)
allDbIdsStr = Object.keys(instanceTree.nodeAccess.dbIdToIndex);
getNodeIdByDbIds("【電梯】", (nodeIds) => {
$(selector).trigger("autodesk:loaded", nodeIds);
});
});
}
// 輔助函數,使用 Promise 封裝 viewer.getProperties 函數
function viewerGetProperties(dbIds,attributeName = null) {
// 在這裡,我們使用 viewer.getProperties 函數的成功回調函數作為 resolve 函數,
// 並使用 viewer.getProperties 函數的失敗回調函數作為 resolve 函數的參數
// 這樣,當 viewer.getProperties 函數成功時Promise 會傳回 properties 物件;
// 當 viewer.getProperties 函數失敗時Promise 會傳回 null。
return new Promise((resolve, reject) => {
let option = {};
if (attributeName != null) {
option.propFilter = [attributeName]; // 限制只返回指定的屬性
}
viewer.model.getBulkProperties2(dbIds, option, // 取得指定元素的屬性信息
function (elements) {
resolve(elements); // 成功時傳回 elements 物件
})
});
}
// 輔助函數,使用 Promise 封裝 viewer.search 函數
async function getNodeIdBySearch(text) {
return new Promise((resolve, reject) => {
viewer.search(text, (e) => { // 在 3D 模型中搜索具有指定文本的元素
resolve(e); // 成功時傳回搜索結果
}, (e) => {
resolve(null); // 失敗時傳回 null
})
})
}
// 主函數 - 透過 model 全部 node 取得特定 nodeId
async function getNodeIdByDbIds(checkName = "【電梯】", callback = null) {
let evelMap = new Map();
let hasElement = false; // 設置是否有 【tag_id】的node
let targetNodeIds = await getNodeIdBySearch(checkName);
let elements = await viewerGetProperties(targetNodeIds,"【tag_id】");
// 從 elements 中篩選出包含 【tag_id】 屬性的元素
elements = elements.filter(x => x.properties.findIndex(y => y.displayName == "【tag_id】" && y.displayValue.indexOf(checkName) != -1) != -1);
if (elements) {
hasElement = true;
}
for (var e of elements) {
let name = e.properties[0].displayValue; // 獲取元素的 【tag_id】 屬性
let chiElements = null;
// 獲取 node 元素的子元素信息
targetNodeIds = await viewerGetProperties([e.dbId], "child");
// 二次篩選
chiElements = targetNodeIds.filter(x => x.properties.findIndex(y => y.displayName == "child") != -1);
// 獲取子元素的 nodeId
targetNodeIds = chiElements.map(x => x.properties[0].displayValue);
// 獲取子元素的屬性信息
chiElements = await viewerGetProperties(targetNodeIds);
// 將 node 元素的 【tag_id】 屬性和子元素的 nodeId 加入 Map 中
evelMap.set(name, chiElements[0]?.dbId);
}
if (!hasElement) {
callback ? callback([]) : "";
return [];
}
callback ? callback(evelMap) : "";
return evelMap;
}
function setElevatorFloor(floor) {
if (floor == 0)
targetFloorZ = 0;
else if (floor == 1)
targetFloorZ = 15;
else if (floor == 2)
targetFloorZ = 26;
}
function setElevatorSpeed(speed) { //0.01 ~ 1
elevatorSpeed = speed;
}
function movElevator() {
let tree = viewer.model.getData().instanceTree;
let nodeId = 10952;
let fragProxyZ = 0;
var movStatus = 0; // 0=no 1=up 2=down
if (fragProxy.position.z > targetFloorZ) {
movStatus = 2
}
else if (fragProxy.position.z < targetFloorZ) {
movStatus = 1
}
if (movStatus == 0) {
return;
}
tree.enumNodeFragments(nodeId, function (frag) {
fragProxy = viewer.impl.getFragmentProxy(viewer.model, frag);
fragProxy.getAnimTransform();
//let fragPosition = new THREE.Vector3(0, 0, 15);// 一樓0 二樓15 三樓 26
if (movStatus == 2) {
fragProxy.position.z -= elevatorSpeed;
}
else if (movStatus == 1) {
fragProxy.position.z += elevatorSpeed;
}
fragProxyZ = fragProxy.position.z;
fragProxy.updateAnimTransform()
});
viewer.impl.sceneUpdated(true);
if (movStatus == 2) {
if (fragProxyZ >= targetFloorZ) {
requestAnimationFrame(movElevator);
}
}
else if (movStatus == 1) {
if (fragProxyZ <= targetFloorZ) {
requestAnimationFrame(movElevator);
}
}
//let fragPosition = new THREE.Vector3(position);// 一樓0 二樓15 三樓 26
//fragProxy.position = fragPosition;
//fragProxy.updateAnimTransform();
//viewer.impl.sceneUpdated(true);
}
function getAllDbIds(viewer) {
var instanceTree = viewer.model.getData().instanceTree;
var allDbIdsStr = Object.keys(instanceTree.nodeAccess.dbIdToIndex);
return allDbIdsStr.map(function (id) { return parseInt(id) });
}
/**
* Autodesk.Viewing.Document.load() failuire callback.
*/
function onDocumentLoadFailure(viewerErrorCode) {
console.error("onDocumentLoadFailure() - errorCode:" + viewerErrorCode);
}
function getForgeToken(callback) {
fetch(forgeTokenBase.url).then(res => {
res.json().then(data => {
let limitResType = ["object", "undefined"];
let access_token = data;
$.each(forgeTokenBase.res_access_token, (idx, dict) => {
access_token = access_token[dict];
})
let expires_in = data;
$.each(forgeTokenBase.res_expires_in, (idx, dict) => {
expires_in = expires_in[dict];
})
if (limitResType.includes(typeof access_token) || limitResType.includes(typeof expires_in)) {
access_token = "", expires_in = "";
throw "access_token or expires_in on the ForgeTokenBase object for getting forge token by URL is not the correct path.";
}
callback(access_token, expires_in);
});
});
//callback("eyJhbGciOiJSUzI1NiIsImtpZCI6IlU3c0dGRldUTzlBekNhSzBqZURRM2dQZXBURVdWN2VhIn0.eyJzY29wZSI6WyJkYXRhOndyaXRlIiwiZGF0YTpyZWFkIiwiYnVja2V0OnJlYWQiLCJidWNrZXQ6dXBkYXRlIiwiYnVja2V0OmNyZWF0ZSJdLCJjbGllbnRfaWQiOiJUQTNocXNGZnpRYk5PVVhLcGxkS1VLU2V3NFNKMjF3NSIsImF1ZCI6Imh0dHBzOi8vYXV0b2Rlc2suY29tL2F1ZC9hand0ZXhwNjAiLCJqdGkiOiJiemxzWE5qWElvZ2R1UjUzTUJkdlhrTTNTT01qeVB1bHJrMmdTVWJudGNTeDg1b01kRG1xejg3Z05jenJkRzhpIiwiZXhwIjoxNjY4MTgzMDM2fQ.VU3qLwTJ9nlXnomKCdk4y5UcgszGEO_zlvE7w5mWWajeBMwKLo-zw7LJEqUEajRksvssppR9SbVsjLSx-vDVc3DRhCo3jYTWKPT1T3wQrlkOSqLeIrAdnKdBDNBWKgrGJt_xcmXc3dZ3XNKf9L_F6Ex808rUlo6cem1mcPpKl1jCBDqKu1mAX7aDtZ65TTQZbGGhbG4HdnET-d1i5w4LunGN11UAHhDUW3n0SWWIBL27PiiUQONZttajhD5st6IngYLcjr93BYVyJmDF7-wm4WZlHSw2OnXIfbJcFXEd83uVv_Rej4UXjzZ0e6kHwzc2nvGvKSIFu3Nt7CabdR8CkA", 3599);
}
//------------------ 熱圖 -------------------------------
class ADHeatMaps {
constructor(option = {}) {
this.devices = option.devices ?? [];
this.checkNodeString = "【ROOM】";
this.tempVals = [];
this.roomDbIds = []; //房間 dbId
this.model = null;
this.dataVizExtn = null;
this.onComplete = option.onComplete ?? null;
this.init();
}
init = async function () {
// 載入 Autodesk Viewer 的資料視覺化擴充功能
const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
// 儲存 Viewer 的模型
this.model = viewer.model;
const {
SurfaceShadingData,
SurfaceShadingPoint,
SurfaceShadingNode,
} = Autodesk.DataVisualization.Core;
let nodeIds = await getNodeIdByDbIds(this.checkNodeString);
nodeIds = Array.from(nodeIds);
nodeIds = nodeIds.map(x => { return { room: x[0] , nodeId: x[1]} });
this.roomDbIds = nodeIds;
// 建立一個 SurfaceShadingData 物件,並將 SurfaceShadingNode 加入到該物件中
const heatmapData = new SurfaceShadingData();
$.each(this.roomDbIds.map(x => x.nodeId), (idx, rDbid) => {
// 建立一個名為 "Room Panel" 的 SurfaceShadingNode 物件,並將房間的模型給傳入,只在該房間呈現溫度
const shadingNode = new SurfaceShadingNode("RoomPanel" + rDbid, rDbid);
// 遍歷每個設備,建立一個 SurfaceShadingPoint 物件並加入到 SurfaceShadingNode 中,透過這些設備渲染溫度
this.devices.filter(x => x.roomDbId == rDbid).forEach((device) => {
const shadingPoint = new SurfaceShadingPoint(
device.id,
device.position,
device.sensorTypes
);
shadingNode.addPoint(shadingPoint);
device.temp = 0;
});
heatmapData.addChild(shadingNode);
})
// 將資料初始化並顯示在模型上
heatmapData.initialize(this.model);
// 對模型做表面顏色的渲染
await dataVizExtn.setupSurfaceShading(this.model, heatmapData);
// 對 "temperature" 的溫度設定兩種顏色:紅色和藍色
dataVizExtn.registerSurfaceShadingColors("temperature", [0x0000ff, 0xff0000]);
this.dataVizExtn = dataVizExtn;
$.each(this.roomDbIds.map(x => x.nodeId), (idx, rDbid) => {
this.dataVizExtn.renderSurfaceShading("RoomPanel" + rDbid, "temperature", this.getSensorValue.bind(this));
})
/*this.changeTemp(this.tempVal);*/
this.onComplete ? this.onComplete() : "";
}
getSensorValue = function(device, sensorType) {
let dev = this.devices.filter(x => x.id == device.id)[0];
return dev.temp / 40;
}
// 改變溫度
changeTemp = function (devId, temp) {
this.tempVal = temp;
// 透過 device id 取得 roomDbId
this.devices.forEach((dev) => {
if (devId == dev.id) {
dev.temp = temp;
}
})
this.dataVizExtn.updateSurfaceShading(this.getSensorValue.bind(this));
//if (rDbid != null) {
// // 取得新的溫度值
// let getSensorValue = (device, sensorType) => {
// return this.tempVal / 40;
// }
// // 對 "Room Panel" 做表面顏色的渲染,並使用新的溫度值
// this.dataVizExtn.renderSurfaceShading("RoomPanel" + rDbid, "temperature", getSensorValue);
//}
}
}
function setTransparentBuilding() {
//allDbIdsStr.forEach((dbId) => {
// setTransparency(dbId, 0.2);
//})
for (var i = 0; i < allDbIdsStr.length; i++) {
setTransparency(parseInt(allDbIdsStr[i]), 0.2);
}
}
function recoverTransparentBuilding() {
//allDbIdsStr.forEach((dbId) => {
// setTransparency(dbId, 1);
//})
for (var i = 0; i < allDbIdsStr.length; i++) {
setTransparency(parseInt(allDbIdsStr[i]), 1);
}
}
//設定模型 透明度
function setTransparency(nodeId, opacity) {
var model = viewer.model;
//var nodeId = 1633;
var fragList = viewer.model.getFragmentList();
var fragIds = []
model.getData().instanceTree.enumNodeFragments(
nodeId, (fragId) => {
fragIds.push(fragId)
});
fragIds.forEach((fragId) => {
//获取材质
var material = fragList.getMaterial(fragId);
if (material) {
//设置透明度
material.opacity = opacity;//0.5;
material.transparent = true;
//标记更新
material.needsUpdate = true;
}
})
//更新viewer
viewer.impl.invalidate(true, true, true);
}
function changeColor(nodeId) {//電梯變綠色
let instanceTree = viewer.model.getData().instanceTree;
instanceTree.enumNodeChildren(nodeId, function (chiNodeId) {
var color = new THREE.Vector4(0, 1, 0, 1);
viewer.setThemingColor(chiNodeId, color);
}, true)
}
function hideColor(nodeId) {//顏色改成透明
let instanceTree = viewer.model.getData().instanceTree;
instanceTree.enumNodeChildren(nodeId, function (chiNodeId) {
var color = new THREE.Vector4(0, 1, 0, 0);
viewer.setThemingColor(chiNodeId, color);
}, true)
}
//------------------ 紀錄熱點座標 ---------------
function getHopspotPoint(data) {
//var av = Autodesk.Viewing;
myDataList = data;
//viewer.addEventListener(av.GEOMETRY_LOADED_EVENT, addHotPoint, {
// once: true,
//});
}
//-------------------- end ----------------------
//------------------- 加入熱點 -----------------
async function addHotPoint(data) {
var viewer = data.target;
const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
const DataVizCore = Autodesk.DataVisualization.Core;
const viewableType = Autodesk.DataVisualization.Core.ViewableType.SPRITE;//DataVizCore.ViewableType.SPRITE;
const spriteColor = new THREE.Color(0xffffff);
const dbIdStart = 10;
const dbIdEnd = 19;
let spriteIcon = "/file/img/forge/hotspot.svg";
if (location.href.indexOf("localhost:5966") != -1) {
spriteIcon = "/img/forge/hotspot.svg";
}
const style = new DataVizCore.ViewableStyle(viewableType, spriteColor, spriteIcon);
//熱點 點擊事件註冊
viewer.addEventListener(DataVizCore.MOUSE_CLICK, onSpriteClicked);// SPRITE_SELECTED
//viewer.addEventListener(
// Autodesk.Viewing.SELECTION_CHANGED_EVENT,
// onSelectionChange
//);
const viewableData = new DataVizCore.ViewableData();
viewableData.spriteSize = 24; // Sprites as points of size 24 x 24 pixels
myDataList.forEach((myData, index) => {
const dbId = 10 + index;
const myPosition = myData.position;
const viewable = new DataVizCore.SpriteViewable(myPosition, style, dbId);
myData._dbId = dbId;
viewableData.addViewable(viewable);
});
await viewableData.finish();
dataVizExtn.addViewables(viewableData);
$(selector).trigger("autodesk:complete:sprite", { myDataList });
//---------------- 熱點點擊事件 --------------------
function onSpriteClicked(event) {
event.hasStopped = true;
if (event != undefined && event != null) {
if (event.dbId >= dbIdStart && event.dbId <= dbIdEnd) {//event.dbId > 0 && event.dbId < 19
console.log(`Sprite clicked: ${event.dbId}`);
openHotspotModal();
for (let i = dbIdStart; i <= dbIdEnd; i++) {
changeColorForHotspot(i, false);
changeScaleForHotspot(i, false);
}
let myData = myDataList.filter(x => x._dbId == event.dbId)[0];
$(selector).trigger("autodesk:click:sprite", { event, myData });
} else {
$(selector).trigger("autodesk:clickOut:sprite", { event });
}
if (event.clickInfo != null) {
//document.getElementById('deviceName').innerHTML = viewer.model.getInstanceTree().getNodeName(event.clickInfo.dbId);
//document.getElementById('deviceDbid').innerHTML = event.clickInfo.dbId;
//document.getElementById('devicePosition').innerHTML = "(" + (event.clickInfo.point.x).toFixed(2) + ", " + (event.clickInfo.point.y).toFixed(2) + ", " + (event.clickInfo.point.z).toFixed(2) + ")";
console.log(`event>> dbId: ${event.clickInfo.dbId}, id: ${event.clickInfo.object.id}, position.x: ${event.clickInfo.point.x}, y: ${event.clickInfo.point.y}, z: ${event.clickInfo.point.z}, name: ${viewer.model.getInstanceTree().getNodeName(event.clickInfo.dbId)}`);
}
}
}
//function onSelectionChange(event) {
// if (event != undefined && event != null) {
// const dbIds = event.dbIdArray;
// if (dbIds.length > 0) {
// // 處理已選取元件的邏輯
// $(selector).trigger("autodesk:click:sprite", event);
// //openHotspotModal();
// console.log(`------ name: ${viewer.model.getInstanceTree().getNodeName(dbIds)} , dbId: ${dbIds}`);//, id: ${event.clickInfo.object.id}, position.x: ${event.clickInfo.point.x}, y: ${event.clickInfo.point.y}, z: ${event.clickInfo.point.z}
// } else {
// // 處理沒有選取元件的邏輯
// $(selector).trigger("autodesk:click:sprite", event);
// console.log("no item");
// }
// }
//}
}
// 熱點 更換顏色
async function changeColorForHotspot(dbId, type = true) {
const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
let spriteColorFocus = new THREE.Color(0x00ffe1);
if (!type) {
spriteColorFocus = new THREE.Color(0xffffff);
}
const viewablesToUpdate = dbId;
dataVizExtn.invalidateViewables(viewablesToUpdate, (viewable) => {
return {
color: spriteColorFocus,
};
});
}
// 熱點 更換大小
async function changeScaleForHotspot(dbId, type = true) {
const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
let scale = 1;
if (type) {
scale = 1.2;
}
const viewablesToUpdate = dbId;
dataVizExtn.invalidateViewables(viewablesToUpdate, (viewable) => {
return {
scale: scale, // Restore the viewable size
//url: "https://.../circle.svg",
};
});
}
//------------------- end --------------
//----------------- 開關熱點小視窗 ----------------------
function openHotspotModal() {
//var modal = document.getElementById("hotspotModal");
//modal.style.display = "block";
//$("#pills-register-tab").removeClass("active");
//$("#pills-alarm-tab").removeClass("active");
//$("#pills-operation-tab").removeClass("active");
//$("#pills-login-tab").tab("show");
}
function closeHotspotModal() {
//var modal = document.getElementById("hotspotModal");
//modal.style.display = "none";
}
//------------------ end --------------------------------
//------------------ 熱圖 -------------------------------
async function loadHeatmaps(model) {
const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
//取三個空調設備的位置打點
const devices = [
{
id: "Oficina 5",
//name: "Oficina-",
position: { x: 6.98, y: -19.00, z: 16.86 }, // x: 0, y: 25, z: -2.5 (-4.93, -20.61, 16.86)
sensorTypes: ["temperature", "humidity"]
},
{
id: "Oficina 4",
//name: "Oficina-",
position: { x: 35.85, y: -2.24, z: 16.86 }, // x: 0, y: 25.03, z: -2.52 (23.94, -3.85, 16.86)
sensorTypes: ["temperature", "humidity"]
},
{
id: "Oficina 3",
//name: "Oficina-",
position: { x: 6.98, y: -2.24, z: 16.86 }, // x: 0, y: 25.03, z: -2.52 (-4.93, -3.85, 16.86)
sensorTypes: ["temperature", "humidity"]
}
];
//冷氣N5: (-4.93, -20.61, 16.86), N4: (23.94, -3.85, 16.86), N3: (-4.93, -3.85, 16.86)
// Initialize sensor values
let sensorVals = [];
for (let i = 0; i < devices.length; i++) {
sensorVals[i] = Math.random();
}
const roomDbIds = [];
roomDbIds.push(7567);
const {
SurfaceShadingData,
SurfaceShadingPoint,
SurfaceShadingNode,
} = Autodesk.DataVisualization.Core;
const shadingNode = new SurfaceShadingNode("Room Panel", roomDbIds);
devices.forEach((device) => {
const shadingPoint = new SurfaceShadingPoint(
device.id,
device.position,
device.sensorTypes
);
shadingNode.addPoint(shadingPoint);
});
const heatmapData = new SurfaceShadingData();
heatmapData.addChild(shadingNode);
heatmapData.initialize(model);
// Setup surface shading
await dataVizExtn.setupSurfaceShading(model, heatmapData);
dataVizExtn.registerSurfaceShadingColors("temperature", [0xff0000, 0x0000ff]);
function getSensorValue(device, sensorType) {
return sensorVals[parseInt(device.id.slice(-1)) - 1];
}
dataVizExtn.renderSurfaceShading("Room Panel", "temperature", getSensorValue);
setInterval(() => {
// Modify sensor values.
for (let i = 0; i < devices.length; i++) {
sensorVals[i] = Math.random();
}
dataVizExtn.updateSurfaceShading(getSensorValue);
}, 2000);
}
//------------------ end --------------------------------
async function loadHeatmapsForFloor(model) {
const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
//x: -17.33, y: 51.03, z: -2.52
const devices = [
{
id: "Oficina 5",
//name: "Oficina-",
position: { x: 6.98, y: -19.00, z: 16.86 }, // x: 0, y: 25, z: -2.5 (-4.93, -20.61, 16.86)
sensorTypes: ["temperature", "humidity"]
},
{
id: "Oficina 4",
//name: "Oficina-",
position: { x: 35.85, y: -2.24, z: 16.86 }, // x: 0, y: 25.03, z: -2.52 (23.94, -3.85, 16.86)
sensorTypes: ["temperature", "humidity"]
},
{
id: "Oficina 3",
//name: "Oficina-",
position: { x: 6.98, y: -2.24, z: 16.86 }, // x: 0, y: 25.03, z: -2.52 (-4.93, -3.85, 16.86)
sensorTypes: ["temperature", "humidity"]
}
];
// Initialize sensor values
let sensorVals = [];
for (let i = 0; i < devices.length; i++) {
sensorVals[i] = Math.random();
}
const roomDbIds = [];
roomDbIds.push(7567);
const {
SurfaceShadingData,
SurfaceShadingPoint,
SurfaceShadingNode,
} = Autodesk.DataVisualization.Core;
const shadingNode = new SurfaceShadingNode("Room Panel", roomDbIds);
devices.forEach((device) => {
const shadingPoint = new SurfaceShadingPoint(
device.id,
device.position,
device.sensorTypes
);
shadingNode.addPoint(shadingPoint);
});
const heatmapData = new SurfaceShadingData();
heatmapData.addChild(shadingNode);
heatmapData.initialize(model);
// Setup surface shading
await dataVizExtn.setupSurfaceShading(model, heatmapData);
//dataVizExtn.registerSurfaceShadingColors("co2", [0x00ff00, 0xff0000]);
dataVizExtn.registerSurfaceShadingColors("temperature", [0xff0000, 0x0000ff]);
function getSensorValue(device, sensorType) {
return sensorVals[parseInt(device.id.slice(-1)) - 1];
}
dataVizExtn.renderSurfaceShading("Room Panel", "temperature", getSensorValue);
setInterval(() => {
// Modify sensor values.
for (let i = 0; i < devices.length; i++) {
sensorVals[i] = Math.random();
}
dataVizExtn.updateSurfaceShading(getSensorValue);
}, 2000);
}
//
async function loadHeatmap() {
const model = viewer.model;
loadHeatmaps(model);
}
async function loadHeatmapForFloor() {
const model = viewer.model;
loadHeatmapsForFloor(model);
}
//------------ 剖面 ----------------------
async function getRemoteLevels() {
const aecData = await Autodesk.Viewing.Document.getAecModelData(this.viewer.model.getDocumentNode());
if (!aecData.levels) return null;
const levels2 = aecData.levels;
levels2.sort((a, b) => b.elevation - a.elevation);
return levels2;
}
async function getLevelsData(lowerFloor, upperFloor) {
const data = await this.getRemoteLevels();
for (var i = 0; i < data.length; i++) {
if ((data[i].name).indexOf(lowerFloor) != -1) {
lowerIdx = i;
}
if ((data[i].name).indexOf(upperFloor) != -1) {
upperIdx = i;
}
}
this.levels = data;
profile();
}
function getCutPlaneParam(idx, n) {
if (idx < 0 || !n) return;
const level = this.levels[idx];
if (!level) return;
const model = this.viewer.model;
const globalOffset = model.getData().globalOffset;
const units = model.getUnitString();
const elevRaw = Autodesk.Viewing.Private.convertUnits('ft', units, 1, level.elevation);
let d = elevRaw - globalOffset.z - 0.5;
if (n == 1)
d = -1 * d;
return new THREE.Vector4(0, 0, n, d);
}
function profile() {
//const upperIdx = 6;
const upperCutPlaneParam = this.getCutPlaneParam(upperIdx, 1);
//const lowerIdx = 7;
const lowerCutPlaneParam = this.getCutPlaneParam(lowerIdx, -1);
this.viewer.setCutPlanes([upperCutPlaneParam, lowerCutPlaneParam]);
}
//----------------- end -----------------------------------------------