关于程序员:从零开始画自己的DAG作业依赖图四节点连线优化版

8次阅读

共计 2204 个字符,预计需要花费 6 分钟才能阅读完成。

概述

上个版本简略的连线在一些简单场景,尤其层级比拟多,连线跨层级比拟多的状况下,会呈现线条会穿过矩形的状况,这一讲就是在这个根底上,去优化这个连线。

场景剖析

在上面几种状况下,简略版本的画法曾经没法办躲避阻碍节点了。

这种状况, 因为简略版本,咱们只在整条门路上增加了 2 个拐点,这种画法,当呈现上述情况,线条就会被 B 挡住,理论的需要,咱们要躲避这种节点,绕开。

应该是上面这种状况:

再简单一点的场景如下

这时候有 2 个节点挡住了。咱们要做的就是依照图示,绕开节点。

思路剖析

察看剖析,咱们要想绕开,一些阻碍节点,咱们先要晓得哪些节点会挡住,才能够绕开。有两个曾经明确数据是,每一层的节点的坐标咱们是晓得,终点 p1, 起点是 p6。咱们能够模仿这个过程:

  1. 如果 p1 所在直线没有被最近的下一层挡住,也就是图中 D,E,F 节点挡住的话,那就阐明,终点能够先画到 p2
  2. 画到 p2 之后,持续判断第三层节点,因为 B 节点会挡住从 p2 往下画的竖线,所以绕开 B 节点,因为 P6 起点再 p2 左侧,所以,在 B 的左侧找一个空白的中央,即 p3
  3. 当初画到 p3 了,这时候终点编程 p3 了,问题转换成画 p1 的场景了
  4. 始终循环,直到到起点这一层,把这个门路上的所有的折点记录下来,就是咱们的门路

具体实现

function drawLine(startX, startY, endX, endY, color, sourceNodeName, targetNodeName, endLayer, startLayer, lineNodes) {var points = []; //  保留门路上的折点
    var sx =  startX;
    var ex = endX;
    for (var layer = startLayer + 1; layer < endLayer; layer++) {
        //  判断以后这一层有没有节点挡住
        var coverRectIndex = -1;
        for(var i = 0; i < lineNodes[layer].length; i++){if(lineNodes[layer][i].x < sx && (sx - lineNodes[layer][i].x) < config.rect.width){
                coverRectIndex = i;
                break;
            }
        }
        if(coverRectIndex === -1){
            //  如果没有挡住,查看下一层
            continue;
        }else{
            //  如果有挡住,则须要依据终点和指标节点绝对地位,决定往左边绕还是后边绕
           
            var midY = lineNodes[layer][coverRectIndex].y - 40;
            
            // 计算是右边的空隙还是左边的空隙
            var midX = lineNodes[layer][coverRectIndex].x;
                midX += sx > ex? -(config.rect.space / 2 + config.rect.width) : (config.rect.space / 2 + config.rect.width);
            while (true) {
                var flag = false;
                if (nodeLines[layer]) {for (var i = 0; i < nodeLines[layer].length; i++) {var line = nodeLines[layer][i];
                        if (line.startY === midY) {if (checkCross(sx, midX, line.startX, line.endX)) {flag = true;}
                        }
                        if (flag) break;
                    }
                } else {nodeLines[layer] = [];}
                if (!flag) break;
                midY -= lineDis;
            }
            if (sx !== midX) {nodeLines[layer].push({
                    startX: sx,
                    startY: midY,
                    endX: midX,
                    endY: midY
                })
            }
            // 存储门路上点
            points.push({x: sx, y: midY});
            points.push({x: midX, y: midY});
            sx = midX;
        }
    }
    
   //  独自解决最初一层的场景
    var midY = lineNodes[endLayer][0].y - 40;
    while (true) {
        var flag = false;
        if (nodeLines[endLayer]) {for (var i = 0; i < nodeLines[endLayer].length; i++) {var line = nodeLines[endLayer][i];
                if (line.startY === midY) {if (checkCross(sx, ex, line.startX, line.endX)) {flag = true;}
                }
                if (flag) break;
            }
        } else {nodeLines[endLayer] = [];}
        if (!flag) break;
        midY -= lineDis;
    }
    if (sx !== ex) {nodeLines[layer].push({
            startX: sx,
            startY: midY,
            endX: ex,
            endY: midY
        })
    }
    points.push({x: sx, y: midY});
    points.push({x: ex, y: midY});
    return points;
}

总结

这里是在原来的根底上进行优化的,实现了躲避阻碍节点的性能。一开始,我想到是 A* 算法去搜寻,然而像素点太多,算法复杂度 Hold 不住,前面卡在缩点的环节上,通过共事的指导,才实现了以后的这种优化,还是要多学习,多总结!

本文由华为云公布

正文完
 0