Обновлять

Обновлять

Мне нужно равномерно распределить два (или более) узла на заданном расстоянии, см. MWE ниже:

введите описание изображения здесь

\documentclass[tikz]{standalone}
\usetikzlibrary{positioning, calc}
\begin{document}
\begin{tikzpicture}[
    text node/.style={rectangle, draw}
]
    \small

    \begin{scope}
        \node (aa) at (0,0) {};
        \node (ab) at (14,0) {};
        \node (c) [text node, right=of aa] {This is a rather long node with text};
        \node (d) [text node, right=of c] {Short};  
    \end{scope}

    \begin{scope}[shift={(0,-1)}]
        \node (ba) at (0,0) {};
        \node (bb) at (14,0) {};
        \node (c2) [text node] at ($(ba)!0.33!(bb)$) {This is a rather long node with text};
        \node (d2) [text node] at ($(ba)!0.66!(bb)$) {Short};   
    \end{scope}

    \foreach \n in {aa, ab, c, d, ba, bb, c2, d2}
        \draw[red, shift=(\n.center)] plot[mark=x] coordinates{(0,0)};
\end{tikzpicture}
\end{document}

При простом размещении узлов рядом друг с другом они, очевидно, загромождают правую часть расстояния (первый случай). Поэтому я попытался вычислить их размещение вдоль расстояния, но этот подход не срабатывает из-за разных размеров узлов (второй случай). Как мне вычислить положения узлов так, чтобы расстояние между ними и по сторонам было одинаковым?

решение1

Этот ответ выполняется поэтапно. Если вам нужен только окончательный код, прокрутите страницу вниз.


Proof-of-concept, возможно. Обратите внимание, что узлы всегда имеют размеры, даже если они пустые. Так что ваша картинка вводит в заблуждение в том смысле, что вы не показываете границы узлов, между которыми размещены другие узлы. Однако их размеры должны быть учтены, если красные метки подразумеваются как соответствующие точки, поскольку они не находятся на границах узлов.

\documentclass[tikz,multi,border=10pt]{standalone}
\usetikzlibrary{positioning, calc}
\begin{document}
\begin{tikzpicture}[
  text node/.style={rectangle, draw, inner sep=2.5pt},
  spread two/.code n args=6{%
    \pgfmathsetmacro\firstwidth{width("#3")}%
    \pgfmathsetmacro\secondwidth{width("#5")}%
    \path ($(#6.west)-(#1.east)$) ++(-\firstwidth-\secondwidth-10 pt,0) coordinate (a);
    \node (#2) [text node, anchor=west] at ($(#1.east)+1/3*(a)$) {#3};
    \node (#4) [text node, anchor=east] at ($(#6.west)-1/3*(a)$) {#5};
  },
  ]
  \small
  \node (aa) at (0,0) {};
  \node (ab) at (14,0) {};
  \tikzset{spread two={aa}{c}{This is a rather long node with text}{d}{Short}{ab}}
  \foreach \n in {aa, ab, c, d}
  \draw[red, shift=(\n.center)] plot[mark=x] coordinates{(0,0)};
\end{tikzpicture}
\end{document}

доказательство концепции

Вероятно, \letсинтаксис мог бы предложить более удобный подход.


Обновлять

Можно немного автоматизировать это. Например, мы можем получить значение inner xsepвместо того, чтобы жестко его кодировать. (Выше я использовал 2.5pt. Значение по умолчанию .3333em.)

\begin{tikzpicture}[
  text node/.style={rectangle, draw},
  spread two/.code n args=6{%
    \pgfmathsetmacro\firstwidth{width("#3")}% 145.58443 pt for testing below (default inner xsep is .3333em)
    \pgfmathsetmacro\secondwidth{width("#5")}% 22.1179 pt
    \path ($(#6.west)-(#1.east)$) ++(-\firstwidth-\secondwidth-4*\pgfkeysvalueof{/pgf/inner xsep},0) coordinate (a);
    \node (#2) [text node, anchor=west] at ($(#1.east)+1/3*(a)$) {#3};
    \node (#4) [text node, anchor=east] at ($(#6.west)-1/3*(a)$) {#5};
  },
  ]
  \small
  \node (aa) at (0,0) {};
  \node (ab) at (14,0) {};
  \tikzset{spread two={aa}{c}{This is a rather long node with text}{d}{Short}{ab}}
  \foreach \n in {aa, ab, c, d}
  \draw[red, shift=(\n.center)] plot[mark=x] coordinates{(0,0)};
\end{tikzpicture}

Как и прежде, это дает нам

автоматически найти все размеры

[Это немного отличается, так как в этой версии используются настройки по умолчанию, inner xsepпоскольку я не указал иного, но это все.]

Вот проверка того, что все работает так, как мы ожидаем:

\begin{tikzpicture}[
  text node/.style={rectangle, draw},
  spread two/.code n args=6{%
    \pgfmathsetmacro\firstwidth{width("#3")}%
    \pgfmathsetmacro\secondwidth{width("#5")}%
    \path ($(#6.west)-(#1.east)$) ++(-\firstwidth-\secondwidth-4*\pgfkeysvalueof{/pgf/inner xsep},0) coordinate (a);
    \node (#2) [text node, anchor=west] at ($(#1.east)+1/3*(a)$) {#3};
    \node (#4) [text node, anchor=east] at ($(#6.west)-1/3*(a)$) {#5};
  },
  ]
  \small
  \node (aa) at (0,0) {};
  \node (ab) at (14,0) {};
  \tikzset{spread two={aa}{c}{This is a rather long node with text}{d}{Short}{ab}}
  \foreach \n in {aa, ab, c, d}
  \draw[red, shift=(\n.center)] plot[mark=x] coordinates{(0,0)};
  \node [red, inner sep=0pt] at (a) {a};
  \path ($(ab.west)-(aa.east)$) ++(-167.7pt,0) ++(-1.3333em,0) node [blue,inner sep=0pt] {a};
  \node [blue, inner sep=0pt] at ($(aa.east)+1/3*(a)$) {x};
  \node [blue, inner sep=0pt] at ($(ab.west)-1/3*(a)$) {x};
  \node [blue, inner sep=0pt, xshift=145.58443pt] at ($(aa.east)+1/3*(a)+(.6667em,0)$) {x};
  \node [blue, inner sep=0pt, xshift=145.58443pt] at ($(aa.east)+2/3*(a)+(.6667em,0)$) {x};
\end{tikzpicture}

что дает нам

проверка размещения

синие отметки там, где мы и ожидали.

Однако синтаксис оставляет желать лучшего. Поэтому мы могли бы изменить наше определение, чтобы spread twoоно было немного более осмысленным. Например,

\tikzset{%
  text node/.style={rectangle, draw},
  spread two/.code args={#1 and #2 with contents #3 and #4 between #5 and #6}{%
    \pgfmathsetmacro\firstwidth{width("#3")}%
    \pgfmathsetmacro\secondwidth{width("#4")}%
    \path ($(#6.west)-(#5.east)$) ++(-\firstwidth-\secondwidth-4*\pgfkeysvalueof{/pgf/inner xsep},0) coordinate (a);
    \node (#1) [text node, anchor=west] at ($(#5.east)+1/3*(a)$) {#3};
    \node (#2) [text node, anchor=east] at ($(#6.west)-1/3*(a)$) {#4};
  },
}

Теперь мы можем написать

\begin{tikzpicture}\small
  \node (aa) at (0,0) {};
  \node (ab) at (14,0) {};
  \tikzset{spread two=c and d with contents {This is a rather long node with text} and {Short} between aa and ab}
  \foreach \n in {aa, ab, c, d}
  \draw[red, shift=(\n.center)] plot[mark=x] coordinates{(0,0)};
\end{tikzpicture}

производить

больше смысла

Полный код:

\documentclass[tikz,multi,border=10pt]{standalone}
\usetikzlibrary{positioning,calc}
\begin{document}
\begin{tikzpicture}[
  text node/.style={rectangle, draw},
  spread two/.code n args=6{%
    \pgfmathsetmacro\firstwidth{width("#3")}% 145.58443 pt for testing below (default inner xsep is .3333em)
    \pgfmathsetmacro\secondwidth{width("#5")}% 22.1179 pt
    \path ($(#6.west)-(#1.east)$) ++(-\firstwidth-\secondwidth-4*\pgfkeysvalueof{/pgf/inner xsep},0) coordinate (a);
    \node (#2) [text node, anchor=west] at ($(#1.east)+1/3*(a)$) {#3};
    \node (#4) [text node, anchor=east] at ($(#6.west)-1/3*(a)$) {#5};
  },
  ]
  \small
  \node (aa) at (0,0) {};
  \node (ab) at (14,0) {};
  \tikzset{spread two={aa}{c}{This is a rather long node with text}{d}{Short}{ab}}
  \foreach \n in {aa, ab, c, d}
  \draw[red, shift=(\n.center)] plot[mark=x] coordinates{(0,0)};
\end{tikzpicture}
\begin{tikzpicture}[
  text node/.style={rectangle, draw},
  spread two/.code n args=6{%
    \pgfmathsetmacro\firstwidth{width("#3")}%
    \pgfmathsetmacro\secondwidth{width("#5")}%
    \path ($(#6.west)-(#1.east)$) ++(-\firstwidth-\secondwidth-4*\pgfkeysvalueof{/pgf/inner xsep},0) coordinate (a);
    \node (#2) [text node, anchor=west] at ($(#1.east)+1/3*(a)$) {#3};
    \node (#4) [text node, anchor=east] at ($(#6.west)-1/3*(a)$) {#5};
  },
  ]
  \small
  \node (aa) at (0,0) {};
  \node (ab) at (14,0) {};
  \tikzset{spread two={aa}{c}{This is a rather long node with text}{d}{Short}{ab}}
  \foreach \n in {aa, ab, c, d}
  \draw[red, shift=(\n.center)] plot[mark=x] coordinates{(0,0)};
  \node [red, inner sep=0pt] at (a) {a};
  \path ($(ab.west)-(aa.east)$) ++(-167.7pt,0) ++(-1.3333em,0) node [blue,inner sep=0pt] {a};
  \node [blue, inner sep=0pt] at ($(aa.east)+1/3*(a)$) {x};
  \node [blue, inner sep=0pt] at ($(ab.west)-1/3*(a)$) {x};
  \node [blue, inner sep=0pt, xshift=145.58443pt] at ($(aa.east)+1/3*(a)+(.6667em,0)$) {x};
  \node [blue, inner sep=0pt, xshift=145.58443pt] at ($(aa.east)+2/3*(a)+(.6667em,0)$) {x};
\end{tikzpicture}
\tikzset{%
  text node/.style={rectangle, draw},
  spread two/.code args={#1 and #2 with contents #3 and #4 between #5 and #6}{%
    \pgfmathsetmacro\firstwidth{width("#3")}%
    \pgfmathsetmacro\secondwidth{width("#4")}%
    \path ($(#6.west)-(#5.east)$) ++(-\firstwidth-\secondwidth-4*\pgfkeysvalueof{/pgf/inner xsep},0) coordinate (a);
    \node (#1) [text node, anchor=west] at ($(#5.east)+1/3*(a)$) {#3};
    \node (#2) [text node, anchor=east] at ($(#6.west)-1/3*(a)$) {#4};
  },
}
\begin{tikzpicture}\small
  \node (aa) at (0,0) {};
  \node (ab) at (14,0) {};
  \tikzset{spread two=c and d with contents {This is a rather long node with text} and {Short} between aa and ab}
  \foreach \n in {aa, ab, c, d}
  \draw[red, shift=(\n.center)] plot[mark=x] coordinates{(0,0)};
\end{tikzpicture}
\end{document}

Связанный контент