在graphviz中设计类似UML的图表的问题

时间:2012-02-12 18:45:14

标签: graphviz image-graphviz

我目前在graphiz上设计类似UML的图表时遇到问题。问题的原因是它们不完全是UML图。主要区别在于我使用缩进来为对象的属性添加层次结构。实现这些特性对我来说有点困难。我想要实现的是:

diagram 1

我通常使用名为record的节点形状来设计这些图表。当我必须链接其中两个类似UML的图表时,问题就像UML中的关系一样,即聚合,关联,组合等。

当我有图表时,我无法与箭头建立关系,因为箭头只是从一个节点的随机部分到另一个节点的另一个随机部分。 我有类似UML的图表的方式很好,但关系箭头使它不是我想要的,因为我希望箭头从一个节点的特定点到另一个特定点另一个节点。

diagram 2

我用来创建此图表的DOT代码如下:

digraph G {

    fontname = "Bitstream Vera Sans"
    fontsize = 8

    node [
        fontname = "Bitstream Vera Sans"
        fontsize = 8
        shape = "record"
    ]

    edge [
        fontname = "Bitstream Vera Sans"
        fontsize = 8    
    ]

    Person [
        label = "{Person \l\l \ age : int\l \ livesIn : City \l \  \ \ sinceYear : int}"
    ] // \l -new line, \ -indentation

    City [
        label = "{City \l \ \ name : string}"
    ]

    Person -> City
}

我尝试通过在节点内使用水平线划分来解决这个问题,即使我不想要这些线。水平线划分使我可以使用ports使这种特定关系成为可能,但它们会产生一个新的问题。他们创建的问题是他们摆脱了我想要的缩进并在上一个图中。我试图解决箭头问题的方法有效,但是会产生新问题 - 缩进消失,水平线划分不能隐藏

diagram 3

我用来创建此图表的代码是:

digraph G {

    fontname = "Bitstream Vera Sans"
    fontsize = 8

    node [
        fontname = "Bitstream Vera Sans"
        fontsize = 8
        shape = "record"
        penwidth = 0.5 
    ]

    edge [
        fontname = "Bitstream Vera Sans"
        fontsize = 8    
    ]

    Person [
        label = "{<g0> Person | <g1> age : int | <g2> livesIn : City | <g3> sinceYear : int}"
    ] // \l -new line, \ -indentation

    City [
        label = "{<f0> City | <f1> name : string}"
    ]

    Person:<g2> -> City:<f1> [arrowhead = "empty", headlabel = "*"]
}

这些缩进是这段关系的重要组成部分,所以我想知道是否有人知道我能做些什么才能在图表中包含这些缩进以及我可以做些什么来使水平线划分不可见?

如果有人有更好的方式/想法,我也会感激,这与我在图2和图2中所做的完全不同。 3,这将帮助我实现图1。

1 个答案:

答案 0 :(得分:2)

你原来的尝试并不坏。我会说使用端口肯定是要走的路。 如果将节点放在群集中,则可以使用群集的边框并隐藏记录节点的边框,去掉那些分隔线。

正如您所指出的,使用反斜杠\不再适用于逃避空间。解决方法是使用&#92;代替,这将转义空白。作为替代方案,您还可以使用&nnbsp;替换每个空格。任何一个都会达到要求的效果。

我做了一些小改动以使事情更具可读性,例如将Graph属性放在graph块而不是图的根中,并将端口名重命名为更合理的东西。我还删除了任何未使用的端口。

我想出的最终结果是:

enter image description here

...这是我使用的DOT代码:

digraph G {

    graph [
        compound = true     // To clip the head at the cluster border
        penwidth = 2        // Make the cluster's borders a bit thicker
        rankdir = "LR"      // Make the arrow and nodes go from Left to Right
        ranksep = 1         // Add a bit more space inbetween nodes
    ]

    node [
        color = none        // Hide the node's border
        fontname = "Bitstream Vera Sans"
        height = 0          // Make the node as small as possible (it will grow if it needs more space)
        margin = 0          // Remove unneeded whitespace
        shape = "record"    // So we can use ports
    ]

    edge [
        arrowhead = "open"
        labelangle = -5     // Place the asteriks closer to the line
        labeldistance = 2.5 // Place the asteriks further away from the arrow head
        penwidth = 2        // Make the line a bit thicker
    ]

    /* @NOTE: escaping spaces in the label using '\' doesn't work so use '&nbsp' or '&#92' instead. */
    subgraph cluster_Person {
        Person [
            label = "\N\l | &#92; &#92; &#92;  age : int\l | <livesIn> &#92; &#92; &#92;  livesIn : City\l | &#92; &#92; &#92; &#92; &#92; &#92;  sinceYear : int\l"
        ]
    }

    subgraph cluster_City {
        City [
            label = "<city> \N\l | &#92; &#92; &#92;  name : string\l"
        ]
    }

    Person:livesIn -> City:city [headlabel = "*", lhead = "cluster_City"] // lhead allows us to point to the cluster's border instead of the node, as long as we add `compound = true` to the graph
}