2010-11-03 3 views
14

Я хотел бы программно создавать диаграммы, как этот http://yaroslavvb.com/upload/junction-tree-decomposition.pngсоветы по созданию диаграмм Graph

Я полагаю, я должен использовать GraphPlot с VertexCoordinateRules, VertexRenderingFunction и EdgeRenderingFunction для графиков. Что я должен использовать для цветных скошенных фонов?

Редактировать Используя идеи в основном Саймона, вот это упрощенная «менее надежный» версия, которую я закончил с использованием

 
Needs["GraphUtilities`"]; 
GraphPlotHighlight[edges_, verts_, color_] := Module[{}, 
    vpos = Position[VertexList[edges], Alternatives @@ verts]; 
    coords = Extract[GraphCoordinates[edges], vpos]; 
    (* add .002 because end-cap disappears when segments are almost colinear *) 
    AppendTo[coords, First[coords] + .002]; 
    Show[Graphics[{color, CapForm["Round"], JoinForm["Round"], 
    Thickness[.2], Line[coords], Polygon[coords]}], 
    GraphPlot[edges], ImageSize -> 150] 
    ] 

SetOptions[GraphPlot, 
    VertexRenderingFunction -> ({White, EdgeForm[Black], Disk[#, .15], 
     Black, Text[#2, #1]} &), 
    EdgeRenderingFunction -> ({Black, Line[#]} &)]; 
edges = GraphData[{"Grid", {3, 3}}, "EdgeRules"]; 
colors = {LightBlue, LightGreen, LightRed, LightMagenta}; 
vsets = {{8, 5, 2}, {7, 5, 8}, {9, 6, 3}, {8, 1, 2}}; 
MapThread[GraphPlotHighlight[edges, #1, #2] &, {vsets, colors}] 

http://yaroslavvb.com/upload/mathematica-graphs.png

+0

Краска? : D Просто шутка –

+0

Как вы сделали графики, используемые в вашем вопросе? – Simon

+0

Нашли их в Интернете. Я подозреваю, что это было сделано с некоторыми пакетами из латекса –

ответ

11

ответ обобщающего Samsdram немного, я получаю

GraphPlotHighlight[edges:{((_->_)|{_->_,_})..},hl:{___}:{},opts:OptionsPattern[]]:=Module[{verts,coords,g,sub}, 
    verts=Flatten[edges/.Rule->List]//.{a___,b_,c___,b_,d___}:>{a,b,c,d}; 
    g=GraphPlot[edges,FilterRules[{opts}, Options[GraphPlot]]]; 
    coords=VertexCoordinateRules/.Cases[g,HoldPattern[VertexCoordinateRules->_],2]; 
    sub=Flatten[Position[verts,_?(MemberQ[hl,#]&)]]; 
    coords=coords[[sub]];  
    Show[Graphics[{OptionValue[HighlightColor],CapForm["Round"],JoinForm["Round"],Thickness[OptionValue[HighlightThickness]],Line[AppendTo[coords,First[coords]]],Polygon[coords]}],g] 
] 
Protect[HighlightColor,HighlightThickness]; 
Options[GraphPlotHighlight]=Join[Options[GraphPlot],{HighlightColor->LightBlue,HighlightThickness->.15}]; 

Некоторые из кода выше можно было бы сделать немного более надежным, но это работает:

GraphPlotHighlight[{b->c,a->b,c->a,e->c},{b,c,e},VertexLabeling->True,HighlightColor->LightRed,HighlightThickness->.1,VertexRenderingFunction -> ({White, EdgeForm[Black], Disk[#, .06], 
Black, Text[#2, #1]} &)] 

Mathematica graphics


EDIT # 1: Очищенная версия этого кода находится на

EDIT # 2: Как уже говорилось в комментариях ниже, шаблон, что мой edges должен соответствовать список краевыми правил с дополнительными этикетками. Это немного меньше общего, чем то, что используется функцией GraphPlot (и по версии выше gist), где правила края также могут быть обернуты в Tooltip.

Чтобы найти нужный шаблон, используемый GraphPlot я неоднократно использовал Unprotect[fn];ClearAttributes[fn,ReadProtected];Information[fn] где fn является объектом интереса, пока я не обнаружил, что он использовал (очищенное вверх) функцию следующее:

Network`GraphPlot`RuleListGraphQ[x_] := 
    ListQ[x] && Length[x] > 0 && 
    [email protected]@Map[Head[#1] === Rule 
     || (ListQ[#1] && Length[#1] == 2 && Head[#1[[1]]] === Rule) 
     || (Head[#1] === Tooltip && Length[#1] == 2 && Head[#1[[1]]] === Rule)&, 
     x, {1}] 

Я думаю, что мой edges:{((_ -> _) | (List|Tooltip)[_ -> _, _])..} узор эквивалентен и более кратким ...

+0

Что вы пытаетесь совместить с рисунком "edge"? –

+0

Порядок вершин в «GraphicsComplex», сгенерированный 'GraphPlot', - это просто порядок, который они имеют в' edge'. Мой 'verts = ...' является всего лишь уродливым способом получить этот список вершин в том порядке, в котором они встречаются, чтобы я знал, какие координаты извлечь из 'g' и перейти к команде« Graphics ». Это неудобство, вызванное тем, что если «VertexLabeling-> False», то GraphPlot не хранит никакой информации о том, какая именно вершина. – Simon

+0

ic ... кажется, вы можете обойти это с помощью VertexList/GraphCoordinates. Я действительно спрашивал о границах: шаблон в определении функции. Например, он соответствует {3 -> 4, 4 -> 5, {6 -> 7, 2}} –

5

Для простых примеров, когда вы только соединения двух узлов (например, ваш пример справа), вы можете рисовать линии с закрытыми конечными точками, как это.

vertices = {a, b}; 
Coordinates = {{0, 0}, {1, 1}}; 
GraphPlot[{a -> b}, VertexLabeling -> True, 
VertexCoordinateRules -> 
    MapThread[#1 -> #2 &, {vertices, Coordinates}], 
Prolog -> {Blue, CapForm["Round"], Thickness[.1], Line[Coordinates]}] 

Mathematica graphics

Для более сложных примеров (например, второй справа) я рекомендовал бы рисование многоугольника, используя координаты вершин, а затем трассировки краев многоугольника с блокированной линией. Я не мог найти способ добавить скошенный край непосредственно к полигону. При прослеживании периметра многоугольника вам нужно добавить координату первой вершины в конец отрезка линии, чтобы линия делала полный периметр полигона. Кроме того, существуют два отдельных графических директивы для строк CapForm, которые определяют, нужно ли скосить концы строки и JoinForm, что диктует, скопировать промежуточные точки линии.

vertices = {a, b, c}; 
Coordinates = {{0, 0}, {1, 1}, {1, -1}}; 
GraphPlot[{a -> b, b -> c, c -> a}, VertexLabeling -> True, 
VertexCoordinateRules -> 
    MapThread[#1 -> #2 &, {vertices, Coordinates}], 
Prolog -> {Blue, CapForm["Round"], JoinForm["Round"], Thickness[.15], 
    Line[AppendTo[Coordinates, First[Coordinates]]], 
    Polygon[Coordinates]}] 

Mathematica graphics

+0

Как вы можете выделить только подмножество вершин, используя это? – Simon

4

JoinForm [ "Round"] будет округлить стыки отрезков.

Вам понадобится заполненный многоугольник вокруг центров вершин в цветной области, а затем JoinForm["Round"], ..., Line[{...}], чтобы получить закругленные углы.

Рассмотрим

 
foo = GraphPlot[{a -> b, a -> c, b -> d, b -> e, b -> f, c -> e, e -> f}, 
    VertexRenderingFunction -> 
    ({White, EdgeForm[Black], Disk[#, .1], Black, Text[#2, #1]} &)] 
Show[ 
    Graphics[{ 
     RGBColor[0.6, 0.8, 1, 1], 
     Polygon[foo[[1, 1, 1, 1, 1, {2, 5, 6, 2}]]], 
     JoinForm["Round"], Thickness[0.2], 
     Line[foo[[1, 1, 1, 1, 1, {2, 5, 6, 2}]]] 
    }], 
    foo 
] 
Mathematica graphics

, где Foo [[1,1,1,1,1]] список вершин и центров {2,5,6} вытаскивает {B, E, F } вершин. ({2,5,6,2} закрывает линию обратно в исходную точку.)

Существует много места для преувеличения, но я думаю, что это покрывает ингредиент, о котором вы не упомянули выше.

Смежные вопросы