Heute brauche ich wieder Ihre Hilfe, um mit dem Paket fertig zu werden forest
(es ist ein wirklich leistungsstarkes Paket, aber auch ziemlich komplex). Im Grunde habe ich bereits mehrere Stunden damit verbracht, ein Ultimatumspiel in Baumform zu zeichnen, das so aussehen sollte:
Bisher ist es mir gelungen, diesen Code zu erstellen, der irgendwie funktioniert (aber nicht gut):
\documentclass{report}
\usepackage[T1]{fontenc}
\usepackage{amssymb}
\usepackage{mathtools}
\usepackage{forest}
\usepackage[labelfont=bf,skip=0pt,labelsep=period]{caption}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.6}
\usetikzlibrary{matrix,calc,positioning}
\pgfplotsset{soldot/.style={color=black,only marks,mark=*}}
\pgfplotsset{/pgfplots/xlabel near ticks/.style={/pgfplots/every axis x label/.style={at={(ticklabel cs:0.5)},anchor=near ticklabel}},/pgfplots/ylabel near ticks/.style={/pgfplots/every axis y label/.style={at={(ticklabel cs:0.5)},rotate=90,anchor=near ticklabel}}}
\begin{document}
\begin{figure}
\begin{forest}
for tree={l sep=4em, s sep=8em, anchor=center}
[$P_1$, circle, draw,
[,name=0, edge label={node[midway,left,outer sep=1.5mm,]{$x=0$}}]
[$P_2$, l*=2, before computing xy={s=(s("!p")+s("!n"))/2}, circle, draw, edge label={node[midway,right,]{$x$}}
[{$c-x,x$}, edge label={node[midway,left,outer sep=1.5mm,]{$Y$}}]
[{$0,0$}, edge label={node[midway,right,outer sep=1.5mm,]{$N$}}]]
[,name=1, edge label={node[midway,right,outer sep=1.5mm,]{$x=c$}}]]
\draw (0) to[bend right=45] (1);
\end{forest}
\end{figure}
\end{document}
Die Ausgabe, die ich erhalte, ist diese:
Idealerweise möchte ich mehrere Dinge ändern. Erstens möchte ich, dass (a) die gekrümmte Linie die Zweige des Baums berührt, um diesen hässlichen weißen Raum zu vermeiden. Zweitens möchte ich (b) die Überlappung zwischen der gekrümmten Linie und dem Knoten P2 vermeiden. Drittens möchte ich (c) sicherstellen, dass die Winkel der beiden Zweige in den beiden Knoten gleich sind. Mit anderen Worten, der Winkel des zweiten Knotens ist größer als der des ersten Knotens, und ich möchte, dass sie gleich sind. Viertens möchte ich, dass (d) die Zweige des zweiten Knotens möglichst kürzer sind als die des ersten. Alle Fragen sind gleichermaßen relevant. Jede Hilfe zu einem der vier Probleme wird sehr geschätzt.
PS: Idealerweise möchte ich so weit wie möglich bei meinem aktuellen Code bleiben (mit anderen Worten, ich möchte die unbedingt notwendigen Mindeständerungen am Code vornehmen, um die erforderlichen Änderungen zu erhalten, da es sich um einen Code handelt, den ich mehr oder weniger leicht verstehen kann).
Antwort1
Hier ist eine Lösung, die meiner Meinung nach alle genannten Anforderungen erfüllt. Ich bin aufgrund des Zielbildes davon ausgegangen, dass Sie nicht möchten, dass der Bogen den obersten Punkt des Knotens verfehlt P_2
. Wenn dies nicht erforderlich ist, müssen Sie sich mit einigen der in meinem Code enthaltenen Berechnungen nicht befassen.
\documentclass[tikz, border=10pt, multi]{standalone}
Wir laden through
TikZ calc
-Bibliotheken, um den Bogen korrekt zu zeichnen.
\usetikzlibrary{through,calc}
\usepackage{forest}
Nun richten wir einige Stile ein. Einige davon vereinfachen Ihren vorhandenen Code. Wenn Sie sie nicht verwenden möchten, können Sie sie weglassen.
\forestset{%
auto edge label
automatisiert den Code zur Formatierung der edge label
. Es erstellt den Knoten, versetzt den Inhalt in den Mathematikmodus und entscheidet, ob das Label links oder rechts vom Rand platziert wird. Das bedeutet, dass
edge label=x^2, auto edge label
wird das Richtige tun.
auto edge label/.style={%
before typesetting nodes={%
Tun Sie nichts, wenn es der Stammknoten ist.
if level=0{}{
Wenn sich der Knoten in der zweiten Hälfte der untergeordneten Knoten seines Elternteils befindet oder wenn er das mittlere untergeordnete Knoten ist ...
if={n()>(n_children("!u")/2)}{
Wenn der Knoten das mittlere untergeordnete Element ist ...
if={n()==((n_children("!u")+1)/2)}{
edge label/.wrap value={
node[midway, right] {$##1$}
},
}{
Wenn sich der Knoten in der zweiten Hälfte der untergeordneten Knoten seines übergeordneten Knotens befindet ...
edge label/.wrap value={
node[midway, outer sep=1.5mm, right] {$##1$}
},
},
}{
Wenn sich der Knoten in der ersten Hälfte der untergeordneten Knoten seines übergeordneten Knotens befindet ...
edge label/.wrap value={
node[midway, outer sep=1.5mm, left] {$##1$}
},
}
},
},
},
Dies ist der Stil für schönere leere Knoten. Er stammt von Seite 65 des aktuellen Handbuchs. Er ist Teil der linguistics
Bibliothek. Wenn Sie diese Bibliothek verwenden, können Sie diese Definition also weglassen und den Stil direkt anwenden.
Beachten Sie, dass sich die Erklärung in diesem Teil des Handbuchs meiner Meinung nach fälschlicherweise auf nicht vorhandene Optionen bezieht, aber da bin ich mir nicht sicher.
nice empty nodes/.style={% page 65 of the manual - this is from the linguistics library
for tree={
calign=fixed edge angles
},
delay={
where content={}{
shape=coordinate,
for parent={
for children={anchor=north}
}
}{}
}
},
Dies ist der Stil zum Zeichnen der Bögen. Sie übergeben dies als Option an das übergeordnete Element der Knoten, durch die der Bogen gezeichnet werden soll.
Außer zum zweiten Kind werden keine Kanten als Teil des Baums selbst gezeichnet. Wenn es mehr als 3 Kinder geben könnte, müsste dies etwas ausgefeilter werden. Dieser Code geht von 3 Kindern aus.
Stattdessen wird der Bogen anschließend gezeichnet, indem die entsprechenden Punkte basierend auf der Position des mittleren Knotens und dem Standardwinkel zu den Knoten bei Verwendung berechnet werden calign=fixed edge angles
. Die Kanten zum ersten und dritten Kind werden zu diesem Zeitpunkt gezeichnet.
[Dies sollte im Hinblick auf die Überprüfung verschiedener Möglichkeiten eigentlich etwas ausgefeilter sein, aber in relevanten Fällen wie dem MWE sollte es funktionieren.]
arc below/.style={
tikz+={%
\clip (.center) coordinate (o) -- (!1.north) coordinate (a) |- (!2.north) coordinate (b) -| (!3.north) coordinate (c) -- cycle;
\node [draw, circle through={(b)}] at (o) {};
\draw [\forestoption{edge}] () -- ($(o)!1!-35:(b)$) ($(o)!1!35:(b)$) -- ();
},
for children={
if n=2{}{no edge},
}
}
}
Einfacher TikZ-Stil für mehr Komfort.
\tikzset{%
my circle/.style={draw, circle}
}
Dann können wir das Ganze einfach wie folgt auf den Baum anwenden.
\begin{document}
\begin{forest}
for tree={
Vom MWE.
l sep=4em,
s sep=8em,
Wenden Sie zwei der neuen Stile auf den gesamten Baum an.
auto edge label,
nice empty nodes,
Setzen Sie alle Knoten in den Mathematikmodus, um Dollarzeichen zu sparen.
math content,
}
Geben Sie den arc below
Stil für die Wurzel an.
[P_1, my circle, arc below
[, edge label={x=0}]
[P_2, my circle, edge label=x
[{c-x,x}, edge label=Y]
[{0,0}, edge label=N]
]
[, edge label={x=c}]
]
\end{forest}
\end{document}
Vollständiger Code:
\documentclass[tikz, border=10pt, multi]{standalone}
\usetikzlibrary{through,calc}
\usepackage{forest}
\forestset{%
auto edge label/.style={%
before typesetting nodes={%
if level=0{}{
if={n()>(n_children("!u")/2)}{
if={n()==((n_children("!u")+1)/2)}{
edge label/.wrap value={
node[midway, right] {$##1$}
},
}{
edge label/.wrap value={
node[midway, outer sep=1.5mm, right] {$##1$}
},
},
}{
edge label/.wrap value={
node[midway, outer sep=1.5mm, left] {$##1$}
},
}
},
},
},
nice empty nodes/.style={% page 65 of the manual - this is from the linguistics library
for tree={
calign=fixed edge angles
},
delay={
where content={}{
shape=coordinate,
for parent={
for children={anchor=north}
}
}{}
}
},
arc below/.style={
tikz+={%
\clip (.center) coordinate (o) -- (!1.north) coordinate (a) |- (!2.north) coordinate (b) -| (!3.north) coordinate (c) -- cycle;
\node [draw, circle through={(b)}] at (o) {};
\draw [\forestoption{edge}] () -- ($(o)!1!-35:(b)$) ($(o)!1!35:(b)$) -- ();
},
for children={
if n=2{}{no edge},
}
}
}
\tikzset{%
my circle/.style={draw, circle}
}
\begin{document}
\begin{forest}
for tree={
l sep=4em,
s sep=8em,
auto edge label,
nice empty nodes,
math content,
}
[P_1, my circle, arc below
[, edge label={x=0}]
[P_2, my circle, edge label=x
[{c-x,x}, edge label=Y]
[{0,0}, edge label=N]
]
[, edge label={x=c}]
]
\end{forest}
\end{document}
BEARBEITEN
Wenn Sie den Abstand zwischen den ersten beiden Ebenen des Baums weiter vergrößern möchten, können Sie am einfachsten den Wert für l sep
den Stammknoten erhöhen. Hier ist ein absichtlich übertriebenes Beispiel:
\begin{forest}
for tree={
l sep=4em,
s sep=8em,
auto edge label,
nice empty nodes,
math content,
}
[P_1, my circle, arc below, l sep*=6
[, edge label={x=0}]
[P_2, my circle, edge label=x
[{c-x,x}, edge label=Y]
[{0,0}, edge label=N]
]
[, edge label={x=c}]
]
\end{forest}
Hier wird der Mindestabstand zwischen der Wurzel und ihren untergeordneten Elementen auf das Sechsfache des üblichen Mindestabstands zwischen Ebenen mit festgelegt l sep*=6
. Wenn Sie lieber einen absoluten Betrag hinzufügen möchten, können Sie sagen l sep+=<dimension>
. Oder wenn Sie einfach die Standardeinstellung überschreiben möchten, l sep=<dimension>
gibt den Mindestabstand genau an.
Es ist wichtig, dass l sep
sichergestellt wird, dassMinimumAbstand. Wenn also l sep
für eine Ebene sehr klein und für eine andere etwas größer eingestellt ist, kann es sein, dass Sie in beiden Fällen den gleichen Abstand erhalten, da andere Faktoren dazu führen, dassWalderfordert, dass die Knoten in größeren Abständen angeordnet sind als die jeweils angegebenen Mindestabstände.
Ich stelle fest, dass Ihr tatsächlicher Zielbaum nicht dem in der Frage gezeigten entspricht. Tatsächlich ist der schwierigste Teil meines obigen Codes für Ihren endgültigen Baum überhaupt nicht erforderlich.
Hier ist eine automatisierte Version dieses Baums als Referenz. Diese Version verzichtet auf die TikZ-Bibliotheken, da sie nur für benötigt werden arc below
. arc through
ist ein neuer Stil, der mit den West- und Ostankern verbunden wird, anstatt durch den Nordanker zu verlaufen. my arc
bestimmt den Stil des Bogens. Dies kann im Baum festgelegt werden, indem my arcs={<key list>}
der Stil bestimmt wird. Standardmäßig ist es leer und der Bogen wird mit dem Stil der aktuellen edge
Option gezeichnet. Durch Festlegen des Stils mit my arcs
kann der edge
Stil ergänzt oder überschrieben werden. Beispielsweise kann der Bogen densely dashed
gerade sein, wenn die Kanten durchgezogen gezeichnet sind.
\forestset{%
arc through/.style={
tikz+={%
\path [\forestoption{edge}, my arc] (!1) [out=-35, in=180] to (!2.west) (!2.east) [out=0, in=-145] to (!3);
}
},
my arcs/.code={%
\tikzset{%
my arc/.style={#1},
}
},
}
\tikzset{%
my arc/.style={},
}
\documentclass[tikz, border=10pt, multi]{standalone}
\usepackage{forest}
\forestset{%
auto edge label/.style={%
before typesetting nodes={%
if level=0{}{
if={n()>(n_children("!u")/2)}{
if={n()==((n_children("!u")+1)/2)}{
edge label/.wrap value={
node[midway, right] {$##1$}
},
}{
edge label/.wrap value={
node[midway, outer sep=1.5mm, right] {$##1$}
},
},
}{
edge label/.wrap value={
node[midway, outer sep=1.5mm, left] {$##1$}
},
}
},
},
},
nice empty nodes/.style={% page 65 of the manual - this is from the linguistics library
for tree={
calign=fixed edge angles
},
delay={
where content={}{
shape=coordinate,
for parent={
for children={anchor=north}
}
}{}
}
},
arc through/.style={
tikz+={%
\path [\forestoption{edge}, my arc] (!1) [out=-35, in=180] to (!2.west) (!2.east) [out=0, in=-145] to (!3);
}
},
my arcs/.code={%
\tikzset{%
my arc/.style={#1},
}
},
}
\tikzset{%
my circle/.style={draw, circle},
my arc/.style={},
}
\begin{document}
\begin{forest}
for tree={
l sep=4em,
s sep=8em,
auto edge label,
nice empty nodes,
math content,
my arcs={densely dashed},
}
[P_1, my circle, arc through
[, edge label={x=0}]
[P_2, my circle, edge label=x
[{c-x,x}, edge label=Y]
[{0,0}, edge label=N]
]
[, edge label={x=c}]
]
\end{forest}
\end{document}
BEARBEITEN BEIseite
Diese Version ist nur fürClément. Obwohl es mehr als 546 Zeichen sind, sind es immer noch nur 644. Und Kile macht den Nur-TikZ-Code 563 Zeichen lang, also zählt meine Statistik die Zeichen wahrscheinlich anders.
Persönlich halte ich das nicht für einen Vorteil, aber so ist es nun einmal.
Es ist nicht sehr transparent, daher empfehle ich die Verwendung nicht wirklich.
Allerdings ist die Art und Weise, wie der Bogen gezeichnet wird, viel schöner als in meinem früheren Code. Ich würde mich wahrscheinlich eher auf diese Methode stützen, arc below
als die through
Bibliothek zu verwenden.
Die größte Zeicheneinsparung wird durch den Verzicht auf Automatisierung erreicht. Die Randbeschriftungen werden nicht mehr automatisch entsprechend der Position des untergeordneten Elements im Verhältnis zu seinen Geschwistern platziert. Wenn Sie also einen Knoten hinzufügen, müssen Sie prüfen, ob aus s left
s werden soll right
oder umgekehrt. Darüber hinaus wird für die Kreise kein Stil verwendet, was die Flexibilität und Wartbarkeit des Codes einschränkt. Schließlich werden Dollarzeichen für den Inhalt von Knoten verwendet, anstatt math content
weil math content,
mehr Zeichen enthalten sind als erforderlich sind, um jedem Knoten, der sie benötigt, ein Paar Dollarzeichen zuzuweisen.
Ironischerweise verwendet die Zeichnung des Bogens jetzt tatsächlichWaldFunktionen stärker und TikZ-Funktionen weniger stark. ( y()
wird mit einem pgfmath-Wrapper verwendet, um die für den Bogen benötigten Informationen zu erhalten, anstatt sich auf die through
Bibliothek zu verlassen.)
\documentclass{standalone}
\usepackage{forest}
\usetikzlibrary{calc}
\begin{document}
\begin{forest}
ey/.style={shape=coordinate,no edge},
elr/.style 2 args={edge label={node[midway,outer sep=1.5mm,#1]{$#2$}}},
el/.style={elr={left}{#1}},
er/.style={elr={right}{#1}},
for tree={l sep=4em,s sep=8em,calign=fixed edge angles}
[$P_1$,draw,circle
[,el={x=0},ey]
[$P_2$,draw,circle,er=x,anchor=north,before drawing tree={TeX/.wrap pgfmath arg={\gdef\rs{#1}}{y("!u")-y()}},tikz={\draw(!u)--($(!u)!1!-35:(.north)$)arc(235:305:\rs pt)--(!u);}
[${c-x,x}$,el=Y]
[${0,0}$,er=N]]
[,er={x=c},ey]]
\end{forest}
\end{document}
Antwort2
Ich weiß, dass Sie dabei bleiben möchten, forest
aber während Sie auf eine Antwort warten, können Sie versuchen, Ihr Schema auf eine einfache Art und Weise zu zeichnen. Das ist nicht so schwierig:
Lass uns P1
irgendwo zeichnen
\node[circle,draw] (P1) {$P_1$};
Zeichnen wir P2
in einer bestimmten bekannten Entfernung untenP1
\node[circle, draw, on grid, below = 2cm of P1, anchor=north] (P2) {$P_2$};
mit on grid
und anchor=north
wir erzwingen eine 2cm
Distanz zwischen dem Mittelpunkt von P1 und dem Norden von P2. Diese Distanz benötigen wir für einen perfekten Bogen.
Jetzt können wir die Grenze ziehen zwischen P1
undP2
\draw (P1)-- node[right]{$x$} (P2);
Entscheiden Sie als Nächstes, welche Winkel Sie für das linke und rechte Kind wünschen. Die Armlänge beginnt 2cm
in P1
der Mitte. Am Ende des rechten Kindes zeichnen wir den Bogen, da wir Anfangswinkel, Endwinkel und Radius kennen.
\draw (P1) -- node[right] {$x=c$} ++ (-60:2cm) arc (-60:-120:2cm);
\draw (P1) -- node[left] {$x=0$} ++ (240:2cm);
Und wir beenden die Übung mit P2
Kindern, die ähnliche Befehle verwenden:
\draw (P2) -- node[right] {$N$} ++ (-60:2cm) node[below] {$0,0$};
\draw (P2) -- node[left] {$Y$} ++ (240:2cm) node[below] {$c-x,x$};
Das ist alles. Das Ergebnis:
und vollständiger Code:
\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}
\draw (-2,-2) grid (2,2);
\node[circle,draw] (P1) {$P_1$};
\node[circle, draw, on grid, below = 2cm of P1, anchor=north] (P2) {$P_2$};
\draw (P1)-- node[right]{$x$} (P2);
\draw (P1) -- node[right] {$x=c$} ++ (-60:2cm) arc (-60:-120:2cm);
\draw (P1) -- node[left] {$x=0$} ++ (240:2cm);
\draw (P2) -- node[right] {$N$} ++ (-60:2cm) node[below] {$0,0$};
\draw (P2) -- node[left] {$Y$} ++ (240:2cm) node[below] {$c-x,x$};
\end{tikzpicture}
\end{document}
Antwort3
- Der „weiße Raum“ ist nichts anderes als leere Knoten. Auch wenn Sie keinen Text hinzugefügt haben, werden die Knoten erstellt und erzeugen somit den weißen Raum. Um dieses Problem zu lösen, fügen Sie einfach
coordinate
den Optionen für diese Knoten Folgendes hinzu:name=1, coordinate,...
- Gelöst durch den nächsten Punkt.
calign=fixed edge angles
Erweitern Sie Ihrefor tree={}
Optionen für die Winkel .- Ich kann keine Möglichkeit finden, dies zu tun, nicht einmal im Handbuch. Ich glaube, ich übersehe etwas Offensichtliches.
Hier jedenfalls das aktuelle Ergebnis:
Antwort4
Bearbeiten: istgame
Version 2.0
Mit demistgame
Version 2.0 haben Sie mehr Kontrolle über das bogenförmige Verzweigungskontinuum:
\documentclass{standalone}
\usepackage{istgame}
\begin{document}
\begin{istgame}[->,font=\footnotesize]
\cntmdistance{15mm}{30mm}
\cntmAistb[->]{x=0}[al]{x=1}[ar]
\cntmApreset[ultra thin]<1.5>
\istrootcntmA(0)[null node]{1}
\istbA{x}[r]
\endist
\xtdistance{10mm}{20mm}
\istroot(1)(0-1)[null node]<45>{2}
\istb{Y}[l]{c-x,x}
\istb{N}[r]{0,0}
\endist
\end{istgame}
\end{document}
Ursprüngliche Antwort
ultimatum
Dies ist eine weitere Lösung, um die gewünschte Form des Spiels zu erhalten , indem Sie dieistgame
Paket. (Eine weitere Möglichkeit zum Zeichnen des Ultimatumspiels finden Sie im Paketdokument.) Da die istgame
Umgebung fast identisch mit der ist tikzpicture
, können Sie Tikz macros
innerhalb der istgame
Umgebung verwenden.
\documentclass{standalone}
\usepackage{istgame}
\begin{document}
\begin{istgame}[->,font=\footnotesize]
\istroot(0)[null node]{1}+15mm..15mm+
\istb{x=0}[l]
\istb<level distance=1.42*15mm>{x}[r]
\istb{x=c}[r]
\endist
\xtdistance{10mm}{20mm}
\istroot(1)(0-2)[null node]<45>{2}
\istb{Y}[l]{c-x,x}
\istb{N}[r]{0,0}
\endist
\draw[-,ultra thin,tension=1] plot [smooth] coordinates {(0-1)(0-2)(0-3)};
\end{istgame}
\end{document}