Проблемы с проектированием UML - подобных диаграмм в графвизе - PullRequest
3 голосов
/ 12 февраля 2012

В настоящее время у меня проблемы с проектированием 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 и3, это поможет мне достичь диаграммы 1.

1 Ответ

2 голосов
/ 24 октября 2013

Ваша первоначальная попытка не была плохой. Я бы сказал, что использование портов, безусловно, путь. Если вы поместите узел в кластер, вы можете использовать границу кластера и скрыть границу узла записи, избавившись от этих разделительных линий.

Как вы заметили, использование обратной косой черты \ больше не работает для выхода из пробела. Обходной путь должен использовать &#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
}
...