创建图表的技巧

发布于 2024-09-30 04:41:02 字数 1624 浏览 2 评论 0原文

我想以编程方式创建这样的图表
(来源:yaroslavvb.com

我想我应该将 GraphPlot 与 VertexCooperativeRules、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

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

回心转意 2024-10-07 04:41:02

概括一下 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]} &)]

Mathematicagraphics


编辑#1:
可以在 http://gist.github.com/663438 找到此代码的清理版本

编辑#2:
正如下面的评论中所讨论的,我的边缘必须匹配的模式是带有可选标签的边缘规则列表。这比 GraphPlot 函数(以及上面的版本 要点),其中边缘规则也可以包含在工具提示中。

为了找到 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}]

我认为我的边缘:{((_ -> _) | (List|Tooltip)[_ -> _, _])..} 模式是等效的并且更简洁......

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]} &)]

Mathematica graphics


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...

↙厌世 2024-10-07 04:41:02

对于仅连接两个节点的简单示例(如最右侧的示例),您可以像这样绘制带有上限端点的线。

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]}]

Mathematicagraphics

对于更复杂的示例(如右数第二个),我建议使用顶点坐标绘制多边形,然后进行跟踪带有顶线的多边形边缘。我找不到直接向多边形添加斜边的方法。追踪多边形的周长时,需要将第一个顶点的坐标添加到构成多边形完整周长的线段的末端。此外,还有两个单独的线条图形指令: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 图形

For simple examples where you are only connecting two nodes (like your example on the far right), you can draw lines with capped end points like this.

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

For more complex examples (like second from the right) I would recommend drawing a polygon using the vertex coordinates and then tracing the edge of the polygon with a capped line. I couldn't find a way to add a beveled edge directly to a polygon. When tracing the perimeter of the polygon you need to add the coordinate of the first vertex to the end of the line segment that the line makes the complete perimeter of the polygon. Also, there are two separate graphics directives for lines CapForm, which dictates whether to bevel the ends of the line, and JoinForm, which dictates whether to bevel the intermediate points of the line.

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

情话难免假 2024-10-07 04:41:02

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} 在起点处关闭线路。)

有足够的空间进行美化,但我认为这涵盖了您上面没有提到的成分。

JoinForm["Round"] will round the joins of line segments.

You'll want a filled polygon around the centers of the vertices in the colored region, then a JoinForm["Round"], ..., Line[{...}] to get the rounded corners.

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

where foo[[1,1,1,1,1]] is the list of vertex centers and {2,5,6} pulls out the {b,e,f} vertices. ({2,5,6,2} closes the line back at its starting point.)

There's plenty of room for prettifying, but I think this covers the ingredient you didn't mention above.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文