Como usar a distância do nó para compensar o início e/ou fim de uma seta com TikZ?

Como usar a distância do nó para compensar o início e/ou fim de uma seta com TikZ?

Quero desenhar uma seta onde um dos pontos finais não esteja realmente conectado a outro nó e quero que o comprimento da seta leve em consideração a distância do nó ao qual a setaéapegado. Então, eu gostaria de poder escrever algo como

\draw [->] ([left of] the-node) -- (the-node);

Veja o MWE abaixo:

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}[
    node/.style={
      node distance=5mm,
    },
  ]
  \node [node] (n) {n};

  % This is what I would like to write (or something like it)
  %\draw [->] ([left of] n) -- (n);

  % Here are my options so far, none of which I like

  % 1:
  \draw [->] ([yshift=5mm] n.north) -- (n);
  % CON: requires explicit use of the node distance

  % 2:
  \coordinate (coord1) at ([xshift=5mm] n.east);
  \draw [->] (coord1) -- (n);
  % CON: requires explicit use of the node distance AND an extra coordinate

  % 3:
  \coordinate [below=of n] (coord2);
  \draw [->] (coord2) -- (n);
  % CON: requires an extra coordinate, and it doesn't seem to use the node
  % distance of 'n' anyway
\end{tikzpicture}
\end{document}

Aqui está o resultado do MWE:

insira a descrição da imagem aqui

Alguma idéia de como eu poderia conseguir isso?

Responder1

Você pode usar coordenadas relativas no lado esquerdo. (No lado direito você deve usar calc.)

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
  \node (n) {n};
  \draw [->] (n.north)+(0,5mm) -- (n);
  \draw [->] (n.east)+(5mm,0) -- (n);
  \draw [->] (n.south)+(0,-5mm) -- (n);
\end{tikzpicture}
\end{document}

Uma solução ainda mais simples:

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
  \node (n) {n};
  \draw [<-] (n.north) -- +(0,5mm);
  \draw [<-] (n.east) -- +(5mm,0);
  \draw [<-] (n.south) -- +(0,-5mm);
\end{tikzpicture}
\end{document}

Responder2

Aqui está uma solução simples (que mostra como usar node distance):

insira a descrição da imagem aqui

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}
  \node (n) {n};
  \begin{scope}[node distance=2cm]
    \draw[red,->] coordinate[below=of n] (a) (a) -- (n);
  \end{scope}
  \begin{scope}[node distance=1cm]
    \draw[blue,->] coordinate[left=of n] (a) (a) -- (n);
  \end{scope}
  \begin{scope}[node distance=5mm]
    \draw[green,->] coordinate[right=of n] (a) (a) -- (n);
  \end{scope}
\end{tikzpicture}
\end{document}

Responder3

Valores de distância com escopo padrão

A node distanceconfiguração não é um atributo de um nó, mas do escopo circundante. Então você não pode acessar"a distância do nó de n"como você disse, mas apenas"a distância atual do nó". Usando isso, você pode definir um estilo que usa a distância do nó atual como deslocamento, como em:

my above/.style={yshift=\tikz@node@distance},

Agora você pode usar coordenadas do formato ([my above] n.center). Infelizmente, é necessário especificar uma âncora de nó, caso contrário o TikZ tentará calcular um ponto na borda do nó, ignorando a yshiftopção no processo.

Use a distância atual do nó

\begin{tikzpicture}[node distance=5mm]
\node[node distance=20mm] (n) {n}; % node distance does nothing here
\draw[->,red]   ([my above=n] n.center) -- (n);
\draw[->,green] ([my below]n.center) -- (n);
\draw[->,blue]   ([my left]n.center) -- (n);

% Larger node distance for the right line
\begin{scope}[node distance=10mm]
    \draw[->,purple] ([my right]n.center) -- (n);
\end{scope}
\end{tikzpicture}

Valores de distância por nó

Agora, se você deseja armazenar um atributo por nó, você deve definir uma macro global cujo nome contenha o nome do nó (armazenado em \tikz@fig@name), que contém o valor desejado:

my distance/.style={execute at end node={%
        \expandafter\gdef\csname my@node@distance@\tikz@fig@name\endcsname{#1}%
}},

Isto é o que o my distanceestilo faz: ele define uma macro chamada \my@node@distance@NAMEonde NAMEé o nome do nó atualmente declarado. Esta macro contém o valor atribuído em my distance=10mm, que poderá ser acessado posteriormente utilizando o nome mencionado anteriormente, conforme mostrado no my above2estilo:

my above2/.style={yshift/.expanded=\csname my@node@distance@#1\endcsname },

A única desvantagem é que você precisa especificar o nome do nó novamente como argumento, como em ([my above2=n] n.center), porque o nome do nó ainda não foi analisado durante o processamento das opções. Portanto, precisamos do argumento extra para dizer a ele para usar a distância armazenada do nó n, e não de algum outro nó.

Observe que a seta roxa não é afetada pela distância do nó definida em scopee ainda usa o valor de my distance=10mm, que foi especificado ao definir o nó n.

Usando distância por nó

\begin{tikzpicture}[node distance=5mm]
\node[my distance=10mm] (n) {n};
\draw[->,red]   ([my above2=n] n.center) -- (n);
\draw[->,green] ([my below2=n] n.center) -- (n);
\draw[->,blue]   ([my left2=n] n.center) -- (n);

% This method is completely unaffected by setting node distance
\begin{scope}[node distance=20mm]
    \draw[->,purple] ([my right2=n]n.center) -- (n);
\end{scope}
\end{tikzpicture}

O código completo

\documentclass[tikz,margin=5pt]{standalone}
\usepackage{tikz}


\begin{document}

\makeatletter
% Basic solution using the current node distance
\tikzset{
    my above/.style={yshift=\tikz@node@distance},
    my below/.style={yshift=-\tikz@node@distance},
    my right/.style={xshift=\tikz@node@distance},
    my left/.style={xshift=-\tikz@node@distance},
}
\begin{tikzpicture}[node distance=5mm]
\node[node distance=20mm] (n) {n}; % node distance does nothing here
\draw[->,red]   ([my above=n] n.center) -- (n);
\draw[->,green] ([my below]n.center) -- (n);
\draw[->,blue]   ([my left]n.center) -- (n);

% Larger node distance for the right line
\begin{scope}[node distance=10mm]
    \draw[->,purple] ([my right]n.center) -- (n);
\end{scope}
\end{tikzpicture}

\vspace{1cm}

% Advanced solution using per-node storage
\tikzset{
    my above2/.style={yshift/.expanded=\csname my@node@distance@#1\endcsname },
    my below2/.style={yshift/.expanded=-\csname my@node@distance@#1\endcsname},
    my right2/.style={xshift/.expanded=\csname my@node@distance@#1\endcsname },
    my left2/.style= {xshift/.expanded=-\csname my@node@distance@#1\endcsname},
    my distance/.style={
        execute at end node={%
            \expandafter\gdef\csname my@node@distance@\tikz@fig@name\endcsname{#1}%
        }%
    },
}
\makeatother

\begin{tikzpicture}[node distance=5mm]
\node[my distance=10mm] (n) {n};
\draw[->,red]   ([my above2=n] n.center) -- (n);
\draw[->,green] ([my below2=n] n.center) -- (n);
\draw[->,blue]   ([my left2=n] n.center) -- (n);

% This method is completely unaffected by setting node distance
\begin{scope}[node distance=20mm]
    \draw[->,purple] ([my right2=n]n.center) -- (n);
\end{scope}
\end{tikzpicture}
\end{document}

Responder4

Provavelmente existem maneiras melhores de usar \tikz@node@distancesem \makeatlettere, \makeatothermas não as conheço, por isso estou aberto a qualquer sugestão.

\documentclass[border=2mm,tikz]{standalone}

\begin{document}
\begin{tikzpicture}
  \node (n) {n};

  \makeatletter
  \begin{scope}[node distance=2cm]
   \draw [->, red]  (n) --++(90:\tikz@node@distance);
   \begin{scope}[node distance=1cm]
   \draw [->, blue]  (n) --++(0:\tikz@node@distance);
   \draw [->, orange]  (n) --++(180:\tikz@node@distance);
   \end{scope}
   \draw [->, green]  (n) --++(-90:\tikz@node@distance);
  \end{scope}
   \makeatother

\end{tikzpicture}
\end{document}

insira a descrição da imagem aqui

Editar:O próximo código mostra uma das sugestões do percusse:

\documentclass[border=2mm,tikz]{standalone}

\makeatletter
\def\nodedistance{\tikz@node@distance}
\makeatother

\begin{document}
\begin{tikzpicture}
  \node (n) {n};

  \begin{scope}[node distance=2cm]
   \draw [->, red]  (n) --++(90:\nodedistance);
   \begin{scope}[node distance=1cm]
   \draw [->, blue]  (n) --++(0:\nodedistance);
   \draw [->, orange]  (n) --++(180:\nodedistance);
   \end{scope}
   \draw [->, green]  (n) --++(-90:\nodedistance);
  \end{scope}

\end{tikzpicture}
\end{document}

informação relacionada