如何提高通用曲线。\pgfdeclaredecoration 的问题

如何提高通用曲线。\pgfdeclaredecoration 的问题

我想要实现的目标是通过 TikZ 命令定义一条与通用曲线平行的曲线\draw。为了实现它,我使用了 TikZ 装饰库和命令 \pgfdeclaredecoration 来创建它。我采用的解决方案效率不高,但从概念上讲是可行的。这是我的清单的一个最小示例:

\documentclass{standalone}

\usepackage{tikz}

\usetikzlibrary{calc,decorations}
\makeatletter
\newlength\@l
\newcount\@c
\tikzset{
raise line/.initial   = 25pt,
raise points/.initial = 100
}
\pgfdeclaredecoration{Parallel Line}{initial}{
\state{initial}[persistent precomputation={%
                   \pgfmathsetlength{\@l}%
                   {\pgfdecoratedpathlength/(\pgfkeysvalueof{/tikz/raise points})}%
                   \@c=1%
                 },
                 next state = middle,
                 width      =\@l]{\coordinate (DecoratedPointRaised-\the\@c) at 
                                       ($(0,0)+(0,\pgfkeysvalueof{/tikz/raise line})$);}

\state{middle}[persistent precomputation = {\@c=\numexpr\the\@c+1\relax},
               width = \@l]{\coordinate (DecoratedPointRaised-\the\@c) at
                                 ($(0,0)+(0,\pgfkeysvalueof{/tikz/raise line})$);}

\state{final}[persistent precomputation  = {\@c=\numexpr\the\@c+1\relax},
              persistent postcomputation = {\foreach[count=\t from 1]\n in{2,...,100}{ %
                                            \draw (DecoratedPointRaised-\t)--          % Here it does not work!!
                                            (DecoratedPointRaised-\n);}}]{             %
\pgfcoordinate{DecoratedPointRaised-\the\@c}{\pgfpointdecoratedpathlast}
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw (0,0) .. controls++(1,1) and (6,-3).. (7,0);

\draw[decorate,decoration=Parallel Line] (0,0)  .. controls++(1,1) and (6,-3).. (7,0);

%\foreach[count=\t from 1]\n in{2,...,100}{                       %                  
%     \draw (DecoratedPointRaised-\t)--(DecoratedPointRaised-\n); % Here it works!!!!
%}                                                                % 
\end{tikzpicture}
\end{document}

这是我画的:

在此处输入图片描述

下面这一行是原有的,上面这一行是装饰的。

创建平行曲线的步骤如下:

  1. 我创建了一个新的长度\@l,它是步长decoration。我创建了一个新的计数器,\@c以便拥有我将要创建的坐标的顺序名称。
  2. 第一个状态是initial计算间距\@l并在开始时\@c将其设置为 1。然后DecoratedPointRaised-\the\@c创建系列的第一个坐标。完成初始状态后,装饰将传递到中间状态。
  3. 在中间状态预计算中,将新的计算\@c\@c=\@c+1\@c创建坐标后。
  4. 必要时,装饰将进入最终状态,\@c计算最后一个坐标。在这里,我使用后计算来绘制连接所有创建的坐标的所有线段。

问题是最终状态下的后计算不起作用,而如果我在命令之后在其中写入代码\draw,则不会出现问题。为什么?我该如何避免?

在最终状态下,我在命令中使用的坐标系是\state全局坐标系而不是变换后的坐标系吗?

答案1

这似乎也适用于行首的一个小工件double,但使用的是 TikZ v2.10 的标准版本。

\usetikzlibrary{decorations.markings}

\tikzset{forcedist/.style={decorate, decoration={markings,
mark=between positions 0 and 1 step 0.0999 with {\draw[<-] (0,-#1) -- (0,#1); }}}}%Here

\begin{tikzpicture}
\draw [double distance = 1cm,thick]  (0,0) .. controls++(1,1) and (6,-3).. (7,0);
\draw [forcedist=5mm]  (0,0) .. controls++(1,1) and (6,-3).. (7,0);

\draw [double distance = 5mm,thick]  (0,3) --++(8,0);
\draw [forcedist=2.5mm]  (0,3)--++(8,0);
\end{tikzpicture}

导致

在此处输入图片描述

您可以相当轻松地调整箭头的间距和梁的高度。请注意切线计算的奇怪不匹配。直线不会受到此影响。

我没有尝试将这两个命令结合起来,首先我不知道这是否是你想要的,其次你可以使用自己的代码来绘制移动的线并将其添加到其顶部。

编辑:我使用的方法如下:我将装饰物覆盖到double line。我提供了位于 的坐标中间或者中心这条装饰线的坐标,而不是边的坐标。但可能你正在使用坐标作为其中一条边并复制它,因为其中一条黑线从红色曲线的中心穿过。我会尝试将其融入代码中。

编辑2为了能够使用给定的路径作为边缘,我认为你可以使用\pgfsetinnerlinewidth{}第 73.2.7 节中给出的命令内线在 TikZ v2.10 手册中。我还没有尝试过,但似乎是最简单的方法。

编辑3(作者:Andrew Stacey)以下是获取指定线上箭头的略显临时的方法。我们绘制双线,但将其自身裁剪,以便只绘制一半(参见有没有办法在路径的“内部”或“外部”绘制 TikZ 线?有关此技术的更多信息)。这是设计中最粗糙的部分:由于路径没有闭合,我们需要闭合它们以制作剪辑。然后我们绘制线本身。最后,我们使用 percusse 的装饰来装饰它,只是我们调整坐标以使箭头的底部位于线上。

\documentclass{standalone}
%\url{https://tex.stackexchange.com/q/31707/86}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}

\tikzset{forcedist/.style={decorate, decoration={markings,
mark=between positions 0 and 1 step 0.0999 with {\draw[->] (0,0) -- (0,-#1); }}}}%Here
\begin{document}
\begin{tikzpicture}
\begin{scope}
\clip[overlay] (0,0) .. controls++(1,1) and (6,-3).. (7,0) -- ++(3,0) -- ++(0,-5) -- ++(-13,0) -- ++(0,5) -- cycle;
\draw [double distance=2cm,thick]  (0,0) .. controls++(1,1) and (6,-3).. (7,0);
\end{scope}
\draw [thick]  (0,0) .. controls++(1,1) and (6,-3).. (7,0);
\draw [forcedist=1cm]  (0,0) .. controls++(1,1) and (6,-3).. (7,0);

\begin{scope}
\clip[overlay] (0,3) -- ++(8,0)  -- ++(3,0) -- ++(0,-5) -- ++(-13,0) -- ++(0,5) -- cycle;
\draw [double distance=2cm,thick]  (0,3) --++(8,0);
\end{scope}

\draw [thick]  (0,3) --++(8,0);
\draw [forcedist=1cm]  (0,3)--++(8,0);
\end{tikzpicture}
\end{document}

结果:

带箭头的平行线

(初始箭头看起来那样是因为该点处的线的曲率。)

答案2

我可以提供一个解决方案,它只能使用 LuaLaTeX 和最新版本的 PGF 2.10-CVS 进行编译,因为它将 luamath 功能引入 pgf。以下是清单

% !TEX encoding   = UTF-8
% !TEX program    = LuaLaTeX
% !TEX spellcheck = en_GB
\documentclass{standalone}

%\usepackage[margin=2.5cm,left=3cm]{geometry}

\usepackage{tikz}

\usepgflibrary{luamath}
\pgfkeys{/pgf/luamath=true}%<-Put it fase to see what happen

\usetikzlibrary{decorations}
\makeatletter
\newlength\pgf@distributed@force@pitch
\newcount\pgf@distributed@force@new@point
\newcount\pgf@distributed@force@old@point
\newcount\pgf@distributed@force@pitch@points

\tikzset{
distributed force intensity/.initial       = 20pt,
distributed force angle/.initial           = 90,
distributed force intervals/.initial       = 8,
distributed force points/.initial          = 200,%<-I used this value because it does not give problems at path end.
                                                 % change it to see what I mean
}
\pgfdeclaredecoration{Distributed Force}{initial}{
\state{initial}[persistent precomputation={%
                   \pgfmathsetmacro{\pgf@distributed@force@draw@arrow@index}%
                   {\pgfkeysvalueof{/tikz/distributed force points}/\pgfkeysvalueof{/tikz/distributed force intervals}}
                   \pgfmathsetlength{\pgf@distributed@force@pitch}%
                   {\pgfdecoratedpathlength/(\pgfkeysvalueof{/tikz/distributed force points})}%
                 },
                 next state = middle,
                 width      =\pgf@distributed@force@pitch]
                                 {\global\pgf@distributed@force@new@point=0%
                                  \global\pgf@distributed@force@pitch@points=0%
                                  \draw[<-] (0,0)--
                                            (0,\pgfkeysvalueof{/tikz/distributed force intensity})
                                             coordinate (DecoratedPointRaised-\the\pgf@distributed@force@new@point);}

\state{middle}[width=\pgf@distributed@force@pitch]
                {\global\pgf@distributed@force@old@point=\pgf@distributed@force@new@point
                 \global\pgf@distributed@force@new@point=\numexpr\the\pgf@distributed@force@new@point+1\relax
                 \global\pgf@distributed@force@pitch@points=\numexpr\the\pgf@distributed@force@pitch@points+1\relax
                 \draw (0,\pgfkeysvalueof{/tikz/distributed force intensity})
                       coordinate(DecoratedPointRaised-\the\pgf@distributed@force@new@point)--
                       (DecoratedPointRaised-\the\pgf@distributed@force@old@point);
                       \ifnum\pgf@distributed@force@pitch@points=\pgf@distributed@force@draw@arrow@index
                      \draw[<-] (0,0)--(0,\pgfkeysvalueof{/tikz/distributed force intensity});
                      \global\pgf@distributed@force@pitch@points=0
                      \fi
                  }

\state{final}{\global\pgf@distributed@force@old@point=\pgf@distributed@force@new@point
                \global\pgf@distributed@force@new@point=\numexpr\the\pgf@distributed@force@new@point+1\relax
                \pgftransformshift{\pgfpointdecoratedpathlast}
                \draw[<-] (0,0)--++(0,\pgfkeysvalueof{/tikz/distributed force intensity})
                 coordinate(DecoratedPointRaised-\the\pgf@distributed@force@new@point);
                \draw (DecoratedPointRaised-\the\pgf@distributed@force@new@point)--
                      (DecoratedPointRaised-\the\pgf@distributed@force@old@point);
}
}
\makeatother
\tikzset{distributed force/.style = {postaction=decorate,decoration=Distributed Force}}
\begin{document}
\centering
\begin{tikzpicture}

\draw[distributed force,yshift=-3cm,distributed force intensity=10pt]
                     (0,1)  .. controls (1,2) and (6,-2).. (7,0);
\draw[distributed force] (0,0)--++(8,0);
\end{tikzpicture}
\end{document}

这就是我得到的 在此处输入图片描述

相关内容