在 tikz 中生成随机箭头

在 tikz 中生成随机箭头

我想画这个图形:
在此处输入图片描述
因此,我求助于 TikZ。但是,在 TikZ 中精确绘制具有精确位置 (x,y) 的箭头似乎非常困难。我做到了:这
在此处输入图片描述
平均能量损失

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\filldraw[color=gray] (1,0) rectangle (10,5);
\draw[->, line width=2pt, color=red] (2,1) -- (3,1);
\draw[->, line width=2pt, color=red] (2,2) -- (3,2.5);
\draw[->, line width=2pt, color=red] (3,2) -- (30:3);
\end{tikzpicture}
\end{document} 

现在我的问题是

如何在 TikZ 中生成随机长度(2 厘米到 3 厘米之间)和随机倾斜度(如果可能的话,也可以是随机颜色,如红色、黄色、紫色等)的箭头,而无需交叉。是否有任何函数可以生成随机数

笔记:

如果不使用 Tikz,pstricks 或 MetaPost 也可以。目前,Asmptote 无法工作,因为我的系统中似乎存在执行错误。

答案1

更新版本(无交叉):

具有随机颜色、宽度、方向、长度的可能性;图像是使用

\RandArrow

\def\Columns{10}
\RandArrow[80]

在此处输入图片描述

代码:

\documentclass{article} 
\usepackage{tikz}
\usetikzlibrary{calc}

\pgfdeclarelayer{background}
\pgfsetlayers{background,main}

\def\maxArrow{30}
\def\Columns{6}

\newcommand\randomarrow{
  \pgfmathsetseed{\pdfuniformdeviate 10000000}
  \edef\R{\pdfuniformdeviate 255}
  \edef\G{\pdfuniformdeviate 255}
  \edef\B{\pdfuniformdeviate 255}
  \xdefinecolor{mycolor}{RGB}{\R,\G,\B}
  \tikz\draw[->,line width=2pt*rnd+1pt,color=mycolor] 
    (rnd,rnd) -- ++(rnd*360:rnd+0.2);
}
\newcommand\RandArrow[1][30]{%
  \def\maxArrow{#1}  
  \begin{tikzpicture}
  \foreach [count=\i] \val in {1,...,\maxArrow} 
  { 
    \path  
      let \n{row}={int(mod(\i -1, \Columns))}, 
            \n{col}={ int( ( \i - 1 ) / (-\Columns) ) } 
      in 
         (\n{row}, \n{col}) rectangle  +(1,1) 
         +(0.5, 0.5) node{\randomarrow};
  }
  \begin{pgfonlayer}{background}
  \draw[orange!70!black,line width=1pt,fill=yellow!15]
    (current bounding box.north west)
      rectangle
    (current bounding box.south east);
  \end{pgfonlayer}
  \end{tikzpicture}%
}

\begin{document}

\RandArrow

\def\Columns{10}
\RandArrow[80]

\end{document}

避免箭头交叉的想法是有一个网格,并将每个箭头放在网格的一个方格中。

  1. \maxArrows允许指定箭头的数量(初始设置为30)。

  2. \Columns控制网格的行数(初始设置为6)。

  3. \randomarrow绘制一个箭头;宽度、长度、颜色和方向都是使用随机选择的rnd;长度只会(在最坏的情况下)0.2cm大于正方形的宽度;这是为了防止箭头的长度为零。

  4. 主命令带有\RandArrow一个可选参数,允许决定要绘制的箭头数量;默认值为30

  5. 根据建议保罗·加博利his answer\pgfmathsetseed{\pdfuniformdeviate 10000000}用于定义\randomarrow在每次编译时改变伪随机生成器所使用的种子。

在网格中引入一些随机性可以得到更好的结果:

\documentclass{article} 
\usepackage{tikz}
\usetikzlibrary{calc}

\pgfdeclarelayer{background}
\pgfsetlayers{background,main}

\def\maxArrow{30}
\def\Columns{6}

\newcommand\randomarrow{
  \pgfmathsetseed{\pdfuniformdeviate 10000000}
  \edef\R{\pdfuniformdeviate 255}
  \edef\G{\pdfuniformdeviate 255}
  \edef\B{\pdfuniformdeviate 255}
  \xdefinecolor{mycolor}{RGB}{\R,\G,\B}
  \tikz\draw[->,line width=2pt*rnd+1pt,color=mycolor] 
    (rnd,rnd) -- ++(rnd*360:rnd+0.1);
}
\newcommand\RandArrow[1][30]{%
  \pgfmathsetseed{\pdfuniformdeviate 10000000}
  \def\maxArrow{#1}  
  \begin{tikzpicture}
  \foreach [count=\i] \val in {1,...,\maxArrow} 
  { 
    \path  
      let \n{row}={ int(mod(\i -1, \Columns))}, 
            \n{col}={ int( ( \i - 1 ) / (-\Columns) ) } 
      in 
         (\n{row}, \n{col}) rectangle  +({random(2,3)},rand) 
         node[near start] {\randomarrow};
  }
  \begin{pgfonlayer}{background}
  \draw[orange!70!black,line width=1pt,fill=yellow!15]
    (current bounding box.north west)
      rectangle
    (current bounding box.south east);
  \end{pgfonlayer}
  \end{tikzpicture}%
}

\begin{document}

\RandArrow

\def\Columns{10}
\RandArrow[80]

\end{document}

在此处输入图片描述

答案2

编辑:随机非交叉箭头

这是一个非常简单的解决方案(使用网格放置),具有随机颜色、随机长度和随机方向。

在此处输入图片描述

\documentclass[tikz]{standalone}
\pgfmathsetseed{\pdfuniformdeviate 10000000}
\begin{document}
\begin{tikzpicture}
  \fill[black] (0.5,0.5) rectangle (10.5,10.5);
  \foreach \x in {1,...,10} {
    \foreach \y in {1,...,10} {
      % random HSB color definition
      \pgfmathsetmacro\hue{rnd}
      \definecolor{mycolor}{rgb:hsb}{\hue,1,1}
      % random direction and length
      \pgfmathsetmacro\angle{rnd*360}
      \pgfmathsetmacro\halflen{rnd*.3+0.2}
      % arrow
      \draw[line width=2pt,-stealth,color=mycolor]
        (\x,\y) +(\angle:-\halflen) -- +(\angle:\halflen);
    }
  }
\end{tikzpicture}
\end{document} 

第一版:随机箭头

这是一个可能的解决方案。

rnd函数生成一个介于 0 和 1 之间的伪随机数。因此:

  • (rnd*4+3,rnd*4+3)(3,3)给出和之间的随机坐标(7,7).
  • ++(rnd*360:rnd*2+1)将前一个坐标向任意方向(rnd*360)移动,长度在 1cm 到 3cm 之间。

random使用两个参数 x 和 y 的函数生成 x 和 y 之间的随机整数。因此:

  • \pgfmathtruncatemacro\numcolor{random(0,3)}设置\numcolor为 0 至 3 之间的随机整数。

要在每次编译时更改伪随机数生成器使用的种子,您可以在 pemble 中使用 (with pdflatex) 。\pgfmathsetseed{\pdfuniformdeviate 10000000}

在此处输入图片描述

\documentclass[tikz]{standalone}
\pgfmathsetseed{\pdfuniformdeviate 10000000}
\tikzset{
  my arrow/.style={-latex,line width=2},
  my arrow 0/.style={my arrow,color=red},
  my arrow 1/.style={my arrow,color=violet},
  my arrow 2/.style={my arrow,color=yellow},
  my arrow 3/.style={my arrow,color=black},
}
\begin{document}
\begin{tikzpicture}
  \filldraw[color=gray!50] (0,0) rectangle (10,10);
  \foreach \num in {1,...,20} {
    \pgfmathtruncatemacro\numcolor{random(0,3)}
    \draw[my arrow \numcolor] (rnd*4+3,rnd*4+3) -- ++(rnd*360:rnd*2+1);
  }
\end{tikzpicture}
\end{document} 

答案3

随机且不与网格对齐的箭头,使用以下代码tikz:均匀随机分布圆圈

\documentclass{article}
\usepackage{tikz}

\begin{document}
\def\xlist{4}
\def\ylist{4}

\newcommand{\fillrandomly}[4]{
    \pgfmathsetmacro\diameter{#3*2}
    \draw (0-#3,0-#3) rectangle (#1+#3,#2+#3);
    \foreach \i in {1,...,#4}{
        \pgfmathsetmacro\x{rnd*#1}
        \pgfmathsetmacro\y{rnd*#2}
        \xdef\collision{0}
        \foreach \element [count=\i] in \xlist{
            \pgfmathtruncatemacro\j{\i-1}
            \pgfmathsetmacro\checkdistance{ sqrt( ({\xlist}[\j]-(\x))^2 + ({\ylist}[\j]-(\y))^2 ) }
            \ifdim\checkdistance pt<\diameter pt
                \xdef\collision{1}
                \breakforeach
            \fi
        }
        \ifnum\collision=0
            \xdef\xlist{\xlist,\x}
            \xdef\ylist{\ylist,\y}
            \pgfmathsetmacro\randomvalue{rnd*360}
            \draw [red, line width=4pt, -latex] (\x,\y) +(\randomvalue:-#3) -- +(\randomvalue:#3);
        \fi 

    }
}

\begin{tikzpicture}
\pgfmathsetseed{2}
\fillrandomly{7.5}{5}{0.5}{100}

\end{tikzpicture}
\end{document}

答案4

尝试使用 MetaPost,利用其方便的均匀偏差()random 函数,生成一个介于 0 和参数指定的数字之间的随机数。生成的向量的原点、方向和长度都是随机生成的(介于 2 厘米和 3 厘米之间),由于bb宏将给定的向量放入“边界框”中,并检查交叉口时间如果它们不相交则函数为 RGB 规范中的随机颜色。

u := 1cm; % unit length
nb_vectors := 20; wd = .5; 
boolean intersect; pair random_origin; color random_color; path candidate, random_vector[], bb_candidate, bb[];
%
vardef bb(expr p) =
  save orig, extr; pair orig, extr; orig = point 0 of p; extr = point 1 of p;
  pair v,w; v = wd*unitvector(extr-orig)*u; w = v rotated 90;
  (orig - v + w) -- (extr + v + w) -- (extr + v - w) -- (orig - v - w) -- cycle
enddef;
%
beginfig(1);
  pickup pencircle scaled 2bp;
  i = 1; 
  forever: 
    exitunless (i <=  nb_vectors);
    intersect := false;
    random_length := u*(2+uniformdeviate(1));
    random_angle := uniformdeviate(359);
    random_origin := u*(uniformdeviate(wd*nb_vectors), uniformdeviate(wd*nb_vectors));
    random_color := (uniformdeviate(1), uniformdeviate(1), uniformdeviate(1));
    candidate := random_origin -- (random_origin + random_length*dir(random_angle));
    j := 1;
    forever:
      exitif (j = i) or (intersect = true);
      if bb(random_vector[j]) intersectiontimes bb(candidate) <>  (-1, -1):
        intersect := true;
      fi;
      j := j+1;
    endfor;
    if intersect = false: 
      random_vector[i] = candidate;
      drawarrow candidate withcolor random_color;
      i := i+1;
    fi;
  endfor;
endfig;
end.

以下是可能的结果之一:

在此处输入图片描述

相关内容