terrastruct / d2

D2 is a modern diagram scripting language that turns text to diagrams.
https://d2lang.com
Mozilla Public License 2.0
18.05k stars 442 forks source link

dagre: container escape #448

Closed ejulio-ts closed 3 months ago

ejulio-ts commented 1 year ago
state machine: {
    0
    1: {
        red.shape:step
        blu.shape:step
    }
    2: {
        red.shape:step
        blu.shape:step
    }
    3: {
        red.shape:step
        blu.shape:step
    }
    4: {
        red.shape:step
        blu.shape:step
    }
    5: {
        red.shape:step
        blu.shape:step
    }
    6: {
        red.shape:step
        blu.shape:step
    }
    7: {
        red.shape:step
        blu.shape:step
    }
    8: {
        red.shape:step
        blu.shape:step
    }
    9: {
        red.shape:step
        blu.shape:step
    }
    10: {
        red.shape:step
        blu.shape:step
    }
    11: {
        red.shape:step
        blu.shape:step
    }
    12: {
        red.shape:step
        blu.shape:step
    }
    13

    1.red -> 5
    1.blu -> 0
    2.red -> 6
    2.blu -> 0
    3.red -> 7
    3.blu -> 0
    4.red -> 8
    4.blu -> 0
    5.red -> 9
    5.blu -> 2
    6.red -> 10
    6.blu -> 3
    7.red -> 11
    7.blu -> 4
    8.red -> 12
    8.blu -> 1
    9.red -> 13
    9.blu -> 6
    10.red -> 13
    10.blu -> 7
    11.red -> 13
    11.blu -> 8
    12.red -> 13
    12.blu -> 5
}

Result image

Note how 8.blu was rendered outside the container, between 10 and 7

gavin-ts commented 1 year ago

This appears to just be a rare bug with dagre's layout. Not sure how much we can do about this.

Without any of our code in the mix, running dagre.layout(g) with the following setup results in the eight_blue node with a n x value much further to the left despite its parent's dimensions and position.

var g = new dagre.graphlib.Graph({ compound: true, multigraph: true });
g.setDefaultNodeLabel(function () {
 return {};
});
g.setDefaultEdgeLabel(function () {
 return {};
});
g.setGraph({
 ranksep: 100,
 edgesep: 40,
 nodesep: 60,
 rankdir: "TB",
});
g.setNode(`container`, { id: `container` });
g.setNode(`zero`, { id: `zero` });
g.setParent(`zero`, `container`);
g.setNode(`one`, { id: `one` });
g.setParent(`one`, `container`);
g.setNode(`one_red`, { id: `one_red` });
g.setParent(`one_red`, `one`);
g.setNode(`one_blue`, { id: `one_blue` });
g.setParent(`one_blue`, `one`);
g.setNode(`two`, { id: `two` });
g.setParent(`two`, `container`);
g.setNode(`two_red`, { id: `two_red` });
g.setParent(`two_red`, `two`);
g.setNode(`two_blue`, { id: `two_blue` });
g.setParent(`two_blue`, `two`);
g.setNode(`three`, { id: `three` });
g.setParent(`three`, `container`);
g.setNode(`three_red`, { id: `three_red` });
g.setParent(`three_red`, `three`);
g.setNode(`three_blue`, { id: `three_blue` });
g.setParent(`three_blue`, `three`);
g.setNode(`four`, { id: `four` });
g.setParent(`four`, `container`);
g.setNode(`four_red`, { id: `four_red` });
g.setParent(`four_red`, `four`);
g.setNode(`four_blue`, { id: `four_blue` });
g.setParent(`four_blue`, `four`);
g.setNode(`five`, { id: `five` });
g.setParent(`five`, `container`);
g.setNode(`five_red`, { id: `five_red` });
g.setParent(`five_red`, `five`);
g.setNode(`five_blue`, { id: `five_blue` });
g.setParent(`five_blue`, `five`);
g.setNode(`six`, { id: `six` });
g.setParent(`six`, `container`);
g.setNode(`six_red`, { id: `six_red` });
g.setParent(`six_red`, `six`);
g.setNode(`six_blue`, { id: `six_blue` });
g.setParent(`six_blue`, `six`);
g.setNode(`seven`, { id: `seven` });
g.setParent(`seven`, `container`);
g.setNode(`seven_red`, { id: `seven_red` });
g.setParent(`seven_red`, `seven`);
g.setNode(`seven_blue`, { id: `seven_blue` });
g.setParent(`seven_blue`, `seven`);
g.setNode(`eight`, { id: `eight` });
g.setParent(`eight`, `container`);
g.setNode(`eight_red`, { id: `eight_red` });
g.setParent(`eight_red`, `eight`);
g.setNode(`eight_blue`, { id: `eight_blue` });
g.setParent(`eight_blue`, `eight`);
g.setNode(`nine`, { id: `nine` });
g.setParent(`nine`, `container`);
g.setNode(`nine_red`, { id: `nine_red` });
g.setParent(`nine_red`, `nine`);
g.setNode(`nine_blue`, { id: `nine_blue` });
g.setParent(`nine_blue`, `nine`);
g.setNode(`ten`, { id: `ten` });
g.setParent(`ten`, `container`);
g.setNode(`ten_red`, { id: `ten_red` });
g.setParent(`ten_red`, `ten`);
g.setNode(`ten_blue`, { id: `ten_blue` });
g.setParent(`ten_blue`, `ten`);
g.setNode(`eleven`, { id: `eleven` });
g.setParent(`eleven`, `container`);
g.setNode(`eleven_red`, { id: `eleven_red` });
g.setParent(`eleven_red`, `eleven`);
g.setNode(`eleven_blue`, { id: `eleven_blue` });
g.setParent(`eleven_blue`, `eleven`);
g.setNode(`twelve`, { id: `twelve` });
g.setParent(`twelve`, `container`);
g.setNode(`twelve_red`, { id: `twelve_red` });
g.setParent(`twelve_red`, `twelve`);
g.setNode(`twelve_blue`, { id: `twelve_blue` });
g.setParent(`twelve_blue`, `twelve`);
g.setNode(`thirteen`, { id: `thirteen` });
g.setParent(`thirteen`, `container`);
g.setEdge({v:`one_red`, w:`five_red` });
g.setEdge({v:`one_blue`, w:`zero` });
g.setEdge({v:`two_red`, w:`six_red` });
g.setEdge({v:`two_blue`, w:`zero` });
g.setEdge({v:`three_red`, w:`seven_red` });
g.setEdge({v:`three_blue`, w:`zero` });
g.setEdge({v:`four_red`, w:`eight_red` });
g.setEdge({v:`four_blue`, w:`zero` });
g.setEdge({v:`five_red`, w:`nine_red` });
g.setEdge({v:`five_blue`, w:`two_red` });
g.setEdge({v:`six_red`, w:`ten_red` });
g.setEdge({v:`six_blue`, w:`three_red` });
g.setEdge({v:`seven_red`, w:`eleven_red` });
g.setEdge({v:`seven_blue`, w:`four_red` });
g.setEdge({v:`eight_red`, w:`twelve_red` });
g.setEdge({v:`eight_blue`, w:`one_red` });
g.setEdge({v:`nine_red`, w:`thirteen` });
g.setEdge({v:`nine_blue`, w:`six_red` });
g.setEdge({v:`ten_red`, w:`thirteen` });
g.setEdge({v:`ten_blue`, w:`seven_red` });
g.setEdge({v:`eleven_red`, w:`thirteen` });
g.setEdge({v:`eleven_blue`, w:`eight_red` });
g.setEdge({v:`twelve_red`, w:`thirteen` });
g.setEdge({v:`twelve_blue`, w:`five_red` });

Result g._nodes:

{
    "container": {
        "id": "container",
        "x": 1295,
        "y": 375,
        "width": 2590,
        "height": 750
    },
    "zero": {
        "id": "zero",
        "x": 180,
        "y": 400
    },
    "one": {
        "id": "one",
        "x": 135,
        "y": 250,
        "width": 190,
        "height": 100
    },
    "one_red": {
        "id": "one_red",
        "x": 180,
        "y": 250
    },
    "one_blue": {
        "id": "one_blue",
        "x": 120,
        "y": 250
    },
    "two": {
        "id": "two",
        "x": 545,
        "y": 250,
        "width": 190,
        "height": 100
    },
    "two_red": {
        "id": "two_red",
        "x": 590,
        "y": 250
    },
    "two_blue": {
        "id": "two_blue",
        "x": 530,
        "y": 250
    },
    "three": {
        "id": "three",
        "x": 945,
        "y": 250,
        "width": 190,
        "height": 100
    },
    "three_red": {
        "id": "three_red",
        "x": 990,
        "y": 250
    },
    "three_blue": {
        "id": "three_blue",
        "x": 930,
        "y": 250
    },
    "four": {
        "id": "four",
        "x": 1345,
        "y": 250,
        "width": 190,
        "height": 100
    },
    "four_red": {
        "id": "four_red",
        "x": 1390,
        "y": 250
    },
    "four_blue": {
        "id": "four_blue",
        "x": 1330,
        "y": 250
    },
    "five": {
        "id": "five",
        "x": 345,
        "y": 250,
        "width": 130,
        "height": 400
    },
    "five_red": {
        "id": "five_red",
        "x": 360,
        "y": 400
    },
    "five_blue": {
        "id": "five_blue",
        "x": 345,
        "y": 100
    },
    "six": {
        "id": "six",
        "x": 1145,
        "y": 250,
        "width": 130,
        "height": 400
    },
    "six_red": {
        "id": "six_red",
        "x": 1160,
        "y": 400
    },
    "six_blue": {
        "id": "six_blue",
        "x": 1145,
        "y": 100
    },
    "seven": {
        "id": "seven",
        "x": 1975,
        "y": 250,
        "width": 130,
        "height": 400
    },
    "seven_red": {
        "id": "seven_red",
        "x": 1990,
        "y": 400
    },
    "seven_blue": {
        "id": "seven_blue",
        "x": 1960,
        "y": 100
    },
    "eight": {
        "id": "eight",
        "x": 2315,
        "y": 250,
        "width": 130,
        "height": 400
    },
    "eight_red": {
        "id": "eight_red",
        "x": 2330,
        "y": 400
    },
    "eight_blue": {
        "id": "eight_blue",
        "x": 1820,
        "y": 100
    },
    "nine": {
        "id": "nine",
        "x": 745,
        "y": 400,
        "width": 130,
        "height": 400
    },
    "nine_red": {
        "id": "nine_red",
        "x": 760,
        "y": 550
    },
    "nine_blue": {
        "id": "nine_blue",
        "x": 745,
        "y": 250
    },
    "ten": {
        "id": "ten",
        "x": 1545,
        "y": 400,
        "width": 130,
        "height": 400
    },
    "ten_red": {
        "id": "ten_red",
        "x": 1560,
        "y": 550
    },
    "ten_blue": {
        "id": "ten_blue",
        "x": 1545,
        "y": 250
    },
    "eleven": {
        "id": "eleven",
        "x": 2145,
        "y": 400,
        "width": 130,
        "height": 400
    },
    "eleven_red": {
        "id": "eleven_red",
        "x": 2160,
        "y": 550
    },
    "eleven_blue": {
        "id": "eleven_blue",
        "x": 2145,
        "y": 250
    },
    "twelve": {
        "id": "twelve",
        "x": 2485,
        "y": 400,
        "width": 130,
        "height": 400
    },
    "twelve_red": {
        "id": "twelve_red",
        "x": 2500,
        "y": 550
    },
    "twelve_blue": {
        "id": "twelve_blue",
        "x": 2485,
        "y": 250
    },
    "thirteen": {
        "id": "thirteen",
        "x": 1860,
        "y": 700
    }
}
alixander commented 1 year ago

good sleuthing, thx @gavin-ts . do you see any pattern for when this arises? wondering if this is something we can catch at the compilation step that dagre can't handle

ejulio-ts commented 1 year ago

I don't think the compiler should've these layout engine specific checks. Otherwise, dare can get an update and we might still generate the error while it would work as expected

alixander commented 1 year ago

dagre's not getting an update (hasn't been maintained in years). we inherit our dependencies issues and ppl will think it's our bug.