我创建了自己的绘制随机生成的闭环的方法。这是我的代码:
\documentclass[tikz]{standalone}
\usepackage{pgf}
\pgfmathsetseed{\number\pdfrandomseed}
\begin{document}
\begin{tikzpicture}
% Set random in/out angles for the points
\pgfmathsetmacro{\a}{random(45,135)}
\pgfmathsetmacro{\b}{random(300,190)}
\pgfmathsetmacro{\c}{random(290,380)}
\pgfmathsetmacro{\d}{random(340,430)}
\pgfmathsetmacro{\e}{random(20,110)}
\pgfmathsetmacro{\f}{random(110,200)}
\pgfmathsetmacro{\g}{random(160,250)}
\pgfmathsetmacro{\h}{random(200,290)}
% Set random location for points.
% These points are based on an ellipse with horizontal radius 8 and vertical radius 6
\coordinate (a) at (8+1.5*rand,1.5*rand);
\coordinate (b) at (6+1.5*rand,4+1.5*rand);
\coordinate (c) at (1.5*rand,6+1.5*rand);
\coordinate (d) at (-6+1.5*rand,4+1.5*rand);
\coordinate (e) at (-8+1.5*rand,1.5*rand);
\coordinate (f) at (-6+1.5*rand,-4+1.5*rand);
\coordinate (g) at (1.5*rand,-6+1.5*rand);
\coordinate (h) at (6+1.5*rand,-4+1.5*rand);
% Draw the randomly generated closed shape.
\draw (a) to[out=\a, in=\b] (b);
\draw (b) to[out=\b+180, in=\c] (c);
\draw (c) to[out=\c+180, in=\d] (d);
\draw (d) to[out=\d+180, in=\e] (e);
\draw (e) to[out=\e+180, in=\f] (f);
\draw (f) to[out=\f+180, in=\g] (g);
\draw (g) to[out=\g+180, in=\h] (h);
\draw (h) to[out=\h+180, in=\a+180] (a);
\end{tikzpicture}
\end{document}
我的问题是......我如何将其转换为tikz
命令/宏,例如我可以输入
\draw (1,2) \myrandomshape;
进入一个tikzpicture
环境来生成以点 (1,2) 为中心的其中一个形状?
奖金:能够添加键值和节点也很不错,例如
\draw[thick, fill=red] (1,2) \myrandomshape node{A};
生成一个以点 (1,2) 为中心、线条较粗、颜色为红色、中间印有字母“A”的形状。
双倍奖金:这将是双重能够使用箭头说明符,例如
\draw[->] (1,2) \myrandomshape;
\draw[<-] (-3,0) \myrandomshape;
生成一个以点 (1,2) 为中心、箭头沿边界顺时针方向的形状,以及另一个以点 (-3,0) 为中心、箭头沿边界逆时针方向的形状。
答案1
您可以使用pic
。这里的界面不太好,但我认为它有效。要添加黑色形状,请使用例如\pic at (0,0) {randomblob};
。按照设置,randomblob
有四个键值参数,用作randomblob={<key>=<value>}
。它们是
edgecolor
- 线条的颜色,默认为黑色。fillcolor
- 填充颜色。如果未指定,则不进行填充。label
- 放置在形状中心的节点的文本。arrowtip
- 箭头。如果指定,则沿路径均匀放置 10 个箭头。
其他设置如thick
和fill opacity
可以添加到pic
,而不是randomblob
。
\documentclass[tikz]{standalone}
\usetikzlibrary{decorations.markings,arrows.meta}
\pgfmathsetseed{\number\pdfrandomseed}
\tikzset{randomblob/.pic={
\tikzset{%
/randomblob/.cd,
edgecolor=black,
fillcolor=none,
arrowtip={},
label={},
#1
}
% Set random in/out angles for the points
\pgfmathsetmacro{\a}{random(45,135)}
\pgfmathsetmacro{\b}{random(300,190)}
\pgfmathsetmacro{\c}{random(290,380)}
\pgfmathsetmacro{\d}{random(340,430)}
\pgfmathsetmacro{\e}{random(20,110)}
\pgfmathsetmacro{\f}{random(110,200)}
\pgfmathsetmacro{\g}{random(160,250)}
\pgfmathsetmacro{\h}{random(200,290)}
% Set random location for points.
% These points are based on an ellipse with horizontal radius 8 and vertical radius 6
\coordinate (a) at (8+1.5*rand,1.5*rand);
\coordinate (b) at (6+1.5*rand,4+1.5*rand);
\coordinate (c) at (1.5*rand,6+1.5*rand);
\coordinate (d) at (-6+1.5*rand,4+1.5*rand);
\coordinate (e) at (-8+1.5*rand,1.5*rand);
\coordinate (f) at (-6+1.5*rand,-4+1.5*rand);
\coordinate (g) at (1.5*rand,-6+1.5*rand);
\coordinate (h) at (6+1.5*rand,-4+1.5*rand);
\draw [
decoration={
markings,
mark=between positions 0 and 0.9 step 0.1 with {\arrow{\blobarrow}}
},
postaction={decorate},
fill=\blobfillclr,draw=\blobedgeclr]
(a) to[out=\a, in=\b] (b)
to[out=\b+180, in=\c] (c)
to[out=\c+180, in=\d] (d)
to[out=\d+180, in=\e] (e)
to[out=\e+180, in=\f] (f)
to[out=\f+180, in=\g] (g)
to[out=\g+180, in=\h] (h)
to[out=\h+180, in=\a+180] (a);
\node (0,0) {\bloblabel};
},
/randomblob/.search also={/tikz},
/randomblob/.cd,
label/.store in=\bloblabel,
edgecolor/.store in=\blobedgeclr,
fillcolor/.store in=\blobfillclr,
arrowtip/.store in=\blobarrow
}
\begin{document}
\begin{tikzpicture}[x=0.3cm,y=0.3cm]
\pic at (0,0) {randomblob={label=$a+b$,arrowtip={Stealth}}};
\pic [fill opacity=0.2,very thick] at (5,-2) {randomblob={fillcolor=blue,edgecolor=red}};
\pic[thick,blue] at (-5,-5) {randomblob={label={What?},arrowtip=latex,edgecolor=brown}};
\end{tikzpicture}
\end{document}
(我仔细地看了https://tex.stackexchange.com/a/281102/586在编写该代码时。换句话说,我使用了几乎完全相同的代码,所以感谢 cfr。)
原始答案
目前它还不能满足您的加分要求,我会就此回复您。(可能白天没时间,但也许下午/晚上我能想出办法。)
\documentclass[tikz]{standalone}
\pgfmathsetseed{\number\pdfrandomseed}
\tikzset{randomblob/.pic={
% Set random in/out angles for the points
\pgfmathsetmacro{\a}{random(45,135)}
\pgfmathsetmacro{\b}{random(300,190)}
\pgfmathsetmacro{\c}{random(290,380)}
\pgfmathsetmacro{\d}{random(340,430)}
\pgfmathsetmacro{\e}{random(20,110)}
\pgfmathsetmacro{\f}{random(110,200)}
\pgfmathsetmacro{\g}{random(160,250)}
\pgfmathsetmacro{\h}{random(200,290)}
% Set random location for points.
% These points are based on an ellipse with horizontal radius 8 and vertical radius 6
\coordinate (a) at (8+1.5*rand,1.5*rand);
\coordinate (b) at (6+1.5*rand,4+1.5*rand);
\coordinate (c) at (1.5*rand,6+1.5*rand);
\coordinate (d) at (-6+1.5*rand,4+1.5*rand);
\coordinate (e) at (-8+1.5*rand,1.5*rand);
\coordinate (f) at (-6+1.5*rand,-4+1.5*rand);
\coordinate (g) at (1.5*rand,-6+1.5*rand);
\coordinate (h) at (6+1.5*rand,-4+1.5*rand);
% Draw the randomly generated closed shape.
\draw (a) to[out=\a, in=\b] (b)
to[out=\b+180, in=\c] (c)
to[out=\c+180, in=\d] (d)
to[out=\d+180, in=\e] (e)
to[out=\e+180, in=\f] (f)
to[out=\f+180, in=\g] (g)
to[out=\g+180, in=\h] (h)
to[out=\h+180, in=\a+180] (a);
}}
\begin{document}
\begin{tikzpicture}
\pic at (0,0) {randomblob};
\pic[blue] at (2,2) {randomblob};
\pic[thick,red] at (-2,-2) {randomblob};
\end{tikzpicture}
\end{document}
答案2
正如其他人提到的,这pic
是一种有用的方法。请注意,如果使用单独的路径绘制循环,则无法填充。相反,如果将循环绘制为一条路径,则除非使用装饰,否则不可能在不重新绘制各个段的情况下在循环的各个段上获得箭头:
\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{decorations.pathreplacing,math}
\tikzset{pics/random loop/.style={code={
\tikzmath{%
integer \a; coordinate \p;
\a1 = random(45,135); \a2 = random(300,190);
\a3 = random(290,380); \a4 = random(340,430);
\a5 = random(20,110); \a6 = random(110,200);
\a7 = random(160,250); \a8 = random(200,290);
\p1 = (8+1.5*rand,1.5*rand); \p2 = (6+1.5*rand,4+1.5*rand);
\p3 = (1.5*rand,6+1.5*rand); \p4 = (-6+1.5*rand,4+1.5*rand);
\p5 = (-8+1.5*rand,1.5*rand); \p6 = (-6+1.5*rand,-4+1.5*rand);
\p7 = (1.5*rand,-6+1.5*rand); \p8 = (6+1.5*rand,-4+1.5*rand);
}
\path [pic actions/.try, postaction={decoration={show path construction,
curveto code={\path [pic outline/.try]
(\tikzinputsegmentfirst) .. controls(\tikzinputsegmentsupporta)
and (\tikzinputsegmentsupportb) .. (\tikzinputsegmentlast);
}}, decorate}] (\p1)
\foreach \i [evaluate={\j=int(mod(\i, 8)+1);
\u = \a\i + (\i > 1) * 180; \v = \a\j + (\i == 8) * 180;}] in {1,...,8}{
to [out=\u, in=\v] (\p\j) } -- cycle;
}}}
\begin{document}
\begin{tikzpicture}
\foreach \c [count=\i] in {red, yellow, pink, green, orange, purple, blue}
\pic [fill=\c!50,
pic outline/.style={draw=\c!75!black, line width=0.25cm, ->}]
at (360/7*\i:16) {random loop};
\end{tikzpicture}
\end{document}
答案3
这是一个元帖子替代方案。我喜欢 MP 中的这样一个事实:你可以创建一个宏,该宏返回一个path
可以分配给变量的宏,然后将其传递给其他命令(如draw
、reverse
),fill
并对其应用转换(如shifted
、rotated
等)。
prologues := 3;
outputtemplate := "%j%c.eps";
% Make a random ellipsoid with semiaxes a,b and r amount of randomness
vardef random_ellipse(expr a,b,r) =
save e; path e;
e = fullcircle xscaled a yscaled b;
for i=1 upto length e:
point i of e shifted (r*normaldeviate, r*normaldeviate) ..
endfor cycle
enddef;
% Draw n evenly-space arrows along path p
vardef draw_arrows_along(expr p, n) =
save a; a = arclength p / n;
for i=1 upto n:
drawarrow subpath (arctime (i-1)*a of p, arctime i*a of p) of p;
endfor
enddef;
beginfig(1);
randomseed := 3142;
path e[];
e1 = random_ellipse(144,89,13);
e2 = random_ellipse(144,89,13) shifted (200, 0);
e3 = random_ellipse(144,89,13) shifted (200, 150);
e4 = random_ellipse(144,89,13) shifted ( 0, 150);
draw e1;
drawoptions(withcolor .67 red);
draw_arrows_along(e2,13);
drawoptions(withcolor .4 green);
draw_arrows_along(reverse e3, 32);
drawoptions();
fill e4 withcolor .8[blue,white];
draw e4 withcolor .67 blue;
label("A", center e1);
label("B", center e2);
label("C", center e3);
label("D", center e4);
endfig;
end.