EDITAR

EDITAR

Hoje, preciso novamente da sua ajuda para lidar com o pacote forest(é um pacote muito poderoso, mas também bastante complexo). Basicamente, já passei várias horas tentando desenhar um jogo de ultimato em forma de árvore que deveria ficar assim:

insira a descrição da imagem aqui

Até agora, consegui criar este código que de alguma forma funciona (mas não funciona bem):

\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 saída que obtenho é esta:

insira a descrição da imagem aqui

Idealmente, as coisas que gostaria de modificar são várias. Primeiro, gostaria que (a) a linha curva tocasse os galhos da árvore, evitando aquele espaço branco feio. Segundo, (b) gostaria de evitar a sobreposição entre a linha curva e o nó P2. Terceiro, (c) gostaria de ter certeza de que os ângulos dos dois ramos nos dois nós são os mesmos. Em outras palavras, o ângulo do segundo nó é maior que o do primeiro nó e gostaria que fossem iguais. Quarto, (d) gostaria que os ramos do segundo nó fossem mais curtos que os do primeiro, se possível. Todas as questões são igualmente relevantes. Qualquer ajuda com qualquer uma das quatro questões será muito apreciada.

PS: Idealmente, eu gostaria de manter meu código atual o máximo possível (em outras palavras, gostaria de aplicar as alterações mínimas necessárias ao código para obter as alterações necessárias, porque este é um código que posso entender mais ou menos facilmente).

Responder1

Aqui está uma solução que acho que atende a todos os desejos declarados. Presumi, a partir da imagem de destino, que você não queria que o arco ficasse aquém do ponto mais alto do nó P_2. Se isso não for necessário, você não precisa se preocupar com alguns dos cálculos envolvidos no meu código.

\documentclass[tikz, border=10pt, multi]{standalone}

Carregamos bibliotecas throughe calcTikZ para obter o arco desenhado corretamente.

\usetikzlibrary{through,calc}
\usepackage{forest}

Agora configuramos alguns estilos. Algumas delas simplificam seu código existente. Se preferir não utilizá-los, você pode omiti-los.

\forestset{%

auto edge labelautomatiza o código para formatar o arquivo edge label. Ele cria o nó, coloca o conteúdo no modo matemático e decide se coloca o rótulo à esquerda ou à direita da borda. Isso significa que

edge label=x^2, auto edge label

fará a coisa certa.

  auto edge label/.style={%
    before typesetting nodes={%

Não faça nada se for o nó raiz.

      if level=0{}{

Se o nó estiver na segunda metade dos filhos dos pais, ou se for o filho do meio ...

        if={n()>(n_children("!u")/2)}{

Se o nó for o filho do meio...

          if={n()==((n_children("!u")+1)/2)}{
            edge label/.wrap value={
              node[midway, right] {$##1$}
            },
          }{

Se o nó estiver na segunda metade dos filhos dos pais ...

            edge label/.wrap value={
              node[midway, outer sep=1.5mm, right] {$##1$}
            },
          },
        }{

Se o nó estiver na primeira metade dos filhos dos pais ...

          edge label/.wrap value={
            node[midway, outer sep=1.5mm, left] {$##1$}
          },
        }
      },
    },
  },

Este é o estilo para nós vazios mais agradáveis. É da página 65 do manual atual. Faz parte da linguisticsbiblioteca. Portanto, se você usar essa biblioteca, poderá omitir essa definição e apenas aplicar o estilo pronto para uso.

Observe que acho que a explicação nesta parte do manual se refere erroneamente a opções inexistentes, mas não tenho certeza sobre isso.

  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}
        }
      }{}
    }
  },

Aqui está o estilo para desenhar os arcos. Você passa isso como uma opção para o pai dos nós através dos quais o arco deve ser desenhado.

Nenhuma aresta é desenhada como parte da própria árvore, exceto para o segundo filho. Se houver mais de três filhos, isso precisará ser um pouco mais sofisticado. Este código assume 3 filhos.

Em vez disso, o arco é desenhado posteriormente calculando os pontos apropriados com base na posição do nó do meio e no ângulo padrão para os nós ao usar calign=fixed edge angles. As bordas do primeiro e do terceiro filho são desenhadas neste momento.

[Isso realmente deveria ser um pouco mais sofisticado em termos de verificação de várias possibilidades, mas deve funcionar em casos relevantes como o 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},
    }
  }
}

Estilo TikZ simples para maior conveniência.

\tikzset{%
  my circle/.style={draw, circle}
}

Então podemos simplesmente aplicar tudo isso à árvore da seguinte maneira.

\begin{document}
\begin{forest}
  for tree={

Do MWE.

    l sep=4em,
    s sep=8em,

Aplique dois dos novos estilos à árvore inteira.

    auto edge label,
    nice empty nodes,

Coloque todos os nós no modo matemático para salvar cifrões.

    math content,
  }

Especifique o arc belowestilo da raiz.

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

árvore com estilos

Código completo:

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

EDITAR

Se você quiser aumentar ainda mais a separação entre os dois primeiros níveis da árvore, a maneira mais fácil é simplesmente aumentar o valor de l seppara o nó raiz. Aqui está um exemplo deliberadamente exagerado:

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

maior separação de nível

Aqui, a distância mínima entre a raiz e seus filhos é definida como seis vezes a distância mínima usual entre os níveis com l sep*=6. Se preferir adicionar um valor absoluto, você poderia dizer l sep+=<dimension>. Ou se você quiser apenas substituir o padrão, l sep=<dimension>especifique a distância mínima com precisão.

É importante que o que l sepgaranta seja amínimodistância. Portanto, se l sepfor definido muito pequeno para um nível e um pouco maior para outro, você poderá acabar com a mesma distância em cada caso, porque outros fatores significarão queflorestaprecisa que os nós sejam espaçados em distâncias maiores do que qualquer um dos mínimos especificados.

Observo que sua árvore de destino real não é, de fato, como a que você mostrou na pergunta. Na verdade, a parte mais complicada do meu código acima não é necessária para a sua árvore final.

Aqui está uma versão automatizada dessa árvore para referência. Esta versão dispensa as bibliotecas TikZ, pois elas são necessárias apenas para arquivos arc below. arc throughé um novo estilo que se conecta às âncoras oeste e leste, em vez de passar pela âncora norte. my arcdetermina o estilo do arco. Isso pode ser definido na árvore usando my arcs={<key list>}para determinar o estilo. Por padrão, está vazio e o arco é desenhado com o estilo da edgeopção atual. Especificar o estilo my arcspermite complementar ou substituir o edgeestilo. Por exemplo, o arco pode ser densely dasheduniforme se as arestas forem desenhadas de forma sólida.

\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={},
}

arco tracejado através

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

EDITAR AO LADO

Esta versão é apenas paraClemente. Embora tenha mais de 546 caracteres, ainda tem apenas 644. E o Kile faz o código somente do TikZ com 563 caracteres, então provavelmente minhas estatísticas estão contando caracteres de forma diferente.

Pessoalmente, não acho que isso seja uma vantagem, mas aí está.

Não é muito transparente, então não recomendo usar isso.

No entanto, a forma como o arco é desenhado é muito mais organizada do que no meu código anterior. O que eu provavelmente faria seria basear-me arc belownesse método, em vez de usar a throughbiblioteca.

A principal economia de caracteres é obtida com a eliminação da automação. Os rótulos das bordas não são mais colocados automaticamente de acordo com a posição do filho em relação aos seus irmãos. Portanto, se você adicionar um nó, deverá verificar se algum lefts deve se tornar rights ou vice-versa. Além disso, nenhum estilo é utilizado para os círculos, reduzindo a flexibilidade e a facilidade de manutenção do código. Finalmente, os cifrões são usados ​​para o conteúdo dos nós, e não math contentporque math content,contêm mais caracteres do que o número necessário para atribuir um par de cifrões a cada nó que precisa deles.

Ironicamente, o desenho do arco agora usaflorestaapresenta mais recursos e TikZ apresenta menos recursos. ( y()é usado com um wrapper pgfmath para obter as informações necessárias para o arco, em vez de depender da throughbiblioteca.)

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

versão curta e azeda

Responder2

Eu sei que você quer continuar, forestmas enquanto espera por uma resposta, você pode tentar entender a maneira de um homem pobre traçar seu esquema. Não é tão difícil:

Vamos desenhar P1em algum lugar

\node[circle,draw] (P1) {$P_1$};

Vamos desenhar P2a uma certa distância conhecida abaixoP1

\node[circle, draw, on grid, below = 2cm of P1, anchor=north] (P2) {$P_2$};

com on gride anchor=northforçamos uma 2cmdistância entre o centro de P1 e o norte de P2. Precisaremos disso para um arco perfeito.

Agora podemos traçar a linha entre P1eP2

\draw (P1)-- node[right]{$x$} (P2);

Em seguida, decida quais ângulos você deseja para os filhos esquerdo e direito. O comprimento do braço começará 2cmdo P1centro. No final do filho direito, desenhamos o arco porque sabemos o ângulo inicial, o ângulo final e o raio.

\draw (P1) -- node[right] {$x=c$} ++ (-60:2cm) arc (-60:-120:2cm);
\draw (P1) -- node[left] {$x=0$} ++ (240:2cm);

E terminamos com P2as crianças usando comandos semelhantes:

\draw (P2) -- node[right] {$N$} ++ (-60:2cm) node[below] {$0,0$};
\draw (P2) -- node[left] {$Y$} ++ (240:2cm) node[below] {$c-x,x$};

Isso é tudo. O resultado:

insira a descrição da imagem aqui

e código completo:

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

Responder3

  1. O “espaço em branco” nada mais é do que nós vazios. Mesmo que você não tenha adicionado texto, os nós são criados, criando, por sua vez, o espaço em branco. Para resolver isso, basta adicionar coordinateopções para esses nós, comoname=1, coordinate,...
  2. Resolvido no próximo ponto.
  3. Para os ângulos, adicione calign=fixed edge anglesàs suas for tree={}opções.
  4. Não consigo encontrar uma maneira de fazer isso, nem mesmo no manual. Acho que estou perdendo algo óbvio.

De qualquer forma, aqui está o resultado atual:

insira a descrição da imagem aqui

Responder4

Editar: istgameversão 2.0

Com oistgameversão 2.0, você pode ter mais controles no tipo de arco contínuo de ramificações:

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

insira a descrição da imagem aqui

Resposta original

Esta é mais uma solução para obter a forma de ultimatumjogo desejada, utilizando oistgamepacote. (Você pode encontrar outra maneira de desenhar o jogo do ultimato no documento do pacote.) Como o istgameambiente é quase o mesmo que o tikzpicture, você pode usar o tikz macrosdentro do istgameambiente.

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

informação relacionada