adjustEdge.js 5.1 KB
Newer Older
S
sushuang 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
import {curve as curveTool} from 'zrender';
import {vector as vec2} from 'zrender';

var v1 = [];
var v2 = [];
var v3 = [];
var quadraticAt = curveTool.quadraticAt;
var v2DistSquare = vec2.distSquare;
var mathAbs = Math.abs;
function intersectCurveCircle(curvePoints, center, radius) {
    var p0 = curvePoints[0];
    var p1 = curvePoints[1];
    var p2 = curvePoints[2];

    var d = Infinity;
    var t;
    var radiusSquare = radius * radius;
    var interval = 0.1;

    for (var _t = 0.1; _t <= 0.9; _t += 0.1) {
        v1[0] = quadraticAt(p0[0], p1[0], p2[0], _t);
        v1[1] = quadraticAt(p0[1], p1[1], p2[1], _t);
        var diff = mathAbs(v2DistSquare(v1, center) - radiusSquare);
        if (diff < d) {
            d = diff;
            t = _t;
L
lang 已提交
27
        }
S
sushuang 已提交
28
    }
L
lang 已提交
29

S
sushuang 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
    // Assume the segment is monotone,Find root through Bisection method
    // At most 32 iteration
    for (var i = 0; i < 32; i++) {
        // var prev = t - interval;
        var next = t + interval;
        // v1[0] = quadraticAt(p0[0], p1[0], p2[0], prev);
        // v1[1] = quadraticAt(p0[1], p1[1], p2[1], prev);
        v2[0] = quadraticAt(p0[0], p1[0], p2[0], t);
        v2[1] = quadraticAt(p0[1], p1[1], p2[1], t);
        v3[0] = quadraticAt(p0[0], p1[0], p2[0], next);
        v3[1] = quadraticAt(p0[1], p1[1], p2[1], next);

        var diff = v2DistSquare(v2, center) - radiusSquare;
        if (mathAbs(diff) < 1e-2) {
            break;
        }
L
lang 已提交
46

S
sushuang 已提交
47 48 49 50 51 52 53
        // var prevDiff = v2DistSquare(v1, center) - radiusSquare;
        var nextDiff = v2DistSquare(v3, center) - radiusSquare;

        interval /= 2;
        if (diff < 0) {
            if (nextDiff >= 0) {
                t = t + interval;
L
lang 已提交
54 55
            }
            else {
S
sushuang 已提交
56
                t = t - interval;
L
lang 已提交
57 58
            }
        }
S
sushuang 已提交
59 60 61 62 63 64 65 66 67
        else {
            if (nextDiff >= 0) {
                t = t - interval;
            }
            else {
                t = t + interval;
            }
        }
    }
L
lang 已提交
68

S
sushuang 已提交
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
    return t;
}

// Adjust edge to avoid
export default function (graph, scale) {
    var tmp0 = [];
    var quadraticSubdivide = curveTool.quadraticSubdivide;
    var pts = [[], [], []];
    var pts2 = [[], []];
    var v = [];
    scale /= 2;

    function getSymbolSize(node) {
        var symbolSize = node.getVisual('symbolSize');
        if (symbolSize instanceof Array) {
            symbolSize = (symbolSize[0] + symbolSize[1]) / 2;
        }
        return symbolSize;
L
lang 已提交
87
    }
S
sushuang 已提交
88 89 90 91 92 93 94 95 96 97 98 99
    graph.eachEdge(function (edge, idx) {
        var linePoints = edge.getLayout();
        var fromSymbol = edge.getVisual('fromSymbol');
        var toSymbol = edge.getVisual('toSymbol');

        if (!linePoints.__original) {
            linePoints.__original = [
                vec2.clone(linePoints[0]),
                vec2.clone(linePoints[1])
            ];
            if (linePoints[2]) {
                linePoints.__original.push(vec2.clone(linePoints[2]));
100 101
            }
        }
S
sushuang 已提交
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
        var originalPoints = linePoints.__original;
        // Quadratic curve
        if (linePoints[2] != null) {
            vec2.copy(pts[0], originalPoints[0]);
            vec2.copy(pts[1], originalPoints[2]);
            vec2.copy(pts[2], originalPoints[1]);
            if (fromSymbol && fromSymbol != 'none') {
                var symbolSize = getSymbolSize(edge.node1);

                var t = intersectCurveCircle(pts, originalPoints[0], symbolSize * scale);
                // Subdivide and get the second
                quadraticSubdivide(pts[0][0], pts[1][0], pts[2][0], t, tmp0);
                pts[0][0] = tmp0[3];
                pts[1][0] = tmp0[4];
                quadraticSubdivide(pts[0][1], pts[1][1], pts[2][1], t, tmp0);
                pts[0][1] = tmp0[3];
                pts[1][1] = tmp0[4];
119
            }
S
sushuang 已提交
120 121 122 123 124 125 126 127 128 129 130
            if (toSymbol && toSymbol != 'none') {
                var symbolSize = getSymbolSize(edge.node2);

                var t = intersectCurveCircle(pts, originalPoints[1], symbolSize * scale);
                // Subdivide and get the first
                quadraticSubdivide(pts[0][0], pts[1][0], pts[2][0], t, tmp0);
                pts[1][0] = tmp0[1];
                pts[2][0] = tmp0[2];
                quadraticSubdivide(pts[0][1], pts[1][1], pts[2][1], t, tmp0);
                pts[1][1] = tmp0[1];
                pts[2][1] = tmp0[2];
L
lang 已提交
131
            }
S
sushuang 已提交
132 133 134 135 136 137 138 139 140
            // Copy back to layout
            vec2.copy(linePoints[0], pts[0]);
            vec2.copy(linePoints[1], pts[2]);
            vec2.copy(linePoints[2], pts[1]);
        }
        // Line
        else {
            vec2.copy(pts2[0], originalPoints[0]);
            vec2.copy(pts2[1], originalPoints[1]);
L
lang 已提交
141

S
sushuang 已提交
142 143 144
            vec2.sub(v, pts2[1], pts2[0]);
            vec2.normalize(v, v);
            if (fromSymbol && fromSymbol != 'none') {
145

S
sushuang 已提交
146
                var symbolSize = getSymbolSize(edge.node1);
147

S
sushuang 已提交
148 149 150 151
                vec2.scaleAndAdd(pts2[0], pts2[0], v, symbolSize * scale);
            }
            if (toSymbol && toSymbol != 'none') {
                var symbolSize = getSymbolSize(edge.node2);
152

S
sushuang 已提交
153
                vec2.scaleAndAdd(pts2[1], pts2[1], v, -symbolSize * scale);
L
lang 已提交
154
            }
S
sushuang 已提交
155 156 157 158 159
            vec2.copy(linePoints[0], pts2[0]);
            vec2.copy(linePoints[1], pts2[1]);
        }
    });
}