基于 HTML5 WebGL 的 3D 科幻风机
环境温度、机舱温度、齿轮箱温度、风速的图形百分比会随着时间发生改变。
风机在发电的过程中发生的异常情况,发生的故障部位及故障发生的时间。异常信息的收集有利于人们进行异常分析以及异常处理。
整理思路:
场景部分:
这里把 3D 当做背景嵌套在 2D 场景中。
这样在初始化图纸的时候,直接反序列化 2D 图纸即可。
事件部分:
2D 图纸中有很多的按钮,通过它们来控制 3D 中的一些动画。
实现思路是在反序列化图纸的时候把 2D、3D 的 模型和视图对象挂载到 window 上,这样在不同的场景中都可以获取到相应的数据模型。
环境部分:
风速、风向、变桨角度这些会在 2D、3D 中所表现,所以可以把他们放到数据池里面,方便管理。
具体代码实现:
场景搭建:上面说了,我们把 3D 当做背景嵌套在 2D 中,所以只需要序列化 2D 即可,里面需要进行背景判断的部分代码。
相关伪代码:
graphView.deserialize('displays/demo/风力发电机/风力发电机结构查看.json', function (json, dm, gv, datas) {
if (json.title) document.title = json.title
if (json.a['json.background']) {
var bgJSON = json.a['json.background']
if (bgJSON.indexOf('displays') === 0) {
var bgGv = new ht.graph.GraphView()
bgGv.deserialize(bgJSON)
bgGv.addToDOM()
graphView.addToDOM(bgGv.getView())
}
else if (bgJSON.indexOf('scenes') === 0) {
var bgG3d = new ht.graph3d.Graph3dView()
bgG3d.deserialize(bgJSON)
bgG3d.addToDOM()
graphView.addToDOM(bgG3d.getView())
}
graphView.handleScroll = function () { }
}
})
模拟风速:每隔30s,随机产生一个值,当做风速值。
相关伪代码:
// 模拟风速
mockWindSpeed() {
return 8 + Math.random() * 12
}
数据统计:每隔30s,随机变换。
效果:
相关伪代码:
// 指针和扇叶旋转的角度 进行变化
var oldPointerValue = pitchSystem.a('pointer') || 0
// 风机扇叶和变桨系统的旋转角度
var newRotateAngular = (this.windSpeed - 8) * 7.5 * translateAngularRadian.radian
var addPointerValue = newRotateAngular - oldPointerValue var oldWindSpeedClip = environmentalData.a('windSpeedClip') || 0
var newWindSpeedClip = (this.windSpeed - 8) / 12
var addWindSpeedClip = newWindSpeedClip - oldWindSpeedClip var anim = {
duration: 1e3,
easing: (v) => {
return v * v
},
action: (v) => {
var windSpeed = Number(this.windSpeed.toFixed(2))
var Max = Number(MaxValue.toFixed(2))
var average = Number(Aver.toFixed(2))
var windSpeedClip = oldWindSpeedClip + (addWindSpeedClip * v)
// 设置发电参数随机数据
generator.a({ windSpeed })
// 设置环境监测随机数据
environmentalData.a({ windSpeed, windSpeedClip })
// 设置统计参数随机数据
statisticalParam.a({ average, Max, windSpeed })
// 设置变航系统的指针角度
pitchSystem.a('pointer', oldPointerValue + (addPointerValue * v))
}
}
ht.Default.startAnim(anim)
这里涉及到角度和弧度的转换。1° = Math.PI / 180°,1rad = 180° / Math.PI,因为场景中使用的是弧度制,所以需要把随机出的角度值转换成弧度。
这里解释下代码,先获取到当前的值。然后在加上 随机值 - 当前值。比如当前值为 16,随机出的数值有两种情况,1:比当前值大。2:比当前值小。
如果比当前值大的话,比如18,那么就是这样 16 + (18 - 16) * v ( easing 函数运算后的值)
如果比当前值小的话,比如13,那么就是这样 16 + (13 - 16) * v ( easing 函数运算后的值)
这样当随机的时候,就会从当前值平滑的改变到目标值。
数据统计:每隔30s,监测当前风机的故障信息。
效果:
这里使用了 table.json 文件,通过修改 ht.dataSource 属性添加实时信息。
相关伪代码:
var checkInternals = () => {
/**
* 故障信息
* 变桨系统 主轴 偏航系统 齿轮箱 油冷装置 发电机 风冷装置
*/
var FailureStatus = {
// 正常状态
status1: new Map([
[0, ['舱内温度正常,变桨角度正常。', 'i10']],
[1, ['舱内温度正常,主轴转速正常。', 'i9']],
[2, ['偏航系统精确。', 'i8']],
[3, ['齿轮箱温度正常。', 'i1']],
[4, ['油冷装置温控表正常。', 'i3']],
[5, ['发电机功率正常。', 'i5']],
[6, ['风冷装置正常。', 'i2']]
]), // 异常状态
status2: new Map([
[0, ['变桨角度异常。', 'i10']],
[1, ['主轴转速偏高。', 'i9']],
[2, ['偏航系统出现偏移。', 'i8']],
[3, ['齿轮箱温度偏高。', 'i1']],
[4, ['油冷装置内积尘过多。', 'i3']],
[5, ['发电机电流过大。', 'i5']],
[6, ['风冷装置散热不足。', 'i2']]
]),
} // 返回设备正常的状况 status 1: 正常 2: 不正常
var mockQquipmentFailure = (status) => {
var { rangeRandom } = common
var index = rangeRandom(7) // 返回随机出来的设备情况
return FailureStatus[`status${status}`].get(index)
} var info = randomInfo[0]
var targetTag = randomInfo[1] this.tableArr = table.a('ht.dataSource')
var currentTimeFormat = DateUtil.formatHourTime(new Date()) // 默认是正常 如果找到故障关键字的话 赋值为 异常
var status = 'normal'
var time = 0
this.tableArr.push({ status, info, time: currentTimeFormat })
}
我们需要两个 Map 数组方便进行取值操作。一个是正常信息数组,一个是异常信息数组。利用随机值当做一个索引,然后取到相对应的状态信息,添加到 table 中。
如果当前的 status 为 normal,说明是正常信息,否则为异常信息。异常信息的话就可以通过 table.json 的渲染回调函数 "drawCell": function(g, text, rect, option) { } 来修改它的颜色,使其高亮。
偏航系统:风机转动的过程中,随着风的位置的不同,通过偏航系统改变方向。
效果:
相关伪代码:
/**
* 随机偏航系统
* @param { * }
*/
randomYawSystem() {
var { dm } = this
var { d2d } = window
var { rangeRandom } = common var poll = () => {
// 随机数 30 - 50
var random = 30 + rangeRandom(20)
var cabin = dm.getDataByTag('cabin') // 将角度度换算成弧度 然后乘以随机数 实现随机风向
var randomDegrees = translateAngularRadian.radian * random
var defaultDegress = translateAngularRadian.radian * 180 ht.Default.startAnim({
duration: 1e3,
action: (v) => {
var oldValue = cabin.getRotationY()
var newValue = randomDegrees
var addValue = newValue - oldValue cabin.setRotationY(oldValue + addValue * v)
}
})
}
}
上面讲到过角度弧度转换,这里先将随机出的角度转换成弧度,然后赋值,进行旋转。
变桨系统:风速的变化影响风机扇叶的角度。
效果:
相关伪代码:
var old3Value = whiteShell3Line.getRotationX()
var old4Value = whiteShell4Line.getRotationX()
var old5Value = whiteShell5Line.getRotationX() // 指针和扇叶旋转的角度 进行变化
var oldPointerValue = pitchSystem.a('pointer') || 0
// 风机扇叶和变桨系统的旋转角度
var newRotateAngular = (this.windSpeed - 8) * 7.5 * translateAngularRadian.radian
var addPointerValue = newRotateAngular - oldPointerValue whiteShell3Line.setRotationX(old3Value + ((newRotateAngular - oldPointerValue)))
whiteShell4Line.setRotationX(old4Value + ((newRotateAngular - oldPointerValue)))
whiteShell5Line.setRotationX(old5Value + ((newRotateAngular - oldPointerValue)))
先获取到每个扇叶当前的 X 轴旋转值,再获取到需要旋转的角度值,进行赋值。
风机启停:风机的启动和停止
相关伪代码:
var fanWireframe = d3d.getDataByTag('fanWireframe')
fanWireframe.setRotationMode('zxy')
this.allAnimManage = new Map([['fanRotate', null]])
var fanRotating = (easeType) => {
anim = ht.Default.startAnim({
duration: 5e3,
easing: (t) => easeIn(t),
action: (v) => {
fanWireframe.setRotationZ(fanWireframe.getRotationZ() + speed) // 风机轮毂旋转
if (fanWireframe.getRotationZ() <= -6.28) {
fanWireframe.setRotationZ(0)
} // 风机扇叶 uv 偏移
for (let i = 1; i < 17; i++) {
var node = d3d.getDataByTag(`q${i}`)
node.s('shape3d.uv.offset', fanOffsetData(v)[i - 1])
} // 暂停命令
if (isStop) {
stopFanRotate(fanWireframe.getRotationZ())
anim.pause()
anim = null
}
},
finishFunc: () => {
fanRotating(false)
}
}) this.allAnimManage.set('fanRotate', anim)
}
因为可以启动和停止,那么我们就可以通过控制 ht.Default.startAnim() 的返回对象的 resume 和 pause 来达到效果。
所以我把风机旋转的动画添加到了全局对象中,方便进行调用。
setRotationMode('zxy') 方法是设置三维旋转模式,顺序是 z -> x -> y,先进行z轴旋转,再进行x轴旋转,最后进行y轴旋转。设置目的是为了避免坐标轴受外部旋转的影响。
风向: 根据风的角度,判断当前是什么位置的风。
效果:
相关伪代码:
// 判断风向
var windDirection = (rotate) => {
let direction switch (true) {
case rotate === 0:
direction = '南'
break
case rotate === 90:
direction = '东'
break
case rotate === 180:
direction = '北'
break
case rotate === 240:
direction = '西'
break
case rotate > 0 && rotate < 90:
direction = '东南'
break
case rotate > 90 && rotate < 180:
direction = '东北'
break
case rotate > 180 && rotate < 270:
direction = '西北'
break
case rotate > 270 && rotate < 360:
direction = '西南'
break
default:
direction = '没有找到风向'
} return direction
}
// 判断是哪个方向
var angular = randomDegrees * translateAngularRadian.angular
var direction = windDirection(angular)
将罗盘的指针角度放到 switch 进行判断,如果找到对应的风向就返回。
总结
风力发电是一个工业互联网的典型例子,我们可以通过对风机模型或者监测数据进行分析,可以减轻我们工作复杂程度,帮助我们快速了解发电内部结构及发电功能。
HT 能做的东西远远不止于此,这需要我们丰富的想象力以及自身过硬的技术。我希望可以通过这篇文章向大家传递一种能量,让大家更有兴趣、迸发更多新鲜的想法,去做更多好玩的东西。
基于 HTML5 WebGL 的 3D 科幻风机的更多相关文章
- 基于 HTML5 WebGL 的 3D 风机 Web 组态工业互联网应用
基于 HTML5 WebGL 的 3D 风机 Web 组态工业互联网应用 前言 在目前大数据时代背景之下,数据可视化的需求也变得越来越庞大,在数据可视化的背景之下,通过智能机器间的链接并最终将人机链接 ...
- 基于 HTML5 + WebGL 的 3D 可视化挖掘机
前言 在工业互联网以及物联网的影响下,人们对于机械的管理,机械的可视化,机械的操作可视化提出了更高的要求.如何在一个系统中完整的显示机械的运行情况,机械的运行轨迹,或者机械的机械动作显得尤为的重要,因 ...
- 基于 HTML5 + WebGL 实现 3D 可视化地铁系统
前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...
- 基于 HTML5 + WebGL 实现 3D 挖掘机系统
前言 在工业互联网以及物联网的影响下,人们对于机械的管理,机械的可视化,机械的操作可视化提出了更高的要求.如何在一个系统中完整的显示机械的运行情况,机械的运行轨迹,或者机械的机械动作显得尤为的重要,因 ...
- 基于 HTML5 WebGL 构建 3D 智能数字化城市全景
前言 自 2011 年我国城镇化率首次突破 50% 以来,<新型城镇化发展规划>将智慧城市列为我国城市发展的三大目标之一,并提出到 2020 年,建成一批特色鲜明的智慧城市.截至现今,全国 ...
- 基于 HTML5 WebGL 的 3D 网络拓扑图
在数据量很大的2D 场景下,要找到具体的模型比较困难,并且只能显示出模型的的某一部分,显示也不够直观,这种时候能快速搭建出 3D 场景就有很大需求了.但是搭建 3D 应用场景又依赖于通过 3ds Ma ...
- 基于 HTML5 WebGL 的 3D 服务器与客户端的通信
这个例子的初衷是模拟服务器与客户端的通信,我把整个需求简化变成了今天的这个例子.3D 机房方面的模拟一般都是需要鹰眼来辅助的,这样找产品以及整个空间的概括会比较明确,在这个例子中我也加了,这篇文章就算 ...
- 基于 HTML5 WebGL 的 3D SCADA 主站系统
这个例子的初衷是模拟服务器与客户端的通信,我把整个需求简化变成了今天的这个例子.3D 的模拟一般需要鹰眼来辅助的,这样找产品以及整个空间的概括会比较明确,在这个例子中我也加了,这篇文章就算是我对这次项 ...
- 基于 HTML5 WebGL 的 3D 智慧隧道漫游巡检
前言 这次为大家展示的是通过 HT for Web 灵活的图型化编辑工具打造的智慧隧道监控系统.通过 HTML5 技术实现了桌面和移动端的跨平台性,同时现实了可视化运维. 这次主要跟大家分享里面的漫游 ...
随机推荐
- PyCharm2019 激活
文章末尾补充几个激活码:网上收集 一.破解补丁激活优点:永久期限 缺点:需要修改配置文件和下载破解文件 1.下载破解文件点击链接 链接: https://pan.baidu.com/s/1T405JC ...
- Linux 部署MySQL 一主一从一备
主服务器搭建 准备三台服务器,一主一从一备 在主服务器(master)下找到mysql配置文件. Window下为my.ini(一般在C:\ProgramData\MySQL\MySQL Server ...
- 01-Vue.js基础
一.Vue基础 1.介绍 Vue是一套用于构建用户界面的渐进式框架.Vue的核心库只关注视图层,不仅容易上手,还便于与第三方库或既有的项目整合.兼容性:Vue 不支持 IE8 及以下版本,因为 Vue ...
- 禧云Redis跨机房双向同步实践
编者荐语: 2019年4月16日跨机房Redis同步中间件(Rotter)上线,团餐率先商用: 以下文章来源于云纵达摩院 ,作者杨海波 禧云信息/研发中心/杨海波 20191115 关键词:Rot ...
- JAVA描述算法和数据结构(01):稀疏数组和二维数组转换
本文源码:GitHub·点这里 || GitEE·点这里 一.基本简介 1.基础概念 在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵:与之相反, ...
- vue template标签
在普通的html里面: template标签默认有个 display:none; 属性,并且其里面的内容是不可见的. 在vue里面: template标签类似一个隐藏的div,在审查元素的时候是找不到 ...
- Java入门系列之集合Hashtable源码分析(十一)
前言 上一节我们实现了散列算法并对冲突解决我们使用了开放地址法和链地址法两种方式,本节我们来详细分析源码,看看源码中对于冲突是使用的哪一种方式以及对比我们所实现的,有哪些可以进行改造的地方. Hash ...
- HttpClientExtensions去了哪里
使用HttpClient实现http请求是非常常见的方式,有一个HttpClient的拓展类HttpClientExtensions提供了更多的拓展方法,包括但不限于 PostAsJsonAsync ...
- 解决html导出pdf中文乱码问题的正确姿势
简介 本文使用jspdf 1.5.3版.GitHub地址:https://github.com/MrRio/jsPDF jspdf是歪果仁开发的,因此在一开始就没想过支持非英文以外的文字,这就导致了非 ...
- php反序列化漏洞绕过魔术方法 __wakeup
0x01 前言 前天学校的ctf比赛,有一道题是关于php反序列化漏洞绕过wakeup,最后跟着大佬们学到了一波姿势.. 0x02 原理 序列化与反序列化简单介绍 序列化:把复杂的数据类型压缩到一个字 ...