советы по созданию графических диаграмм

Я хотел бы программно создавать диаграммы, подобные этой
(источник: yaroslavvb.com)

Я предполагаю, что мне следует использовать 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}]


(источник: yaroslavvb.com)


person Yaroslav Bulatov    schedule 03.11.2010    source источник
comment
Как вы сделали графики, используемые в вашем вопросе?   -  person Simon    schedule 04.11.2010
comment
Нашла их в сети. Я подозреваю, что это было сделано с помощью какого-то пакета Latex.   -  person Yaroslav Bulatov    schedule 04.11.2010
comment
Вольфрам рассказывает о функции графа выделения примерно в 9:15 в youtube.com/watch?v=8afAaSiwD78. -- может быть, это будет встроено в следующую версию?   -  person Simon    schedule 13.11.2010
comment
Интересно... кстати, похоже, что блокноты презентаций TechCon были опубликованы (хотя и не от Wolfram) -- wolfram.com/events/techconf2010/speakers.html   -  person Yaroslav Bulatov    schedule 13.11.2010
comment
reference.wolfram.com/mathematica/ref/HighlightGraph.html   -  person Simon    schedule 15.11.2010


Ответы (3)


Немного обобщая ответ Самсдрама, я получаю

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


РЕДАКТИРОВАТЬ № 1: очищенную версию этого кода можно найти по адресу http://gist.github.com/663438

РЕДАКТИРОВАТЬ № 2. Как обсуждалось в комментариях ниже, шаблон, которому должен соответствовать мой edges, представляет собой список пограничных правил с необязательными метками. Это немного менее общее, чем то, что используется функцией GraphPlot (и версией, приведенной выше gist). ), где пограничные правила также разрешено заключать в Tooltip.

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

Network`GraphPlot`RuleListGraphQ[x_] := 
  ListQ[x] && Length[x] > 0 && 
    And@@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)[_ -> _, _])..} эквивалентен и более лаконичен...

person Simon    schedule 04.11.2010
comment
что вы пытаетесь сопоставить с рисунком краев? - person Yaroslav Bulatov; 04.11.2010
comment
Порядок вершин в GraphicsComplex, сгенерированный GraphPlot, — это просто порядок их появления в edges. Мой verts=... — это просто уродливый способ получить этот список вершин в том порядке, в котором они встречаются, чтобы я знал, какие координаты извлечь из g и передать команде Graphics. Это кладж, вызванный тем фактом, что если VertexLabeling->False, то GraphPlot не хранит никакой информации о том, какая вершина какая. - person Simon; 04.11.2010
comment
ic... кажется, вы можете обойти это с помощью VertexList/GraphCoordinates. На самом деле я спрашивал о краях: шаблон в определении функции. Например, он соответствует {3 -> 4, 4 -> 5, {6 -> 7, 2}}. - person Yaroslav Bulatov; 04.11.2010
comment
@Ярослав Я не знал о VertexList - это намного лучше. Что касается шаблона, это тот же шаблон, который GraphPlot использует при построении списка ребер (в отличие от матрицы смежности). - person Simon; 04.11.2010
comment
Как вы можете сказать, что это образец, который они используют? - person Yaroslav Bulatov; 04.11.2010
comment
@Ярослав Я не могу ... но он делает то же самое, что описано в документации. (конечно, поправьте меня, если я ошибаюсь) - person Simon; 05.11.2010
comment
а, понятно, это для ребер с опциональной меткой - person Yaroslav Bulatov; 05.11.2010
comment
Да, края с необязательными метками. На самом деле, немного покопавшись, вы обнаружите, что Mma использует проверку: NetworkGraphPlotRuleListGraphQ[x_]:=!NetworkGraphPlotDumpPrivatebigMatrixQ[x]&&ListQ[x]&&Length[x]›0&&And@@Map[Head[#1]===Rule||(ListQ[#1] &&Длина[#1]==2&&Заголовок[#1[[1]]]===Правило)||(Заголовок[#1]===Подсказка&&Длина[#1]==2&&Заголовок[#1[[1]]] ===Правило)&,x,{1}]`, которое немного более общее, чем мое, поскольку оно позволяет завернуть Rule в Tooltip. - person Simon; 05.11.2010
comment
@Ярослав 3 шага (извините за беспорядок...) (1)Unprotect[GraphPlot];ClearAttributes[GraphPlot,ReadProtected];Information[GraphPlot] (2)Unprotect[NetworkGraphPlotDumpPrivateRuleListGraphQ];ClearAttributes[NetworkGraphPlotDumpPrivateRuleListGraphQ,ReadProtected];Information[NetworkGraphPlotDumpPrivateRuleListGraphQ]` (3)Unprotect[NetworkGraphPlotRuleListGraphQ];ClearAttributes[NetworkGraphPlotRuleListGraphQ,ReadProtected];Information[NetworkGraphPlotRuleListGraphQ] - person Simon; 05.11.2010
comment
@Simon Ваши последние два комментария очень интересны! Не могли бы вы отредактировать свой ответ и включить их? Здесь, в комментариях, они почти спрятаны для будущих читателей, и я предполагаю, что вам понадобилось немало усилий, чтобы это раскопать. - person Dr. belisarius; 20.11.2010
comment
@belisarius Спасибо. На самом деле это не часть моего ответа, но вы правы, эти вещи теряются в комментариях. Я отредактировал свой ответ. - person Simon; 20.11.2010

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

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

Для более сложных примеров (например, второй справа) я бы рекомендовал нарисовать многоугольник, используя координаты вершин, а затем обвести край многоугольника линией с заглушками. Я не смог найти способ добавить скошенный край непосредственно к многоугольнику. При трассировке периметра многоугольника вам необходимо добавить координату первой вершины к концу отрезка линии, чтобы линия составляла полный периметр многоугольника. Кроме того, существуют две отдельные графические директивы для линий: 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

person Samsdram    schedule 03.11.2010
comment
Как вы можете выделить только подмножество вершин, используя это? - person Simon; 04.11.2010

JoinForm["Round"] будет округлять соединения сегментов линий.

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

Consider

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} закрывает линию в исходной точке.)

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

person Eric Towers    schedule 04.11.2010