避免线条和箭头互相交叉

编程语言 2026-07-12

我在R 里有这个图:

library(DiagrammeR)

grn <- '#66BB6A'
red <- '#EF5350'
nvy <- '#1B3A5C'
gry <- '#BBBBBB'

lag_diagram <- grViz(paste0("
digraph lag_grid {

  graph [
    rankdir  = TB,
    fontname = 'Arial',
    bgcolor  = 'white',
    nodesep  = 0.50,
    ranksep  = 0.40,
    margin   = 0.3
  ]

  node [
    fontname = 'Arial',
    fontsize = 9,
    style    = 'filled,rounded',
    shape    = box,
    width    = 1.15,
    height   = 0.40,
    penwidth = 0
  ]

  # ===========================================================
  # COLUMN HEADERS
  # ===========================================================
  node [shape = plaintext, fillcolor = 'white', fontsize = 12,
        fontcolor = '", nvy, "', fontname = 'Arial Bold', width = 1.15]

  hdr_a [label = 'A']
  hdr_b [label = 'B']
  hdr_c [label = 'C']
  hdr_d [label = 'D']
  hdr_e [label = 'E']
  hdr_f [label = 'F']

  { rank = same; hdr_a; hdr_b; hdr_c; hdr_d; hdr_e; hdr_f }
  edge [style = invis]
  hdr_a -> hdr_b -> hdr_c -> hdr_d -> hdr_e -> hdr_f

  # ===========================================================
  # ROW 1
  # ===========================================================
  node [shape = box, fontsize = 9, fontcolor = 'white',
        fontname = 'Arial', width = 1.15, height = 0.40]

  r1_a [label = '1', fillcolor = '", red, "']
  r1_b [label = '1', fillcolor = '", red, "']
  r1_c [label = '1', fillcolor = '", red, "']
  r1_d [label = '1', fillcolor = '", red, "']
  r1_e [label = '1', fillcolor = '", red, "']
  r1_f [label = '1', fillcolor = '", red, "']

  { rank = same; r1_a; r1_b; r1_c; r1_d; r1_e; r1_f }
  edge [style = invis]
  r1_a -> r1_b -> r1_c -> r1_d -> r1_e -> r1_f

  # ===========================================================
  # ROW 2
  # ===========================================================
  r2_a [label = '2', fillcolor = '", grn, "']
  r2_b [label = '2', fillcolor = '", grn, "']
  r2_c [label = '2', fillcolor = '", grn, "']
  r2_d [label = '2', fillcolor = '", red, "']
  r2_e [label = '2', fillcolor = '", red, "']
  r2_f [label = '2', fillcolor = '", red, "']

  { rank = same; r2_a; r2_b; r2_c; r2_d; r2_e; r2_f }
  edge [style = invis]
  r2_a -> r2_b -> r2_c -> r2_d -> r2_e -> r2_f

  # ===========================================================
  # ROW 3
  # ===========================================================
  r3_a [label = '3', fillcolor = '", red, "']
  r3_b [label = '3', fillcolor = '", red, "']
  r3_c [label = '3', fillcolor = '", red, "']
  r3_d [label = '3', fillcolor = '", red, "']
  r3_e [label = '3', fillcolor = '", red, "']
  r3_f [label = '3', fillcolor = '", red, "']

  { rank = same; r3_a; r3_b; r3_c; r3_d; r3_e; r3_f }
  edge [style = invis]
  r3_a -> r3_b -> r3_c -> r3_d -> r3_e -> r3_f

  # ===========================================================
  # ROW 4
  # ===========================================================
  r4_a [label = '4', fillcolor = '", red, "']
  r4_b [label = '4', fillcolor = '", grn, "']
  r4_c [label = '4', fillcolor = '", red, "']
  r4_d [label = '4', fillcolor = '", red, "']
  r4_e [label = '4', fillcolor = '", red, "']
  r4_f [label = '4', fillcolor = '", red, "']

  { rank = same; r4_a; r4_b; r4_c; r4_d; r4_e; r4_f }
  edge [style = invis]
  r4_a -> r4_b -> r4_c -> r4_d -> r4_e -> r4_f

  # ===========================================================
  # ROW 5
  # ===========================================================
  r5_a [label = '5', fillcolor = '", red, "']
  r5_b [label = '5', fillcolor = '", red, "']
  r5_c [label = '5', fillcolor = '", red, "']
  r5_d [label = '5', fillcolor = '", red, "']
  r5_e [label = '5', fillcolor = '", red, "']
  r5_f [label = '5', fillcolor = '", red, "']

  { rank = same; r5_a; r5_b; r5_c; r5_d; r5_e; r5_f }
  edge [style = invis]
  r5_a -> r5_b -> r5_c -> r5_d -> r5_e -> r5_f

  # ===========================================================
  # ROW 6
  # ===========================================================
  r6_a [label = '6', fillcolor = '", red, "']
  r6_b [label = '6', fillcolor = '", red, "']
  r6_c [label = '6', fillcolor = '", red, "']
  r6_d [label = '6', fillcolor = '", red, "']
  r6_e [label = '6', fillcolor = '", red, "']
  r6_f [label = '6', fillcolor = '", red, "']

  { rank = same; r6_a; r6_b; r6_c; r6_d; r6_e; r6_f }
  edge [style = invis]
  r6_a -> r6_b -> r6_c -> r6_d -> r6_e -> r6_f

  # ===========================================================
  # CHAIN ARROWS
  # ===========================================================
  edge [style = solid, color = '", gry, "', arrowhead = vee,
        arrowsize = 0.4, penwidth = 0.9]

  r1_a -> r2_a -> r3_a -> r4_a -> r5_a -> r6_a
  r1_b -> r2_b -> r3_b -> r4_b -> r5_b -> r6_b
  r1_c -> r2_c -> r3_c -> r4_c -> r5_c -> r6_c
  r1_d -> r2_d -> r3_d -> r4_d -> r5_d -> r6_d
  r1_e -> r2_e -> r3_e -> r4_e -> r5_e -> r6_e
  r1_f -> r2_f -> r3_f -> r4_f -> r5_f -> r6_f

  # ===========================================================
  # VERTICAL ORDERING
  # ===========================================================
  edge [style = invis]
  hdr_a -> r1_a

}
"))

我想修改它,使绿色框现在指向底部的蓝色框,并且确保箭头/线条彼此不相交。

我该如何实现,让箭头/线条正确连接?

解决方案

这有点棘手——因此这是一个相对脆弱的起步方案,供你尝试。

但在指向外部节点的边上使用 constraint = false 时,会让“不用于对节点排序的边”这一点成立——也就是说,它会告诉引擎在这些边存在时仍然保持节点等级。

我创建了一个空的最后一行,并按从左到右的顺序连接内部节点 r7_a -> r7_b -> r7_c -> r7_d -> r7_e -> r7_f,并用不可见的边连接到六行单元格 r6_a -> r7_a...

Limey的评论 与此相关!如果我改为连接外部网格项 r7_c,边就会相交;我的研究显示,在保持等级并防止边缘重叠方面,没有自动化的方法使用ports = rearranging nodes重新排列节点 交叉

library(DiagrammeR)

grn <- '#66BB6A'
red <- '#EF5350'
nvy <- '#1B3A5C'
gry <- '#BBBBBB'

grViz(paste0("
digraph lag_grid {

  graph [
    rankdir  = TB,
    fontname = 'Arial',
    bgcolor  = 'white',
    nodesep  = 0.50,
    ranksep  = 0.40,
    margin   = 0.3,
    splines = ortho
  ]

  node [
    fontname = 'Arial',
    fontsize = 9,
    style    = 'filled,rounded',
    shape    = box,
    width    = 1.15,
    height   = 0.40,
    penwidth = 0
  ]

  # ===========================================================
  # COLUMN HEADERS
  # ===========================================================
  node [shape = plaintext, fillcolor = 'white', fontsize = 12,
        fontcolor = '", nvy, "', fontname = 'Arial Bold', width = 1.15]

  hdr_a [label = 'A']
  hdr_b [label = 'B']
  hdr_c [label = 'C']
  hdr_d [label = 'D']
  hdr_e [label = 'E']
  hdr_f [label = 'F']

  { rank = same; hdr_a; hdr_b; hdr_c; hdr_d; hdr_e; hdr_f }
  edge [style = invis]
  hdr_a -> hdr_b -> hdr_c -> hdr_d -> hdr_e -> hdr_f

  # ===========================================================
  # ROW 1
  # ===========================================================
  node [shape = box, fontsize = 9, fontcolor = 'white',
        fontname = 'Arial', width = 1.15, height = 0.40]

  r1_a [label = '1', fillcolor = '", red, "']
  r1_b [label = '1', fillcolor = '", red, "']
  r1_c [label = '1', fillcolor = '", red, "']
  r1_d [label = '1', fillcolor = '", red, "']
  r1_e [label = '1', fillcolor = '", red, "']
  r1_f [label = '1', fillcolor = '", red, "']

  { rank = same; r1_a; r1_b; r1_c; r1_d; r1_e; r1_f }
  edge [style = invis]
  r1_a -> r1_b -> r1_c -> r1_d -> r1_e -> r1_f

  # ===========================================================
  # ROW 2
  # ===========================================================
  r2_a [label = '2', fillcolor = '", grn, "']
  r2_b [label = '2', fillcolor = '", grn, "']
  r2_c [label = '2', fillcolor = '", grn, "']
  r2_d [label = '2', fillcolor = '", red, "']
  r2_e [label = '2', fillcolor = '", red, "']
  r2_f [label = '2', fillcolor = '", red, "']

  { rank = same; r2_a; r2_b; r2_c; r2_d; r2_e; r2_f }
  edge [style = invis]
  r2_a -> r2_b -> r2_c -> r2_d -> r2_e -> r2_f

  # ===========================================================
  # ROW 3
  # ===========================================================
  r3_a [label = '3', fillcolor = '", red, "']
  r3_b [label = '3', fillcolor = '", red, "']
  r3_c [label = '3', fillcolor = '", red, "']
  r3_d [label = '3', fillcolor = '", red, "']
  r3_e [label = '3', fillcolor = '", red, "']
  r3_f [label = '3', fillcolor = '", red, "']

  { rank = same; r3_a; r3_b; r3_c; r3_d; r3_e; r3_f }
  edge [style = invis]
  r3_a -> r3_b -> r3_c -> r3_d -> r3_e -> r3_f

  # ===========================================================
  # ROW 4
  # ===========================================================
  r4_a [label = '4', fillcolor = '", red, "']
  r4_b [label = '4', fillcolor = '", grn, "']
  r4_c [label = '4', fillcolor = '", red, "']
  r4_d [label = '4', fillcolor = '", red, "']
  r4_e [label = '4', fillcolor = '", red, "']
  r4_f [label = '4', fillcolor = '", red, "']

  { rank = same; r4_a; r4_b; r4_c; r4_d; r4_e; r4_f }
  edge [style = invis]
  r4_a -> r4_b -> r4_c -> r4_d -> r4_e -> r4_f

  # ===========================================================
  # ROW 5
  # ===========================================================
  r5_a [label = '5', fillcolor = '", red, "']
  r5_b [label = '5', fillcolor = '", red, "']
  r5_c [label = '5', fillcolor = '", red, "']
  r5_d [label = '5', fillcolor = '", red, "']
  r5_e [label = '5', fillcolor = '", red, "']
  r5_f [label = '5', fillcolor = '", red, "']

  { rank = same; r5_a; r5_b; r5_c; r5_d; r5_e; r5_f }
  edge [style = invis]
  r5_a -> r5_b -> r5_c -> r5_d -> r5_e -> r5_f

  # ===========================================================
  # ROW 6
  # ===========================================================
  r6_a [label = '6', fillcolor = '", red, "']
  r6_b [label = '6', fillcolor = '", red, "']
  r6_c [label = '6', fillcolor = '", red, "']
  r6_d [label = '6', fillcolor = '", red, "']
  r6_e [label = '6', fillcolor = '", red, "']
  r6_f [label = '6', fillcolor = '", red, "']

  { rank = same; r6_a; r6_b; r6_c; r6_d; r6_e; r6_f}
  edge [style = invis]
  r6_a -> r6_b -> r6_c -> r6_d -> r6_e -> r6_f

  # ===========================================================
  # ROW 7
  # ===========================================================
  r7_a [label = '6', style = invis]
  r7_b [label = '9', fillcolor = '", nvy, "']  # add external node in row 7 as visible
  r7_c [label = '6', style = invis]
  r7_d [label = '6', style = invis]
  r7_e [label = '6', style = invis]
  r7_f [label = '6', style = invis]

  { rank = same; r7_a; r7_b; r7_c; r7_d; r7_e; r7_f}
  edge [style = invis]
  r7_a -> r7_b -> r7_c -> r7_d -> r7_e -> r7_f

  # ===========================================================
  # CHAIN ARROWS
  # ===========================================================
  edge [style = solid, color = '", gry, "', arrowhead = vee,
        arrowsize = 0.4, penwidth = 0.9]

  r1_a -> r2_a -> r3_a -> r4_a -> r5_a -> r6_a
  r1_b -> r2_b -> r3_b -> r4_b -> r5_b -> r6_b
  r1_c -> r2_c -> r3_c -> r4_c -> r5_c -> r6_c
  r1_d -> r2_d -> r3_d -> r4_d -> r5_d -> r6_d
  r1_e -> r2_e -> r3_e -> r4_e -> r5_e -> r6_e
  r1_f -> r2_f -> r3_f -> r4_f -> r5_f -> r6_f

  # add last row connection with invisble arrows
  edge [style = invis]
  r6_a -> r7_a
  r6_b -> r7_b
  r6_c -> r7_c
  r6_d -> r7_d
  r6_e -> r7_e
  r6_f -> r7_f

  # ===========================================================
  # VERTICAL ORDERING
  # ===========================================================
  edge [style = invis]
  hdr_a -> r1_a

  # Connect green nodes to r7_b

  edge [style = solid, color = '", grn, "', arrowhead = vee,
        arrowsize = 0.6, penwidth = 1.5, constraint = false] # use constraint = false!

  r2_a -> r7_b
  r2_b -> r7_b
  r2_c -> r7_b
  r4_b -> r7_b

}
"))

结果 与您提供的图片接近

注意: 你有重复的代码,因此我建议使用函数+ glue / sprintf / paste,并以底层的颜色矩阵 / 标签矩阵作为输入,这将让构建主网格更容易维护。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章