我想画这个图形:
因此,我求助于 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}
避免箭头交叉的想法是有一个网格,并将每个箭头放在网格的一个方格中。
\maxArrows
允许指定箭头的数量(初始设置为30
)。\Columns
控制网格的行数(初始设置为6
)。\randomarrow
绘制一个箭头;宽度、长度、颜色和方向都是使用随机选择的rnd
;长度只会(在最坏的情况下)0.2cm
大于正方形的宽度;这是为了防止箭头的长度为零。主命令带有
\RandArrow
一个可选参数,允许决定要绘制的箭头数量;默认值为30
。根据建议保罗·加博利在
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.
以下是可能的结果之一: