# ht-dnjg **Repository Path**: sinceseason/ht-dnjg ## Basic Information - **Project Name**: ht-dnjg - **Description**: No description available - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2020-07-31 - **Last Updated**: 2020-12-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ht for web ## 参考链接 - [手册](https://www.hightopo.com/guide2/) - [api文档](https://www.hightopo.com/guide/doc/) ## 命名规则 ### 名词解释(二级场景(一栋楼一个场景) 三级场景(一层楼一个场景)) - A0 B0 C0 D0 E1 E2a1 E2a2 E2b1 E2b2 E2c1 E2c2 E2d1 E2d2 #### 一级场景(需要被点击做跳转的层加tag) A0 #### 二级场景 - 场景名(须与一级场景中tag保持一致) A0 - 跳转 A0-1F - 建筑 JZ - 管道 GD - 设备 SB - 巡检 XJ - 用气点 YQD #### 三级场景 - 场景名(须与二级场景中跳转tag保持一致) A0-1F - 建筑 JZ - 管道 GD - 设备 SB - 巡检 XJ - 功能分区 GNFQ #### 不需要拆分的bim 灶具设备生成快照时命名ZJ ### ~~管线&楼层相关~~ - ~~SYQ-A1-1F~5F //商业区A1 1-5楼~~ - ~~SYQ-A1-PIPES //商业区A1 所有管线~~ - ~~SYQ-A1-1F-GUAN // 商业区 A1 1楼 管线~~ - ~~SYQ-A1-ALARMS //商业区 A1 所有报警系统~~ - ~~SYQ-A1-1F-BAOJING //商业区 A1 1楼 报警~~ ### ~~label 相关~~ - ~~SYQ-A1-YQDW //商业区 A1 用气点位~~ - ~~SYQ-A1-XJS //商业区 A1 所有巡检点位~~ - ~~SYQ-A1-1F-XUNJIAN //商业区 A1 1楼 巡检~~ ## 模型拆分 ### 要单独控制 楼板,墙,楼梯 这些obj的显示隐藏,或者颜色这些style, 需要拆分模型后单独导入 n 个对应的obj文件,在一个obj里面无法做到单独控制 ### 导入obj模型后,会出现多个节点(node),可以通过 node.name 里是否包含某些特殊字段来实现部分控制的功能 ```js ht.Default.loadObj('/obj/dnjgjz1.obj', '/obj/dnjgjz1.mtl', cb) => modelMap ``` - **优点**是只需导入一个文件 - **缺点**是后期模型更改或者需要在 name 中增加某个字段会比较麻烦 > 建议使用第一种,便于后期维护 ### 通过BIM插件导入,自动拆分模型 ## 属性查询 ### **无法查询属性** 因为导入obj之后,obj中只包含顶点等信息 ## 建模 ### 建模注意点: 1. 模型: - (1)模型为可编辑面片 - (2)导出时选三角面 - (3)场景总面数尽量不超过90万 2. 贴图: - (1)分辨率2的n次方,如256*512等等 - (2)格式jpg/png - (3)mtl文件中贴图仅保留贴图名称 - (4)名称使用英文(勿用特殊字符) ### 复杂模型如何建模 复杂的模型例如:阀门、弯头等管件无法画出来,需要obj导入 ## 编辑器相关 ### 一个场景里有多个obj,点击某个后控制其他某个 obj 的显示和隐藏 1. 其他图元给个标签 tag 2. 用事件处理中的参数,可以找到给过标签的图元, 然后做处理 ```js var otherOne = view.dm().getDataByTag('tag名') otherOne.s('3d.visible', !otherOne.s('3d.visible')) ``` ### 实现给一个场景里某个模型加点击事件跳转到另一个场景 ```js view.dm().clear() view.deserialize('新场景 url') ``` 预览页面中就可以通过交互进行场景切换了 ### 编辑器里写入和查询属性 1. 写入属性:选中相应管道,打开浏览器控制台输入 `editor3d.ld.a(key, value)` 2. 读取属性:`var value = data.a('pipe1')` ### 双击聚焦交互事件: ```js onDoubleClick:function(event,data,view){ view.flyTo(data,{animation:true,ratio:0.6}) //data.s('3d.visible',false); } ``` ### 导入的obj模型大小限制 场景总面数一般十几万左右,模型基本都没超过 10m,单个设备一般构建在 m 以内,甚至小到几十k,HT 定位的大部分还是运维的系统,用户只需要看得清是个什么样的设备即可。 几十兆导入应该是没问题的,当时放在web上,光资源请求就需要十来秒,建议建模时尽量控制面数。 ### 合并多个obj并添加事件 - 右下列表中多选节点,按**ctrl+g**组合,合并为一个block > 取消组合快捷键 **ctrl+shift+g** - block不支持on开头的事件,可以监听doubleClickData事件 ```js g3d.mi(e=>{ if(e.kind='doubleClickData'){ console.log(e.data) } }) ``` - 将监听函数写在,场景属性**反序列化后**中 ### 创建父子级关系 [参考链接](https://www.hightopo.com/guide/guide/core/datamodel/ht-datamodel-guide.html) 所有文字都给个相同父级, `father.getChildren()` 一次性获取 ## 显示效果 ### 景深 ```js g3d.enablePostProcessing('Dof', true); // 开启景深 module = g3d.getPostProcessingModule('Dof'); module.aperture = 0.18; // 景深阀值 module.image= '景深贴图.png'; // 景深贴图 g3d.iv(); // 刷新拓扑 ``` ## 2D 和 3D 结合 [2,3D 结合方式参考链接](https://www.cnblogs.com/yilyl/p/10393072.html "2D&3D结合") ```js var g2d = new ht.graph.GraphView(); var g3d = new ht.graph3d.Graph3dView(); // 将 3D 组件加入到 body 下 g3d.addToDOM(); // 将 2D 组件加入到 3D 组件的根 div 下,父子 DOM 事件会冒泡,这样不会影响 3D 场景的交互 g2d.addToDOM(g3d.getView()); ``` ## 代码相关 ### 动态添加icon图标 - [在线编辑器](https://www.hightopo.com/demo/Simple3DEditor/index.html) - [相关博客](https://www.cnblogs.com/xhload3d/p/8526529.html) ```js var node = new ht.Node(); node.s({ "shape3d": "billboard", "shape3d.image": 图片url, "shape3d.autorotate": true, "shape3d.fixSizeOnScreen": [ -1, -1 ], "wf.visible": "selected" }) node.p3(位置) // g3d.lp(event) | g3d.getHitPosition(event) 可用鼠标事件获取拖入位置 dm.add(node) ``` ### 聚焦 ```js gv.flyTo(node) ``` ### 获取某个block下所有的子孙节点 ```js dataModel.toDatas(data => {return data.isDescendantOf(dataModel.getDataByTag('M1'))}) dataModel.toDatas(data => {return data.isDescendantOf(dataModel.getDataByTag('M1'))}).toArray().filter(item => item.getClassName() == 'ht.Node') ``` ### 围绕p点以r为半径视角环绕看向p点的动画 ```js var r = 100; var p = [0, 0, 0]; var anim; var animFunc = function() { return ht.Default.startAnim({ duration: 10000, easing: function(t) { return t}, action: function(v, t) { g3d.setCenter(p); var x = p[0] + r * Math.cos(Math.PI * 2 * v); var y = p[1]; var z = p[2] + r * Math.sin(Math.PI * 2 * v); g3d.setEye(x, y, z); }, finishFunc: function() { anim = animFunc(); } }) } anim = animFunc(); ``` ### 设置body背景色 ```js g3d.getView().parentElement.style.background = 'black' ``` ### 编辑器里拆分,减面bim模型 ```js editor3d.gv.dm().getDataByTag('G3').getChildren().toArray(); editor3d.gv.dm().getDatas().toArray(); editor3d.gv.dm().toDatas(data => {return data.isDescendantOf(editor3d.gv.dm().getDataByTag('GX'))}).toArray().filter(item => item.getClassName() == 'ht.Node') ``` ```js var BIMNodes = editor3d.gv.dm().getDataByTag('G3').getChildren().toArray(); var gp = ht.Default.getBIMProperty(); let filter = { property: { '族名称': "管道类型" } } let allNodes = []; //保存拆解出来的模型 BIMNodes.forEach((v) => { try { allNodes = allNodes.concat(ht.Default.extractBIMModel(v, filter)); } catch (e) { console.log(e); console.log(v); return; } }); allNodes.forEach((v) => { let pid = ht.Default.getBIMPropertyGroupId(v); let bimId = v.a('BIMId'); property = gp[pid][bimId]; // console.log(property) let r = parseFloat(property['外径']); if (r == 0) { return; } let res; try { res = ht.Default.calcBimEndpoints(v, false); } catch (e) { console.log(e); console.log(v); return; } if (res.length == 0) { console.log('error to find face'); return; } let n = new ht.Polyline(); n.s('shape3d', 'cylinder'); let p = { x: res[0][0], y: res[0][2], e: res[0][1] }; let p1 = { x: res[1][0], y: res[1][2], e: res[1][1] }; n.setPoints([p, p1]); n.setThickness(r / 100); n.a('BIMId', bimId); n.a('BIMPropertyId', v.a('BIMPropertyId')); n.a('BIMTag', v.a('BIMTag')); n.a('type', 'GX'); for (let [k, v] of Object.entries(property)) { n.a(k, v) } let color = v.a('BIMColor'); if (color) { n.s("shape3d.color", color); } editor3d.gv.dm().add(n); }); ```