zoukankan      html  css  js  c++  java
  • 3D拓扑自动布局之Web Workers篇

    2D拓扑的应用在电信网管和电力SCADA领域早已习以为常了,随着OpenGL特别是WebGL技术的普及,3D方式的数据可视化也慢慢从佛殿神堂步入了寻常百姓家,似乎和最近高档会所被整改为普通茶馆是一样的节奏。

    3D呈现固然比2D方式更直观,但如果摆放图元布局却比2D麻烦,毕竟增加了一个维度,手工布局不如以前2D手工操作方便,因此3D的自动布局功能比2D凸显其重要性。最近玩了玩HT的弹力自动布局插件挺有意思,特别在平板上Touch方式拖拽三维空间图元节点时,对我这种控制欲较强者很有满足感。


     

    弹力布局也不是啥新鲜玩意儿了,传统弹力布局算法都是采用通过CPU迭代运算的方式,对于海量数据特别是在纯客户端运算的方式肯定是不可行的,因此这些年也有很多采用GPU的方式进行并行计算的方式可极大提高性能,等OpenCL更成熟HT for Web提供了WebCL的解决方案我再来张开这个话题。今天的话题采用的还是CPU,只不过我把自动布局的算法拉到了Web Worker来运算,纯属为了好玩实际意义不大,毕竟Worker运算结果还得不断序列化给GUI页面层,不断来回数据传输也挺耗性能,当然如果你让Worker运行一段时间,只把最终结果push回Web层进行呈现还是有点实际意义的,毕竟不用Worker时js单线程运行,对这种计算密集型的算法只会卡死界面无法进行其他业务操作。


     

    以下是页面部分的代码,通过new Worker('workderjs')构建Worker后台运行对象,通过worker.addEventListener('message', ..)监听后台自动布局后派发的图元位置信息进行更新,通过worker.postMessage(info)发送界面拖拽图元位置变化信息。

           function reload() {                    
                var info = {
                    A: parseInt($("A").value), 
                    B: parseInt($("B").value)
                };
                reloadModel(dataModel, info);
                worker.postMessage(info);
            }
    
            function init() {        
                dataModel = new ht.DataModel();                   
                g3d = new ht.graph3d.Graph3dView(dataModel); 
                toolbar = new ht.widget.Toolbar(items);
                borderPane = new ht.widget.BorderPane();
                borderPane.setTopView(toolbar);
                borderPane.setCenterView(g3d);       
    
                g3d.mi(function(evt){
                    if(evt.kind === 'betweenMove'){                
                        moveMap = {};
                        g3d.sm().each(function(data){
                            if(data instanceof ht.Node){
                                moveMap[data._id] = data.p3();
                            }
                        });
                        worker.postMessage({moveMap: moveMap});                
                    }
                }); 
    
                worker = new Worker("worker.js");    
                worker.addEventListener('message', function(e) {
                    var info = e.data;
                    for(var id in info.result){
                        var data = dataModel.getDataById([id]);
                        if(data && !g3d.isSelected(data)){
                            data.p3(info.result[id]);
                        }                
                    }  
                }); 
    
                reload();
            }
    

    以下是后台Work.js的代码,通过importScripts("ht.js")引入HT核心包,通过importScripts("ht-forcelayout.js")引入HT的弹力布局插件,通过importScripts("util.js")引入和页面代码共享的一些通用函数,通过self.postMessage({result: result})发送自动布局运算结果推送到页面,通过
    self.addEventListener('message', ...)监听页面发过来的位置变化信息,从而实现了前后台的互通。

    importScripts("ht.js");
    importScripts("ht-forcelayout.js");
    importScripts("util.js");
    
    ht = self.ht;
    dataModel = new ht.DataModel();
    forceLayout = new ht.layout.Force3dLayout(dataModel);
    
    forceLayout.onRelaxed = function(){    
        var result = {};
        dataModel.each(function(data){
           if(data instanceof ht.Node){
               result[data._id] = data.p3();
           } 
        });
        self.postMessage({result: result});
    };
    forceLayout.start();    
    
    self.addEventListener('message', function(e) {
        var info = e.data;
        if(info.moveMap){
            dataModel.sm().cs();
            for(var id in info.moveMap){
                var data = dataModel.getDataById(id);
                if(data){
                    data.p3(info.moveMap[id]);
                    dataModel.sm().as(data);
                }
            }
        }
        else{
            reloadModel(dataModel, info);                 
        }        
    }, false);
    

    以下视频为在Android平板上跑3D拓扑自动布局的效果,这个例子纯粹为了玩玩Web Workers,这样折腾性能并不会提高,甚至因为来回序列化更费性能,Web Worker可以使用的场景并不太多,比较适合纯数学运算的业务逻辑,同时还需要注意跑在Worker的代码是不能操作任何界面对象,例如window和document之类的对象。

    下篇《3D拓扑自动布局之Node.js篇》我们再将算法移到Node.js端玩

      

      

  • 相关阅读:
    NullPointerException
    面试oracle 经常问的一个问题- 事务
    python 之 import、from、as 关键字的 白话 解释与例子
    python 学习 之 第二章(条件、循环和其他语句)
    python学习 之 第一章 (简单例子与常用数据类型)
    python中常用函数含义记录
    python 2 版本中的input() 和 raw_input() 函数的比较
    字符串处理关键字str 和 repr
    文件操作-一个可以直接复制文件数据的小程序
    C语言 32个关键字
  • 原文地址:https://www.cnblogs.com/xhload3d/p/3557465.html
Copyright © 2011-2022 走看看