Легкое объединение путей Tikz

Nov 29 2020

Я пытаюсь использовать Тикз для рисования узлов для лазания .

Я адаптировал код из этого ответа https://tex.stackexchange.com/a/283009/229885рисовать трехмерную веревку с использованием путей Tikz (основная идея состоит в том, чтобы наложить множество путей разной ширины и цвета, чтобы получить трехмерный вид). Он отлично работает, но есть проблема, которая меня беспокоит, и я не знаю, как ее решить.

На картинке ниже вы видите два узла. Розовый был нарисован с использованием одного пути, а белый - с использованием двух путей. Мне нужно разорвать пути, чтобы правильно изобразить веревочные переходы, но когда я это сделаю, я могу увидеть «шов», где встречаются оба пути.

Вот код, который я использовал для создания этого изображения:

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

%%% The "Rope" command %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                           %
% \Rope[further options]{color}{width}{path definition}                     %
%                                                                           %
\newcommand{\Rope}[4][]                                                     %
{   \pgfmathsetmacro{\RopeLevels}{25}                                       %
    \foreach \RopeLevel in {1,...,\RopeLevels}                              %
    {   \pgfmathsetmacro{\RopeShade}                                        %
            {100 * (\RopeLevel-0.5) / \RopeLevels}                          %
        \pgfmathsetlengthmacro{\RopeWidth}                                  %
            {sqrt(pow(#3, 2) - pow(#3 * (\RopeLevel-1) / \RopeLevels, 2))}  % 
        \draw[#2!\RopeShade!black, line width=\RopeWidth, #1] #4;           %
    }                                                                       %
}                                                                           %
%                                                                           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}
  \begin{tikzpicture}
    \Rope[rounded corners]{pink} {2mm}{ (0.0, 0.0) to (1.0, 1.0) to (0.0, 1.0) to (1.0, 0.0) }
    \Rope[rounded corners]{white}{2mm}{ (1.5, 0.0) to (2.5, 1.0) to (2.0, 1.0) }
    \Rope[rounded corners]{white}{2mm}{ (2.0, 1.0) to (1.5, 1.0) to (2.5, 0.0) }
  \end{tikzpicture}
\end{document}

Я попытался определить новые стили стрелок, которые расширяют пути за пределы заданных координат, но шов все еще виден, несмотря ни на что.

Мои вопросы:

  • Этот шов настоящий или это артефакт, созданный моей программой чтения PDF-файлов? (Я использую Atril 1.24.0 на Xubuntu 20.04.1)
  • Есть ли способ легко присоединиться к путям Tikz?
  • В общем, есть ли лучший способ рисовать альпинистские узлы в LaTeX?

Заранее спасибо,

Ответы

6 AndrewStacey Nov 29 2020 at 20:05

Вот версия, которая перерисовывает часть пути возле перекрестка, чтобы создать вид проезда. Фактически это то, что knotsделает пакет. Если вы хотите рисовать более сложные пути, возможно, стоит изучить эту библиотеку, но в этом случае, поскольку мы знаем, где находится пересечение, она нам не нужна.

\documentclass{article}
%\url{https://tex.stackexchange.com/q/572839/86}
\usepackage{tikz}

%%% The "Rope" command %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                           %
% \Rope[further options]{color}{width}{path definition}                     %
%                                                                           %
\newcommand{\Rope}[4][]                                                     %
{   \pgfmathsetmacro{\RopeLevels}{25}                                       %
    \foreach \RopeLevel in {1,...,\RopeLevels}                              %
    {   \pgfmathsetmacro{\RopeShade}                                        %
            {100 * (\RopeLevel-0.5) / \RopeLevels}                          %
        \pgfmathsetlengthmacro{\RopeWidth}                                  %
            {sqrt(pow(#3, 2) - pow(#3 * (\RopeLevel-1) / \RopeLevels, 2))}  % 
        \draw[#2!\RopeShade!black, line width=\RopeWidth, #1] #4;           %
    }                                                                       %
}                                                                           %
%                                                                           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}
  \begin{tikzpicture}
\Rope[rounded corners]{pink} {2mm}{ (0.0, 0.0) to (1.0, 1.0) to (0.0, 1.0) to (1.0, 0.0) }

\begin{scope}[xshift=1.5cm]
\Rope[rounded corners]{white} {2mm}{ (0.0, 0.0) to (1.0, 1.0) to (0.0, 1.0) to (1.0, 0.0) }
\clip (0.5,0.5) circle[radius=3mm];
\Rope[rounded corners]{white} {2mm}{ (0.0, 0.0) to (1.0, 1.0) }
\end{scope}
  \end{tikzpicture}
\end{document}

Это дает следующее изображение.

Теперь у этого есть артефакты на границе клипа. Это видно только в средстве просмотра и не будет отображаться при распечатке. Это происходит потому, что обтравочный контур не резкий, и поэтому, когда линия проводится многократно, как в вашем стиле веревки, части нижних уровней просвечиваются на границе.

Один из способов избежать этого - убедиться, что нижние слои обрезаны кругом немного меньшего размера, чем слои поверх них (адаптируя идею к проблеме с «кругами на полях» в библиотеке узлов tikz ). Поскольку ваши контуры нарисованы внутри цикла, нам нужно предоставить крючок, чтобы добавить обтравочный контур внутри, когда это необходимо. Для этого я добавил в вашу команду область видимости с дополнительным стилем. Пропуская туда подходящий зажим, можно удалить артефакты.

\documentclass{article}
%\url{https://tex.stackexchange.com/q/572839/86}
\usepackage{tikz}

%%% The "Rope" command %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                           %
% \Rope[further options]{color}{width}{path definition}                     %
%                                                                           %
\newcommand{\Rope}[4][]                                                     %
{   \pgfmathsetmacro{\RopeLevels}{25}                                       %
    \foreach \RopeLevel in {1,...,\RopeLevels}                              %
    {   \pgfmathsetmacro{\RopeShade}                                        %
      {100 * (\RopeLevel-0.5) / \RopeLevels}                          %
        \pgfmathsetlengthmacro{\RopeWidth}                                  %
      {sqrt(pow(#3, 2) - pow(#3 * (\RopeLevel-1) / \RopeLevels, 2))}  %
      \begin{scope}[rope scope/.try]
      \draw[#2!\RopeShade!black, line width=\RopeWidth, #1] #4;           %
      \end{scope}
    }                                                                       %
}                                                                           %
%                                                                           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}
  \begin{tikzpicture}
\Rope[rounded corners]{pink} {2mm}{ (0.0, 0.0) to (1.0, 1.0) to (0.0, 1.0) to (1.0, 0.0) }

\begin{scope}[xshift=1.5cm]
\Rope[rounded corners]{white} {2mm}{ (0.0, 0.0) to (1.0, 1.0) to (0.0, 1.0) to (1.0, 0.0) }
\tikzset{
  rope scope/.code={
    \clip (0.5,0.5) circle[radius={3mm + \RopeLevel/25 pt}];
  }
}
\Rope[rounded corners]{white} {2mm}{ (0.0, 0.0) to (1.0, 1.0) }
\end{scope}
  \end{tikzpicture}
\end{document}

Это производит:

8 Noname Nov 29 2020 at 16:11

Вы можете сократить путь на отрицательную длину и, таким образом, удлинить его, чтобы создать небольшое перекрытие. Этот трюк излечивает многих зрителей, но, возможно, не всех. По крайней мере, не на всех уровнях увеличения.

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

%%% The "Rope" command %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                           %
% \Rope[further options]{color}{width}{path definition}                     %
%                                                                           %
\newcommand{\Rope}[4][]                                                     %
{   \pgfmathsetmacro{\RopeLevels}{25}                                       %
    \foreach \RopeLevel in {1,...,\RopeLevels}                              %
    {   \pgfmathsetmacro{\RopeShade}                                        %
            {100 * (\RopeLevel-0.5) / \RopeLevels}                          %
        \pgfmathsetlengthmacro{\RopeWidth}                                  %
            {sqrt(pow(#3, 2) - pow(#3 * (\RopeLevel-1) / \RopeLevels, 2))}  % 
        \draw[#2!\RopeShade!black, line width=\RopeWidth, #1] #4;           %
    }                                                                       %
}                                                                           %
%                                                                           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}
  \begin{tikzpicture}
    \Rope[rounded corners]{pink} {2mm}{ (0.0, 0.0) to (1.0, 1.0) to (0.0, 1.0) to (1.0, 0.0) }
    \Rope[rounded corners]{white}{2mm}{ (1.5, 0.0) to (2.5, 1.0) to (2.0, 1.0) }
    \Rope[rounded corners,shorten <=-0.2pt]{white}{2mm}{ (2.0, 1.0) to (1.5, 1.0) to (2.5, 0.0) }
  \end{tikzpicture}
\end{document}

Это максимальное увеличение при предварительном просмотре на Mac. Acrobat Reader также подходит для большинства увеличений, но не для всех.

В принципе, можно получить "идеальный" результат, вырезав часть старого контура. Вот невероятно настроенная версия с использованием dash pattern.

\documentclass[tikz, border=2mm]{standalone}
%%% The "Rope" command %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                           %
% \Rope[further options]{color}{width}{path definition}                     %
%                                                                           %
\newcommand{\Rope}[4][]{%                                                   %
   \pgfmathsetmacro{\RopeLevels}{25}                                        %
    \foreach \RopeLevel in {1,...,\RopeLevels}                              %
    {   \pgfmathtruncatemacro{\RopeShade}                                   %
            {100 * (\RopeLevel-0.5) / \RopeLevels}                          %
        \pgfmathsetlengthmacro{\RopeWidth}                                  %
            {sqrt(pow(#3, 2) - pow(#3 * (\RopeLevel-1) / \RopeLevels, 2))}  % 
        \draw[#2!\RopeShade!black, line width=\RopeWidth, #1] #4;           %
    }                                                                       %
}                                                                           %
%                                                                           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}
  \begin{tikzpicture}
    \Rope[rounded corners]{pink} {2mm}{ (0.0, 0.0) to (1.0, 1.0) to (0.0, 1.0) to (1.0, 0.0) }
    \Rope[rounded corners]{white}{2mm}{ (1.5, 0.0) to (2.5, 1.0) to (1.5, 1.0) to (2.5, 0.0) }
    \Rope[rounded corners,dash pattern=on 79.02pt off 80pt]{white}{2mm}{ (1.5, 0.0) to (2.5, 1.0) to (1.5, 1.0) to (2.5, 0.0) }
  \end{tikzpicture}
\end{document}

У этого, похоже, нет никаких сбоев для произвольных увеличений или зрителей (я только тестировал Previewи Acrobat Reader). Можно ли вычислить 79.02pt? Да, по крайней мере, в этом случае. Однако более чистый способ - использовать этот пост .