创建图表的技巧 [英] tips for creating Graph diagrams
问题描述
我想以编程方式创建这样的图表
(来源:
(来源: 找到此代码的清理版本
编辑#2:正如下面的评论中所讨论的,我的 edges
必须匹配的模式是带有可选标签的 edge 规则 列表.这比 GraphPlot
函数(以及上述 gist),其中 边缘规则 也允许包含在 Tooltip
中.
为了找到 GraphPlot
使用的确切模式,我反复使用了 Unprotect[fn];ClearAttributes[fn,ReadProtected];Information[fn]
其中 fn
是感兴趣的对象,直到我发现它使用了以下(清理过的)函数:
Network`GraphPlot`RuleListGraphQ[x_] :=ListQ[x] &&长度[x] >0 &&And@@Map[Head[#1] === 规则||(ListQ[#1] && Length[#1] == 2 && Head[#1[[1]]] === 规则)||(头部[#1] === 工具提示&& 长度[#1] == 2 && 头部[#1[[1]]] === 规则)&,x, {1}]
我认为我的 edges:{((_ -> _) | (List|Tooltip)[_ -> _, _])..}
模式是等效的,更简洁...
I'd like to programmatically create diagrams like this
(source: yaroslavvb.com)
I imagine I should use GraphPlot with VertexCoordinateRules, VertexRenderingFunction and EdgeRenderingFunction for the graphs. What should I use for colored beveled backgrounds?
Edit Using mainly Simon's ideas, here's a simplified "less robust" version I ended up using
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}]
(source: yaroslavvb.com)
Generalising Samsdram's answer a bit, I get
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}];
Some of the code above could be made a little more robust, but it works:
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]} &)]
EDIT #1: A cleaned up version of this code can be found at http://gist.github.com/663438
EDIT #2:
As discussed in the comments below, the pattern that my edges
must match is a list of edge rules with optional labels. This is slightly less general than what is used by the GraphPlot
function (and by the version in the above gist) where the edge rules are also allowed to be wrapped in a Tooltip
.
To find the exact pattern used by GraphPlot
I repeatedly used Unprotect[fn];ClearAttributes[fn,ReadProtected];Information[fn]
where fn
is the object of interest until I found that it used the following (cleaned up) function:
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}]
I think that my edges:{((_ -> _) | (List|Tooltip)[_ -> _, _])..}
pattern is equivalent and more concise...
这篇关于创建图表的技巧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!