我正在尝试使用 tikz 绘制一系列随机箭头,每个箭头都从前一个箭头结束的地方开始。我使用极坐标和remember
。从逻辑角度来看,我觉得以下代码应该有效。但是,前一个箭头的端点不知何故与后面箭头的起点不匹配……
代码:
\begin{figure}[h]
\centering
\begin{tikzpicture}
\draw[-latex] (-3,0) -- (3,0) node[right]{$\ts{Re}(r)$};
\draw[-latex](0,-3) -- (0,3) node[above] {$\ts{Im}(r)$};
\def\r{0}
\def\t{0}
\foreach \z [remember=\r as \rlast (initially 0),remember=\t as \tlast (initially 0)] in {1,2,3,4,5,6}
{
\pgfmathsetmacro{\r}{random(0,360)};
\pgfmathsetmacro{\t}{0.01*random(0,100)};
\draw[->] (\rlast:\tlast) -- ++ (\r:\t);
}
\end{tikzpicture}
\end{figure}
答案1
由于命名坐标是全局存储的:
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw[-latex] (-3,0) -- (3,0) node[right]{$\textrm{Re}(r)$};
\draw[-latex](0,-3) -- (0,3) node[above] {$\textrm{Im}(r)$};
\coordinate (last) at (0,0);
\foreach \z in {1,2,3,4,5,6}
{
\pgfmathsetmacro{\r}{random(0,360)};
\pgfmathsetmacro{\t}{0.01*random(0,100)};
\draw[->] (last) -- ++ (\r:\t) coordinate (last);
}
\end{tikzpicture}
\end{document}
答案2
chains
图书馆和图书馆都graphs
可以帮助您减少手动操作。
这些键将根据前一个坐标(红色)放置下一个坐标,同时将绝对放置坐标(蓝色)。random polar shift
random polar placement
代码(链)
\documentclass[tikz]{standalone}
\usetikzlibrary{arrows.meta, chains}
\tikzset{
random polar shift/.style={ at=(\tikzchainprevious),
shift={({random(0,360)}:{random(0,#1)})}},
random polar placement/.style={at={({random(0,360)}:{random(0,#1)})}}}
\begin{document}
\pgfmathsetseed{20230330}
\begin{tikzpicture}[
start chain=ps going {random polar shift = 100},
start chain=pp going {random polar placement = 300},
every join/.append style={->, shorten >=2\pgflinewidth}]
\draw[-Latex] (-3,0) -- (3,0) node[right]{$\textrm{Re}(r)$};
\draw[-Latex] (0,-3) -- (0,3) node[above]{$\textrm{Im}(r)$};
\path[x=+.1mm, y=+.1mm] foreach \z in {1,...,6} {
coordinate[on chain=ps, join=by red]
coordinate[on chain=pp, join=by blue]};
\end{tikzpicture}
\end{document}
代码(图表)
\documentclass[tikz]{standalone}
\usetikzlibrary{arrows.meta, graphs.standard}
\tikzgraphsset{
random polar shift/.style={group shift={({random(0,360)}:{random(0,#1)})}},
random polar shift/.default=100,
random polar placement/.style={nodes={at={({random(0,360)}:{random(0,#1)})}}},
random polar placement/.default=100}
\begin{document}
\pgfmathsetseed{30032023}
\begin{tikzpicture}
\draw[-Latex] (-3,0) -- (3,0) node[right]{$\textrm{Re}(r)$};
\draw[-Latex] (0,-3) -- (0,3) node[above]{$\textrm{Im}(r)$};
\path[x=+.1mm, y=+.1mm, shorten >=2\pgflinewidth,
graphs/every graph/.append style={path, ->, nodes=coordinate}]
graph[edges=red, random polar shift ] { subgraph I_n [n=6] }
graph[edges=blue, random polar placement=300] { 0[x=0, y=0], subgraph I_n [n=5] };
\end{tikzpicture}
\end{document}
输出(链/图)
答案3
使用++(x,y)
(或+(x,y)
) 可以定义相对于前一个坐标的坐标(这意味着\draw (1,1) -- ++(1,1);
此路径的第二个坐标本质上是({1+1},{1+1})
或(2,2)
)。在您的设置中,这不会产生预期的结果,因为您将 存储\r
为\rlast
和\t
,但\tlast
您绘制到({\r+\rlast},{\t+\tlast})
。因此,路径的第二个坐标永远不会与下一个路径的第一个坐标相同。删除,您就会没事了(我稍微++
放大了值):\t
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw[-latex] (-3,0) -- (3,0) node[right] {$\textrm{Re}(r)$};
\draw[-latex] (0,-3) -- (0,3) node[above] {$\textrm{Im}(r)$};
\foreach \z [
remember=\r as \rlast (initially 0),
remember=\t as \tlast (initially 0)
] in {1,2,3,4,5,6} {
\pgfmathsetmacro{\r}{random(0,360)};
\pgfmathsetmacro{\t}{0.03*random(0,100)};
\draw[->] (\rlast:\tlast) -- (\r:\t);
}
\end{tikzpicture}
\end{document}
你不需要事先定义\t
和\r
,因为 Ti钾Z 将会动态地定义它们。
如果您需要每个路径的第二个坐标相对于第一个坐标,则需要以这样的方式进行计算,即\r
和\t
获取计算出的相对值,以便将这些值存储在和中\rlast
。\tlast
如果您直接在坐标上进行计算(例如使用\draw[->] (\rlast:\tlast) -- ({\r+\rlast}:{\t+\tlast});
),那么您将再次遇到与原始问题相同的问题。所以,我认为这也应该适合您:
\begin{document}
\begin{tikzpicture}
\draw[-latex] (-3,0) -- (3,0) node[right] {$\textrm{Re}(r)$};
\draw[-latex] (0,-3) -- (0,3) node[above] {$\textrm{Im}(r)$};
\foreach \z [
remember=\r as \rlast (initially 0),
remember=\t as \tlast (initially 0)
] in {1,2,3,4,5,6} {
\pgfmathsetmacro{\r}{random(0,360)+\rlast};
\pgfmathsetmacro{\t}{0.01*random(0,100)+\tlast};
\draw[->] (\rlast:\tlast) -- (\r:\t);
}
\end{tikzpicture}
\end{document}
答案4
为了比较,下面是元帖子。
这已被包裹起来,luamplib
因此您需要用 来编译它lualatex
。
\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
% a function to turn a <path> into a <picture> of the path draw with arrows
vardef with_arrows expr p = image(
interim ahangle := 20;
for i=1 upto length p:
drawarrow subpath(i-1, i) of p
cutafter fullcircle scaled 3 shifted point i of p; % shorten the arrow slightly
endfor)
enddef;
beginfig(1);
% axes
path xx, yy;
xx = (left--right) scaled 150;
yy = xx rotated 90;
% paths for the chains of arrows
path chain[];
chain1 = origin for i=1 upto 12: .. uniformdeviate 144 * dir uniformdeviate 360 endfor;
chain2 = origin for i=1 upto 12: -- uniformdeviate 144 * dir uniformdeviate 360 endfor;
% note the different connectors -- for straight, .. for free
% two pictures for comparison
picture P[];
P1 = image(
drawarrow xx;
drawarrow yy;
draw with_arrows chain1 withcolor 1/2 blue;
);
P2 = image(
drawarrow xx;
drawarrow yy;
draw with_arrows chain2 withcolor 1/2 red;
);
% show the pictures side-by-side
draw P1; draw P2 shifted 320 right;
endfig;
\end{mplibcode}
\end{document}
笔记
rθ
为了得到MP 中的点,您可以r * dir theta
用theta
度数来写。要获取半径为 144 pt 的圆中任意位置的随机点,可以这样写
uniformdeviate 144 * dir uniformdeviate 360
uniformdeviate
接受单个无分隔符的数字参数并返回 0 到给定数字之间的一个随机实数。您可以跟踪当前点并在生成它们时绘制指向下一个点的箭头,但我认为在变量中捕获所有点会更简洁
<path>
。然后宏
with_arrows
获取该数据<path>
并返回<picture>
用箭头(细箭头和小间隙)绘制的路径。我认为我更喜欢带有弯曲路径的版本。