为了制作一些技术图纸,我打算复制(示意图)鹅卵石状海底。我可以制作 MWE,但这是我能做到的极限。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{%
decorations.pathreplacing,%
decorations.pathmorphing%
}
\newcommand\irregularcircle[1]{% radius, irregularity
let \n1 = {(#1)+rand*(0.1*#1)} in
+(0:\n1)
\foreach \a in {10,20,...,350}{
let \n1 = {(#1)+rand*(0.2*#1)} in
-- +(\a:\n1)
} -- cycle
}
\begin{document}
\thispagestyle{empty}
\begin{tikzpicture}[
media/.style={font={\footnotesize\sffamily}},
wave/.style={
decorate,decoration={snake,post length=1.4mm,amplitude=2mm,
segment length=2mm},thick},
interface/.style={
% The border decoration is a path replacing decorator.
% For the interface style we want to draw the original path.
% The postaction option is therefore used to ensure that the
% border decoration is drawn *after* the original path.
postaction={draw,decorate,decoration={border,angle=-135,
amplitude=0.3cm,segment length=2mm}}
}
]
\begin{scope}
\draw [draw=none, fill=cyan!10, rounded corners=2mm] (-2,0) rectangle
(10,2);
\draw [interface, thick, black] (-2,0)--(10,0);
\draw[draw=none, fill=brown!10, rounded corners=1mm, opacity=0.5]
(-2,0)rectangle (10,-1);
\clip (-2,0) rectangle (10,-2);
\foreach \a in {0,1,...,100}
{
\draw[black!50,ultra thin,rounded corners=.5mm, fill=brown!20]
(8*rand, rand) \irregularcircle{0.21cm};
}
\end{scope}
\end{tikzpicture}
\end{document}
现在,我有以下问题:
- 有没有更好的方法来画石头(我使用 tikz 上的可用函数来绘制带有噪音的圆圈)
- 我怎样才能(平等地)分配水下的石头?理想情况下,在 xmin、xmax 和 ymin、ymax 之间划界
谢谢!Marco
答案1
另外两个选项,首先\pgfdeclarepatternformonly
在 tikzpicture 环境中使用以能够使用基本的 tikz 代码指令,例如\draw
,\pgfpath...
问题是只接受路径,因此无法用阴影填充;因此,第二个选项是在绘图定义中使用基本的 tikz 代码来完成的,以免多次重复代码并创建另一个定义,例如帮助pattern
和clip
语句foreach
。
结果:
梅威瑟:
\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{calc}
\usetikzlibrary{patterns,shapes.geometric,decorations.pathmorphing,decorations.pathreplacing}
\begin{document}
\begin{tikzpicture}[
myshade/.style={
black!50,
draw,
ultra thin,
rounded corners=.5mm,
top color=brown!20,
bottom color=brown!20!gray
},
interface/.style={
% The border decoration is a path replacing decorator.
% For the interface style we want to draw the original path.
% The postaction option is therefore used to ensure that the
% border decoration is drawn *after* the original path.
postaction={draw,decorate,decoration={border,angle=-135,
amplitude=0.3cm,segment length=2mm}}
}
]
\def\stone(#1)[#2][#3]{%Drawing manually some shape
\begin{scope}[shift={(#1)},rotate=#2,scale=#3,transform shape]
\draw[line width=0.25pt,rounded corners=1pt]
(15:3pt) -- (45:4pt) -- (89:5pt)--(135:6pt) -- (150:3pt) -- (182:4pt)--(235:6pt) -- (280:3pt) -- (330:2pt) -- cycle;
\end{scope}
}
%Declare a new pattern ¿form only?
\pgfdeclarepatternformonly{pebless under sea floor}{\pgfqpoint{0pt}{0pt}}{\pgfqpoint{15pt}{15pt}}{\pgfqpoint{15pt}{15pt}}%
{
\stone(8pt,6pt)[-15][1]
\stone(0pt,0pt)[45][0.7]
\stone(15pt,15pt)[45][0.7]
\stone(0pt,15pt)[45][0.7]
\stone(15pt,0pt)[45][0.7]
\stone(0pt,7.5pt)[180][0.7]
\stone(15pt,7.5pt)[180][0.7]
\stone(7.5pt,0pt)[90][0.7]
\stone(7.5pt,15pt)[90][0.7]
\draw[line width=0.25pt,rotate=-45] (5.5pt,10pt) ellipse (1pt and 2pt);
\draw[line width=0.25pt] (12pt,10pt) circle (0.7pt);
}
%Create a second shape to create a brute force pattern...
\def\stone2(#1)[#2][#3]{
\begin{scope}[shift={(#1)},rotate=#2,scale=#3,transform shape]
\draw[myshade]
(15:3pt) -- (45:4pt) -- (89:5pt)--(135:6pt) -- (150:3pt) -- (182:4pt)--(235:6pt) -- (280:3pt) -- (330:2pt) -- cycle;
\end{scope}
}
\def\stonepattern(#1){%Brute force pattern
\begin{scope}[shift={(#1)}]
\clip (0,0) rectangle ++(15pt,15pt);
\stone2(8pt,6pt)[-15][1]
\stone2(0pt,0pt)[45][0.7]
\stone2(15pt,15pt)[45][0.7]
\stone2(0pt,15pt)[45][0.7]
\stone2(15pt,0pt)[45][0.7]
\stone2(0pt,7.5pt)[180][0.7]
\stone2(15pt,7.5pt)[180][0.7]
\stone2(7.5pt,0pt)[90][0.7]
\stone2(7.5pt,15pt)[90][0.7]
\draw[line width=0.25pt,rotate=-45,myshade] (5.5pt,10pt) ellipse (1pt and 2pt);
\draw[line width=0.25pt,myshade] (12pt,10pt) circle (0.7pt);
\end{scope}
}
%Start drawing the thing
\clip[rounded corners=0.2cm] (0,2) rectangle ++(12,-3);
\fill [cyan!10] (0,0) rectangle ++(12,2);
\fill[fill=brown!25, rounded corners=1mm, opacity=0.5]
(0,0) rectangle ++(12,-1);
%Drawing sea floor using pattern
\fill[pattern=pebless under sea floor] (0,0) rectangle ++(6,-1);
%Dragind sea floor using brute force...
\begin{scope}
\clip(6,0) rectangle ++(6,-1);
\foreach \x in {0,...,11}{
\foreach \y in{0,...,2}{
\stonepattern(6cm+\x*15pt,-1cm+\y*15pt)
}
}
\end{scope}
\draw [thick, black,interface] (0,0)--(13,0);
\end{tikzpicture}
\end{document}
答案2
从概念上讲,画石头的问题与这个答案,我在这里将其回收。这可以避免重叠。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{%
decorations.pathreplacing,%
decorations.pathmorphing%
}
\newcommand\irregularcircle[1]{% radius, irregularity
+(0:#1)
\foreach \a in {30,60,...,330}{
let \n1 = {(#1)+rand*(0.2*#1)} in
-- +(\a:\n1)
} -- cycle
}
%from https://tex.stackexchange.com/a/87518/121799
\def\xlist{4}
\def\ylist{4}
\newcommand{\fillrandomly}[7][]{
\pgfmathsetmacro\diameter{#6*2}
\foreach \i in {1,...,#7}{
\pgfmathsetmacro\x{0.5*(#4+#2+(2*rnd-1)*(#4-#2))}
\pgfmathsetmacro\y{0.5*(#5+#3+(2*rnd-1)*(#5-#3))}
\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}
\draw[black!50,ultra thin,rounded corners=.5mm,
top color=brown!20,bottom color=brown!20!gray,
shading angle={(0.5+rand)*20}]
(\x,\y) \irregularcircle{0.21cm};
\fi
}
}
\begin{document}
\thispagestyle{empty}
\begin{tikzpicture}[
media/.style={font={\footnotesize\sffamily}},
wave/.style={
decorate,decoration={snake,post length=1.4mm,amplitude=2mm,
segment length=2mm},thick},
interface/.style={
% The border decoration is a path replacing decorator.
% For the interface style we want to draw the original path.
% The postaction option is therefore used to ensure that the
% border decoration is drawn *after* the original path.
postaction={draw,decorate,decoration={border,angle=-135,
amplitude=0.3cm,segment length=2mm}}
}
]
\begin{scope}
\draw [draw=none, fill=cyan!10, rounded corners=2mm] (-2,0) rectangle
(10,2);
\draw [interface, thick, black] (-2,0)--(10,0);
\draw[draw=none, fill=brown!10, rounded corners=1mm, opacity=0.5]
(-2,0)rectangle (10,-1);
\clip (-2,0) rectangle (10,-2);
\fillrandomly{-2+0.21}{-0.21}{10-0.21}{-1+0.21}{0.21}{37}
\end{scope}
\end{tikzpicture}
\end{document}
至于你的第二个问题:你对石头的外观有什么大致的想法吗?我提出了一个建议,但它可能与你希望得到的非常不同。
如果背景上有石头的话可能会更好看。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{%
decorations.pathreplacing,%
decorations.pathmorphing
}
\newcommand\irregularcircle[1]{% radius, irregularity
+(0:#1)
\foreach \a in {30,60,...,330}{
let \n1 = {(#1)+rand*(0.2*#1)} in
-- +(\a:\n1)
} -- cycle
}
%from https://tex.stackexchange.com/a/87518/121799
\def\xlist{4}
\def\ylist{4}
\newcommand{\fillrandomly}[7][]{
\pgfmathsetmacro\diameter{#6*2}
\foreach \i in {1,...,#7}{
\pgfmathsetmacro\x{0.5*(#4+#2+(2*rnd-1)*(#4-#2))}
\pgfmathsetmacro\y{0.5*(#5+#3+(2*rnd-1)*(#5-#3))}
\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}
\draw[black!50,ultra thin,rounded corners=.5mm,
top color=brown!20,bottom color=brown!20!gray,
shading angle={(0.5+rand)*20}]
(\x,\y) \irregularcircle{0.21cm};
\fi
}
}
\begin{document}
\thispagestyle{empty}
\begin{tikzpicture}[
media/.style={font={\footnotesize\sffamily}},
wave/.style={
decorate,decoration={snake,post length=1.4mm,amplitude=2mm,
segment length=2mm},thick},
interface/.style={
% The border decoration is a path replacing decorator.
% For the interface style we want to draw the original path.
% The postaction option is therefore used to ensure that the
% border decoration is drawn *after* the original path.
postaction={draw,decorate,decoration={border,angle=-135,
amplitude=0.3cm,segment length=2mm}}
}
]
\draw [draw=none, fill=cyan!10, rounded corners=2mm] (-2,0) rectangle
(10,2);
\begin{scope}
\clip (-2,0) rectangle (10,-2);
\draw[draw=none, fill=brown!10, rounded corners=1mm, opacity=0.5]
(-2,0)rectangle (10,-1);
\fillrandomly{-2+0.21}{-0.21}{10-0.21}{-1+0.21}{0.21}{37}
\draw [interface, thick, black] (-2,0)--(10,0);
\end{scope}
\end{tikzpicture}
\end{document}