2010-11-03 8 views
14

Ich möchte programmatisch Diagramme erstellen, wie diese http://yaroslavvb.com/upload/junction-tree-decomposition.pngTipps zum Erstellen von Graph-Diagramme

Ich kann mir vorstellen sollte ich GraphPlot mit VertexCoordinateRules, VertexRenderingFunction und EdgeRenderingFunction für die Graphen verwenden. Was sollte ich für farbige abgeschrägte Hintergründe verwenden?

bearbeiten Verwendung vor allem Ideen Simons, hier ist eine vereinfachte „weniger robust“ Version, die ich am Ende mit

 
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

Malen? : D Nur ein Witz –

+0

Wie haben Sie die Grafiken in Ihrer Frage verwendet? – Simon

+0

Sie wurden im Internet gefunden. Ich vermute, dass es mit irgendeinem Latex-Paket gemacht wurde. –

Antwort

11

verallgemeinern Samsdram Antwort ein bisschen, erhalte ich

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

Einige der angezeigten Code ein wenig robuster gemacht werden könnte, aber es funktioniert:

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: Eine bereinigte Version dieses Codes kann beigefunden werden

EDIT # 2: Wie unten in den Kommentaren diskutiert, ist das Muster, das mein edges übereinstimmen muss eine Liste von Rand Regeln mit optionaler Etiketten. Dies ist etwas weniger allgemein als das, was von der GraphPlot-Funktion (und von der Version in dem obigen gist) verwendet wird, wo die Kantenregeln auch in einem Tooltip verpackt werden dürfen.

das genaue Muster von GraphPlot verwendet, um finde ich das Objekt von Interesse wiederholt Unprotect[fn];ClearAttributes[fn,ReadProtected];Information[fn] verwendet, wo fn ist, bis ich, dass es fanden die folgende (bereinigt) verwendete Funktion:

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

Ich denke, dass meine edges:{((_ -> _) | (List|Tooltip)[_ -> _, _])..} Muster ist äquivalent und prägnanter ...

+0

was versuchst du mit "Kanten" Muster zu vergleichen? –

+0

Die Reihenfolge der Scheitelpunkte im 'GraphicsComplex', die von' GraphPlot' generiert werden, ist einfach die Reihenfolge, in der sie in 'Kanten' auftreten. Meine 'verts = ...' ist nur eine hässliche Art, diese Liste von Scheitelpunkten in der Reihenfolge zu erhalten, in der sie vorkommen, so dass ich weiß, welche Koordinaten aus 'g' extrahiert werden und an den' Graphics'-Befehl übergeben werden. Es ist ein Kludn, der dadurch bedingt ist, dass GraphPlot, wenn 'VertexLabeling-> False 'ist, keine Information darüber speichert, welcher Vertex welcher ist. – Simon

+0

ic ... es scheint, dass Sie mit VertexList/GraphCoordinates umgehen können. Ich habe tatsächlich nach Kanten gefragt: Muster in Funktionsdefinition. Zum Beispiel entspricht es {3 -> 4, 4 -> 5, {6 -> 7, 2}} –

5

Für einfache Beispiele, bei denen Sie nur zwei Knoten verbinden (wie Ihre Beispiel ganz rechts), können Sie Linien mit gekappten Endpunkten so zeichnen.

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

Für komplexere Beispiele (wie die zweite von rechts) I würde Koordinaten einen Polygons mit den Ecken empfehlen zeichnen und dann mit einer verkappten Linie, die die Kante des Polygons Tracing. Ich konnte keine Möglichkeit finden, eine abgeschrägte Kante direkt einem Polygon hinzuzufügen. Wenn Sie den Umfang des Polygons nachzeichnen, müssen Sie die Koordinate des ersten Eckpunkts zum Ende des Liniensegments hinzufügen, in dem die Linie den vollständigen Umfang des Polygons bildet. Außerdem gibt es zwei separate Grafikdirektiven für die Linien CapForm, die festlegt, ob die Enden der Linie abgeschrägt werden sollen, und JoinForm, das vorschreibt, ob die Zwischenpunkte der Linie abgeschrägt werden sollen.

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

Wie können Sie nur eine Teilmenge von Vertices mit diesem markieren? – Simon

4

JoinForm [ "Round"] rundet die von Liniensegmenten verbindet.

Sie wollen ein gefülltes Polygon um die Mittelpunkte der Scheitelpunkte in der farbigen Region, dann ein JoinForm["Round"], ..., Line[{...}], um die abgerundeten Ecken zu erhalten.

Betrachten

 
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

wo foo [[1,1,1,1,1]] Die folgende Liste von Scheitelpunktzentren und {2,5,6} zieht die {b, e, f } Vertices. ({2,5,6,2} schließt die Linie wieder an ihrem Anfangspunkt.)

Es gibt viel Platz zum Verschönern, aber ich denke, das deckt die Zutaten ab, die Sie oben nicht erwähnt haben.