오늘 패키지를 처리하려면 다시 한 번 여러분의 도움이 필요합니다 forest
(정말 강력한 패키지이지만 다소 복잡하기도 합니다). 기본적으로 나는 이미 다음과 같은 최후통첩 게임을 트리 형태로 그리려고 몇 시간을 소비했습니다.
지금까지 나는 어떻게든 작동하지만 제대로 작동하지 않는 다음 코드를 만들었습니다.
\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}
내가 얻은 결과는 다음과 같습니다.
이상적으로는 수정하고 싶은 것이 여러 개입니다. 먼저, (a) 곡선이 나무 가지에 닿아 보기 흉한 공백을 피하고 싶습니다. 둘째, (b) 곡선과 노드 P2가 겹치는 것을 피하고 싶습니다. 셋째, (c) 두 노드에 있는 두 가지의 각도가 동일한지 확인하고 싶습니다. 즉, 두 번째 노드의 각도가 첫 번째 노드의 각도보다 넓어서 동일하게 하고 싶습니다. 넷째, (d) 가능하다면 두 번째 노드의 가지가 첫 번째 노드의 가지보다 짧으면 좋겠습니다. 모든 질문은 동일하게 관련됩니다. 네 가지 문제에 대한 도움을 주시면 대단히 감사하겠습니다.
PS: 이상적으로는 현재 코드를 최대한 고수하고 싶습니다. 즉, 제가 이해할 수 있는 코드이기 때문에 필요한 변경 사항을 얻기 위해 코드에 필요한 최소한의 변경 사항을 적용하고 싶습니다. 다소 쉽게).
답변1
여기에 명시된 모든 요구 사항을 충족한다고 생각되는 솔루션이 있습니다. 나는 대상 이미지에서 호가 노드의 최상위 지점에 미치지 못하는 것을 원하지 않는다고 가정했습니다 P_2
. 이것이 필요하지 않다면 내 코드에 포함된 계산 중 일부를 귀찮게 할 필요가 없습니다.
\documentclass[tikz, border=10pt, multi]{standalone}
호를 올바르게 그리기 위해 TikZ 라이브러리를 through
로드 합니다 .calc
\usetikzlibrary{through,calc}
\usepackage{forest}
이제 몇 가지 스타일을 설정합니다. 이들 중 일부는 기존 코드를 단순화합니다. 사용하지 않으려면 생략할 수 있습니다.
\forestset{%
auto edge label
의 형식을 지정하기 위한 코드를 자동화합니다 edge label
. 노드를 생성하고 내용을 수학 모드로 설정한 다음 레이블을 가장자리의 왼쪽 또는 오른쪽에 배치할지 결정합니다. 이는 다음을 의미합니다.
edge label=x^2, auto edge label
옳은 일을 할 것입니다.
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$}
},
}
},
},
},
이것은 더 멋진 빈 노드를 위한 스타일입니다. 현재 매뉴얼의 65페이지에 나오는 내용입니다. 도서관 의 일부입니다 linguistics
. 따라서 해당 라이브러리를 사용하는 경우 이 정의를 생략하고 기본적으로 스타일을 적용할 수 있습니다.
매뉴얼의 이 부분에 있는 설명은 존재하지 않는 옵션을 잘못 언급하고 있다고 생각하지만 이에 대해서는 확실하지 않습니다.
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}
}
}{}
}
},
호를 그리는 스타일은 다음과 같습니다. 호를 그려야 하는 노드의 부모에게 이것을 옵션으로 전달합니다.
두 번째 자식을 제외하고는 트리 자체의 일부로 가장자리가 그려지지 않습니다. 자녀가 3명 이상인 경우에는 좀 더 정교해져야 합니다. 이 코드는 3명의 자녀를 가정합니다.
대신 를 사용할 때 중간 노드의 위치와 노드에 대한 기본 각도를 기준으로 적절한 점을 계산하여 나중에 호를 그립니다 calign=fixed edge angles
. 이때 첫 번째 자식과 세 번째 자식의 가장자리가 그려집니다.
[이것은 실제로 다양한 가능성을 확인하는 측면에서 좀 더 정교해야 하지만 MWE와 같은 관련 사례에서는 작동해야 합니다.]
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},
}
}
}
편의를 위해 간단한 TikZ 스타일.
\tikzset{%
my circle/.style={draw, circle}
}
그러면 우리는 이 모든 것을 다음과 같이 트리에 적용할 수 있습니다.
\begin{document}
\begin{forest}
for tree={
MWE에서.
l sep=4em,
s sep=8em,
두 가지 새로운 스타일을 전체 트리에 적용합니다.
auto edge label,
nice empty nodes,
달러 기호를 저장하려면 모든 노드를 수학 모드로 설정하세요.
math content,
}
arc below
루트의 스타일을 지정합니다 .
[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}
전체 코드:
\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}
편집하다
트리의 처음 두 수준 사이의 분리를 더 늘리려면 가장 쉬운 방법은 l sep
루트 노드의 값을 늘리는 것입니다. 다음은 의도적으로 과장된 예입니다.
\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}
여기서 루트와 그 자식 사이의 최소 거리는 레벨 사이의 일반적인 최소 거리의 6배로 설정됩니다 l sep*=6
. 절대 금액을 추가하려면 이라고 말할 수 있습니다 l sep+=<dimension>
. 또는 기본값을 무시하려는 경우 l sep=<dimension>
최소 거리를 정확하게 지정합니다.
l sep
보장하는 것이 중요합니다.최저한의거리. 따라서 l sep
한 수준에서는 매우 작게 설정하고 다른 수준에서는 조금 더 크게 설정하면 다른 요인으로 인해 각 경우에 동일한 거리가 생길 수 있습니다.숲지정된 최소값보다 더 먼 거리에 노드를 배치해야 합니다.
실제 대상 트리는 실제로 질문에 표시된 것과 같지 않습니다. 사실, 위 코드 중 가장 까다로운 부분은 최종 트리에는 전혀 필요하지 않습니다.
다음은 참조용으로 해당 트리의 자동화된 버전입니다. 이 버전에서는 TikZ 라이브러리가 필요하지 않습니다 arc below
. arc through
북쪽 앵커를 거치지 않고 서쪽 앵커와 동쪽 앵커로 연결되는 새로운 스타일입니다. my arc
호의 스타일을 결정합니다. 이는 my arcs={<key list>}
스타일을 결정하는 데 사용되는 트리 내에서 설정할 수 있습니다 . 기본적으로 비어 있으며 현재 edge
옵션의 스타일로 호가 그려집니다. 스타일을 지정하면 스타일 my arcs
을 보완하거나 재정의할 수 있습니다 edge
. 예를 들어, densely dashed
가장자리가 단단하게 그려져 있어도 호가 생길 수 있습니다 .
\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}
따로 편집
이 버전은온화한. 546자가 넘지만 여전히 644자에 불과합니다. 그리고 Kile은 TikZ 전용 코드를 563자로 만들기 때문에 아마도 내 통계에서는 문자를 다르게 계산하는 것 같습니다.
개인적으로 나는 이것이 장점이라고 생각하지 않지만 거기에 있습니다.
매우 투명하지 않으므로 실제로 사용하는 것을 권장하지 않습니다.
그러나 호가 그려지는 방식은 이전 코드보다 훨씬 깔끔해졌습니다. 아마도 내가 할 일은 라이브러리를 arc below
사용하는 것보다 이 방법을 기반으로 하는 것입니다 through
.
문자의 주요 절약은 자동화를 제거함으로써 달성됩니다. 가장자리 레이블은 더 이상 형제를 기준으로 자식의 위치에 따라 자동으로 배치되지 않습니다. 따라서 노드를 추가하는 경우 left
s가 s가 되어야 하는지 right
, 아니면 그 반대인지 확인해야 합니다 . 게다가 원에는 어떤 스타일도 사용되지 않아 코드의 유연성과 유지 관리성이 떨어집니다. 마지막으로, 달러 기호는 달러 기호가 필요한 각 노드에 달러 기호 쌍을 할당하는 데 필요한 수보다 많은 문자를 포함하기 math content
보다는 노드의 내용에 사용됩니다 .math content,
아이러니하게도 호를 그리는 데 실제로는 다음을 사용합니다.숲기능은 더 무겁고 TikZ 기능은 덜 무겁습니다. ( y()
라이브러리에 의존하지 않고 호에 필요한 정보를 얻기 위해 pgfmath 래퍼와 함께 사용됩니다 through
.)
\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}
답변2
나는 당신이 고수하고 싶어한다는 것을 알고 있지만 forest
답변을 기다리는 동안 당신의 계획을 그리는 가난한 사람의 방법을 이해하려고 노력할 수 있습니다. 그렇게 어렵지는 않습니다.
P1
어딘가에 그려보자
\node[circle,draw] (P1) {$P_1$};
P2
아래의 알려진 특정 거리에서 그려 보겠습니다 .P1
\node[circle, draw, on grid, below = 2cm of P1, anchor=north] (P2) {$P_2$};
P1의 중심과 P2의 북쪽 사이에 거리를 강제 로 적용합니다 on grid
. 완벽한 호를 위해서는 그것이 필요합니다.anchor=north
2cm
P1
이제 우리는 과 사이에 선을 그릴 수 있습니다P2
\draw (P1)-- node[right]{$x$} (P2);
다음으로 왼쪽 및 오른쪽 어린이에게 원하는 각도를 결정합니다. 팔 길이는 중앙 2cm
부터 시작 됩니다 P1
. 오른쪽 자식의 끝에서 초기 각도, 최종 각도 및 반경을 알고 있으므로 호를 그립니다.
\draw (P1) -- node[right] {$x=c$} ++ (-60:2cm) arc (-60:-120:2cm);
\draw (P1) -- node[left] {$x=0$} ++ (240:2cm);
P2
그리고 비슷한 명령을 사용하여 아이들을 마무리합니다 .
\draw (P2) -- node[right] {$N$} ++ (-60:2cm) node[below] {$0,0$};
\draw (P2) -- node[left] {$Y$} ++ (240:2cm) node[below] {$c-x,x$};
그게 다야. 결과:
전체 코드는 다음과 같습니다.
\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}
답변3
- "공백"은 빈 노드에 지나지 않습니다. 텍스트를 추가하지 않았더라도 노드가 생성되므로 결과적으로 공백이 생성됩니다. 이 문제를 해결하려면
coordinate
다음과 같이 해당 노드에 대한 옵션을 추가하면 됩니다.name=1, coordinate,...
- 다음 포인트로 해결됩니다.
- 각도는 옵션
calign=fixed edge angles
에 추가하세요for tree={}
. - 설명서에도 방법이 없네요. 나는 분명한 것을 놓치고 있다고 생각합니다.
어쨌든 현재 결과는 다음과 같습니다.
답변4
편집: istgame
버전 2.0
와 더불어istgame
버전 2.0에서는 분기의 호 유형 연속체에 대해 더 많은 제어 기능을 가질 수 있습니다.
\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}
원래 답변
ultimatum
이것은 원하는 게임 의 형태를 얻는 또 다른 솔루션입니다 .istgame
패키지. (패키지 문서에서 최후통첩 게임을 그리는 또 다른 방법을 찾을 수 있습니다.) 환경은 istgame
와 거의 동일하므로 환경 내에서 tikzpicture
tikz를 사용할 수 있습니다 .macros
istgame
\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}