请选择 进入手机版 | 继续访问电脑版
2021ThingJS数字孪生智慧场景可视化开发大赛获奖者专访
查看: 186|回复: 0

[分享] 电子围栏可视化,进步平安运维效力

[复制链接]
avatar

41

主题

41

帖子

292

积分

中级会员

Rank: 3Rank: 3

积分
292
ico_lz  楼主| 发表于 2021-8-19 14:04:43 | 显示全部楼层 |阅读模式
现代产业化的推动在极大加速现代化进程的同时也带来的响应的平安隐患,在传统的监控范畴,一般都是基于Web前端技术来实现 2D 可视化监控,本文彩用ThingJS来机关轻量化的 3D 可视化场景,该3D场景展现了一个现代化商场的数字孪生可视化场景,包括职员的实时位置、电子围栏的范围、现场的平安情况等等,帮助直观的领会当前职员的平安状态。

电子围栏又称周界防盗报警系统,监控防区工作状态,实景中的电子围栏系统用于农业、畜牧业,以及牢狱、军事设备等平安敏感地域。ThingJS平台上,电子围栏指的是一个地区,利用PolygonRegion属性。建立物体工具或模子并开启移动功用,即可起头检测方针点能否进入电子围栏地区,判定true或false显现告警反应。

电子围栏可视化,进步平安运维效力



本篇文章经过对数字孪生可视化场景的搭建和模子的加载,人物实时定位代码的实现、电子围栏和轨迹图的实现停止论述,领会若何经过利用ThingJS实现一个简单的3D电子围栏可视化。

  1. // 增加电子围栏
  2. new THING.widget.Button('增加电子围栏', function() {
  3. // 组成多边形的点(取天下坐标系下的坐标)
  4. points = [
  5. [81, 0.5, 63],
  6. [81, 0.5, 52],
  7. [72, 0.5, 52],
  8. [72, 0.5, 63]
  9. ];
  10. if (polygonMarker) { return; }
  11. // 建立电子围栏(地区)
  12. polygonMarker = app.create({
  13. type: 'PolygonRegion',
  14. points: points, // 传出天下坐标系下点坐标
  15. style: {
  16. regionOpacity: .6,
  17. regionColor: '#3CF9DF', // 地区色彩
  18. lineColor: '#3CF9DF' // 线框色彩
  19. }
  20. });
  21. // 设备永久在最上层显现
  22. polygonMarker.style.alwaysOnTop = false;
  23. })
复制代码


电子围栏可视化,进步平安运维效力



当人物或物体工具动身警报时,有2种方式提醒留意,一是踏足的禁区围栏色彩发生改变;二是展现面板显现报警信息,可视化监控方针点的移动范围。

完整代码以下:

  1. // 增加图片标注
  2. new THING.widget.Button('增加图片标注', function() {
  3. var coord = [83, 0.5, 61];
  4. if (marker1) { return; }
  5. // 建立方针点(marker)
  6. marker1 = app.create({
  7. type: "Marker",
  8. id: "marker1",
  9. url: "/guide/examples/images/navigation/user.png",
  10. position: coord,
  11. size: 1
  12. })
  13. })

  14. var point = [
  15. [81, 63],
  16. [81, 52],
  17. [72, 52],
  18. [72, 63]
  19. ];
  20. // 移动图片标注
  21. new THING.widget.Button('移动图片标注', function() {
  22. var markerEndPoint = [68, 0.5, 55];
  23. if (marker1 != null) {
  24. var moveState = marker1.getAttribute('moveState');
  25. if (moveState == 'complete') {
  26. marker1.off('update', null, '监控图片标注');
  27. return;
  28. }
  29. // 方针点移动
  30. marker1.moveTo({
  31. position: markerEndPoint, // 移动到尽头位置
  32. time: 2 * 1000,
  33. orientToPath: true, // 沿途径偏向
  34. complete: function(ev) {
  35. marker1.off('update', null, '监控图片标注');
  36. $('.warninfo1').css('display', 'none');
  37. $('.warninfo2').css('display', 'block');
  38. $('.warninfo3').css('display', 'none');
  39. marker1.setAttribute('moveState', 'complete');
  40. }
  41. })
  42. }
  43. if (points != null) {
  44. // 监控图片标注能否进入电子围栏地区
  45. if (marker1 != null) {
  46. marker1.on('update', function() {
  47. if (polygonMarker != null) {
  48. var intoPolygonMarker = isInPolygon([marker1.position[0], marker1.position[2]], point);
  49. if (intoPolygonMarker) {
  50. polygonMarker.regionColor = '#a94442';
  51. polygonMarker.lineColor = '#a94442'
  52. $('.warninfo1').css('display', 'block');
  53. $('.warninfo2').css('display', 'none');
  54. $('.warninfo3').css('display', 'none');
  55. } else {
  56. polygonMarker.regionColor = '#3CF9DF';
  57. polygonMarker.lineColor = '#3CF9DF'
  58. $('.warninfo1').css('display', 'none');
  59. $('.warninfo2').css('display', 'none');
  60. $('.warninfo3').css('display', 'block');
  61. }
  62. }
  63. }, '监控图片标注')
  64. }
  65. }
  66. })

  67. // 增加模子标注
  68. new THING.widget.Button('增加模子标注', function() {
  69. //建立方针点(Obj)
  70. people = app.query('#worker')[0];
  71. people.position = [83, 0.1, 56];
  72. people.visible = true;
  73. people.scale = [1.5, 1.5, 1.5];
  74. })

  75. // 移动模子标注
  76. new THING.widget.Button('移动模子标注', function() {
  77. var objEndPoint = [70, 0.1, 60];
  78. if (people != null) {
  79. var moveState = people.getAttribute('moveState');
  80. if (moveState == 'complete') {
  81. people.off('update', null, '监控图片标注');
  82. return;
  83. }
  84. // 播放模子动画
  85. people.playAnimation({
  86. name: '走',
  87. speed: 1,
  88. loopType: THING.LoopType.Repeat,
  89. });
  90. // 模子移动
  91. people.moveTo({
  92. position: objEndPoint, // 移动到尽头位置
  93. orientToPath: true, // 沿途径偏向
  94. time: 8 * 1000,
  95. complete: function(ev) {
  96. people.stopAnimation('走');
  97. people.off('update', null, '监控模子标注');
  98. $('.warninfo1').css('display', 'none');
  99. $('.warninfo2').css('display', 'block');
  100. $('.warninfo3').css('display', 'none');
  101.   people.setAttribute('moveState', 'complete');
  102. }
  103. })
  104. }
  105. if (points != null) {
  106. // 监控模子标注能否进入电子围栏地区
  107. if (people != null) {
  108. people.on('update', function() {
  109. if (polygonMarker != null) {
  110. var intoPolygonMarker = isInPolygon([people.position[0], people.position[2]], point);
  111. if (intoPolygonMarker) {
  112. polygonMarker.regionColor = '#a94442';
  113. polygonMarker.lineColor = '#a94442'
  114. $('.warninfo1').css('display', 'block');
  115. $('.warninfo2').css('display', 'none');
  116. $('.warninfo3').css('display', 'none');
  117. } else {
  118. polygonMarker.regionColor = '#3CF9DF';
  119. polygonMarker.lineColor = '#3CF9DF'
  120. $('.warninfo1').css('display', 'none');
  121. $('.warninfo2').css('display', 'none');
  122. $('.warninfo3').css('display', 'block');
  123. }
  124. }
  125. }, '监控模子标注')
  126. }
  127. }
  128. })

  129. // 重置
  130. new THING.widget.Button('重置', function() {
  131. if (polygonMarker) {
  132. polygonMarker.destroy();
  133. polygonMarker = null;
  134. }
  135. if (marker1) {
  136. marker1.destroy();
  137. marker1 = null;
  138. }
  139. if (people) {
  140. people.visible = false;
  141. people.setAttribute('moveState', null);
  142. }
  143. $('.warninfo1').css('display', 'none');
  144. $('.warninfo1').css('display', 'none');
  145. $('.warninfo1').css('display', 'block');
  146. })

  147. createTip(); // 建立提醒面板
  148. });

  149. /**
  150. * 建立提醒面板
  151. */
  152. function createTip() {
  153. var html =
  154. `<div class="fencing" style="width:200px;position: absolute;top: 50px;left: 50%;transform: translateX(-50%);z-index: 999;">
  155. <div class="alert alert-danger warninfo1" role="alert" style="padding: 15px;margin-bottom: 20px;color: #a94442;background-color: #f2dede;border-color: #ebccd1;border-radius: 4px;display:none;">方针已进入围栏</div>
  156. <div class="alert alert-info warninfo2" role="alert" style="padding: 15px;margin-bottom: 20px;color: #31708f;background-color: #d9edf7;border-color: #bce8f1;border-radius: 4px;display:none;">到达目标地</div>
  157. <div class="alert alert-warning warninfo3" role="alert" style="padding: 15px;margin-bottom: 20px;color: #8a6d3b;background-color: #fcf8e3;border-color: #faebcc;border-radius: 4px;">方针未进入围栏</div>

  158. <div onclick="fenClose()" style="cursor: pointer;position: absolute;top: -7px;right: -8px;width: 16px;height: 16px;border-radius: 50%;background-color: #777777;border: 3px solid #ffffff;">
  159. <div style="position: absolute;width: 10px;height: 2px;background-color: #fff;transform: rotate(45deg);top: 7px;left: 3px;"></div>
  160. <div style="position: absolute;width: 10px;height: 2px;background-color: #fff;transform: rotate(-45deg);top: 7px;left: 3px;"></div>
  161. </div>
  162. </div>`;
  163. $('#div2d').append($(html));
  164. }

  165. /**
  166. * 封闭提醒面板
  167. */
  168. function fenClose() {
  169. $(".fencing").hide();
  170. }
  171. /**
  172. * 检测方针点能否进入电子围栏地区
  173. * @param {Array} checkPoint - 校验坐标
  174. * @param {Array} polygonPoints - 构成电子围栏的坐标
  175. * @returns {Boolean} true 或 false
  176. * @description 此方式仅判定处于同一个平面的方针点能否在地区内(只判定坐标x和z值),
  177. * 不斟酌两者当前离地高度(坐标的y值)
  178. */
  179. function isInPolygon(checkPoint, polygonPoints) {
  180. var counter = 0;
  181. var i;
  182. var xinters;
  183. var p1, p2;
  184. var pointCount = polygonPoints.length;
  185. p1 = polygonPoints[0];
  186. for (i = 1; i <= pointCount; i++) {
  187. p2 = polygonPoints[i % pointCount];
  188. if (checkPoint[0] > Math.min(p1[0], p2[0]) && checkPoint[0] <= Math.max(p1[0], p2[0])) {
  189. if (checkPoint[1] <= Math.max(p1[1], p2[1])) {
  190. if (p1[0] != p2[0]) {
  191. xinters = (checkPoint[0] - p1[0]) * (p2[1] - p1[1]) / (p2[0] - p1[0]) + p1[1];
  192. if (p1[1] == p2[1] || checkPoint[1] <= xinters) {
  193. counter++;
  194. }
  195. }
  196. }
  197. }
  198. p1 = p2;
  199. }
  200. if (counter % 2 == 0) {
  201. return false;
  202. } else {
  203. return true;
  204. }
  205. }
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则