Como posso definir explicitamente a âncora do rótulo TikZ?

Como posso definir explicitamente a âncora do rótulo TikZ?

Quero adicionar labela um nó, mas "dentro" do nó. Algo assim:

saída desejada

O manual parece indicar que isso pode ser possível, embora nenhuma chave real seja nomeada.

O ... ponto de ancoragem para o nó do rótulo ... é determinado de tal forma que o nó do rótulo ficará “de costas” para a borda do nó principal. A âncora escolhida depende da posição do ponto de borda escolhido e de sua posição em relação ao centro do nó principal e se a opção de forma de transformação está definida.Em geral, a escolha deve ser aquela que você espera, mas você mesmo pode ter que estabelecer a âncora em situações difíceis.(enf. adicionado)

Mas quando tento um exemplo como este:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\tikz \node [circle,draw,label={[red,anchor=north]above:X}] {my circle};
\end{document}

Não recebo nenhuma alteração na posição do nó do rótulo. Ainda está “lá fora”.

saída real

Alguma ideia?

Responder1

O problema aqui é que o TikZ aplica alguma automação (ou seja, a \tikz@auto@anchormacro) que irá sobrescrever o seu set anchor.

Podemos sequestrar uma .codechave que é aplicada por último no nó que é usado internamente para o rótulo (sim, mesmo depois de nossas próprias configurações red, anchor=north) e que chama \tikz@auto@anchor:

\tikzset{label anchor/.style={tikz@label@post/.append style={anchor=#1}}}

ou deixamos a macro que faz os cálculos relaxar um pouco (nenhuma chave adicional necessária):

\tikzset{anchor/.append code=\let\tikz@auto@anchor\relax}

Se a chave nova e aprimorada anchorfor agora usada de forma mais global (digamos \tikz[anchor=<dir>]), ela também afetará os nós (e atualmente há uma maneira de recuperá-la).

Também forneço uma chave inside(você pode até usá-la duas vezes para reverter o efeito).

Código

\documentclass[tikz]{standalone}
\usepackage{etoolbox}
\makeatletter
\tikzset{anchor/.append code=\let\tikz@auto@anchor\relax}
\tikzset{inside/.code=\preto\tikz@auto@anchor{\pgf@x-\pgf@x\pgf@y-\pgf@y}}
\makeatother
\begin{document}
\tikz\node [anchor=west, circle,draw,label={[red, anchor=north]above:X}] {my circle};
\tikz\node [anchor=west, circle,draw,label={[red, inside]below:X}] {my circle};
\end{document}

Saída

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Responder2

Aqui está outra abordagem que explora a append after commandopção. A questão é que, ao referir-se à âncora, \tikzlastnode.centerpodemos acrescentar, relativamente a essa posição, rótulos.

O novo estilo capaz de realizar esta tarefa é my label:

\tikzset{my label/.style args={#1:#2}{
  append after command={
    (\tikzlastnode.center) node [#1] {#2}
    }
  }
}

Um mwe:

\documentclass[tikz,png,border=10pt]{standalone}
\usepackage{tikz}
\tikzset{my label/.style args={#1:#2}{
    append after command={
       (\tikzlastnode.center) node [#1] {#2}
    }
  }
}
\begin{document}
\tikz \node [circle,draw,my label={red,above=0.15cm:X}] {my circle};
\tikz \node [circle,draw,my label={red,below=0.15cm:X}] {my circle};
\end{document}

que dá como resultados:

insira a descrição da imagem aqui

insira a descrição da imagem aqui

O estilo aceita no primeiro argumento qualquer opção TikZ, por isso é fácil personalizar cores e posição: na verdade, é melhor ajustar um pouco o deslocamento para não sobrepor o texto.

Se, por outro lado, se sabe que o rótulo sempre deve ser colocado abaixo da “borda norte”, bem, o melhor a fazer é mudar o my labelestilo para:

\tikzset{my label/.style args={#1:#2}{
    append after command={
       (\tikzlastnode.north) node [#1] {#2}
    }
  }
}

Desta forma, basta configurar:

\tikz\node [circle,draw,my label={red,below:X}] {my circle};

permite atingir a meta.

Um mwe:

\documentclass[tikz,png,border=10pt]{standalone}
\usepackage{tikz}
\tikzset{my label/.style args={#1:#2}{
    append after command={
       (\tikzlastnode.north) node [#1] {#2}
    }
  }
}
\begin{document}
\begin{tikzpicture}
\node [circle,draw,my label={red,below:X}] {my circle};
\node [circle,draw,my label={red,below=0.15cm:X},xshift=2cm] {my circle};
\end{tikzpicture}
\end{document}

O resultado:

insira a descrição da imagem aqui

Revisão

O método anterior sofre, como dito nos comentários, se mais de um rótulo for introduzido. Mas isso é perfeitamente possível se, em vez de introduzirmos nós, introduzirmos coordenadas com rótulos.

O código:

\documentclass[tikz,png,border=10pt]{standalone}
\usepackage{tikz}
\tikzset{my label/.style args={[#1]#2:#3}{
    append after command={
       (\tikzlastnode.center) coordinate[label={[label distance=0.1cm,#1]#2:#3}]
    }
  },
}
\begin{document}
\begin{tikzpicture}
\node [circle,
  draw,
  my label={[red]above:X},
  my label={[green!70!blue]below:Y},
  my label={[blue,yshift=0.3cm]above:Z}] {my circle};
\node [circle,
  draw,
  my label={[blue,yshift=-0.15cm]below:X},
  my label={[green!70!blue]70:Z},
  my label={[orange!80!red]130:Y},
  xshift=2cm] {my circle};
\end{tikzpicture}
\end{document}

O resultado:

insira a descrição da imagem aqui

Aviso: ao usar label distancedentro da definição da opção, permite não ter o texto do rótulo sobreposto quando se diz apenas:

\tikz\node [circle,draw,my label={[red]below:X}] {my circle};

Responder3

Você também pode mudar o rótulo:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\tikz \node [circle,draw,label={[red,yshift=-0.5cm]above:X}] {my circle};

\tikz \node [circle,draw,label={[red,label distance=-0.5cm]above:X}] {my circle};
\end{document}

informação relacionada