我是 TikZ 的忠实粉丝,我经常用它制作技术图表,但最近我开始对更具艺术性的用途产生兴趣,即绘制地图。
据我所知,目前还没有一个软件包可以绘制我想要的地图类型,所以我从一些简单的事情开始:绘制一座山的符号。以下是我想到的:
\newcommand\mountain[2][1.] {%
\begin{scope}{scale=#1}
\draw[decorate,decoration={random steps,segment length=3pt,amplitude=1pt,pre length=1pt,post length=1pt}] (#2) ++ (-.5,-0.25) --++ (.5,.5) --++ (.5,-.5);
\end{scope}
}
这里有几棵树:
\newcommand\leaftree[2][1.] {%
\begin{scope}{scale=#1}
\pgfmathparse{0.2+.3*rnd}
\pgfmathsetmacro\stem{\pgfmathresult}
\pgfmathparse{0.2+.3*rnd}
\pgfmathsetmacro\height{\pgfmathresult}
\pgfmathparse{0.2+.3*rnd}
\pgfmathsetmacro\width{\pgfmathresult}
\draw[very thick] (#2) --++ (0,\stem);
\draw[decorate,decoration={random steps,segment length=2pt,amplitude=.3pt,pre length=.1pt,post length=1pt}] ($(#2)+(0,\stem)+(0,\height)$) ellipse ({\width} and {\height});
\end{scope}
}
\newcommand\conifer[2][1.] {%
\begin{scope}{scale=#1}
\pgfmathparse{0.2+.1*rnd}
\pgfmathsetmacro\base{\pgfmathresult}
\pgfmathparse{0.3+.5*rnd}
\pgfmathsetmacro\top{\pgfmathresult}
\pgfmathparse{20+30*rnd}
\pgfmathsetmacro\branchangle{\pgfmathresult}
\pgfmathparse{0.03+.03*rnd}
\pgfmathsetmacro\branchdist{\pgfmathresult}
\foreach\x in {0,\branchdist,...,\top}{
\pgfmathparse{0.1+.5*\x+0.03*rnd};
\draw ($(#2)+(0,\base)+(0,\top)-(0,\x)$) --++(-\branchangle:\pgfmathresult);
\draw ($(#2)+(0,\base)+(0,\top)-(0,\x)$) --++(\branchangle:-\pgfmathresult);
}
\draw[very thick,shorten >=.3pt] (#2) --++(0,\base) --++ (0,\top);
\end{scope}
}
同样,我设想拥有城市等符号,并使用具有random steps
各种设置的键来绘制海岸线、河流等。
然而,一个关键方面是能够用这些物体填充区域。例如,对于山脉,我只想定义外部区域,并让不同大小的山脉随机填充其中。
我查看了不同的问题,要求用符号随机填充区域(主要是圆圈,例如这个:在TikZ中用随机点填充指定区域),但我发现很难将这些解决方案从它们打算填充的简单形状区域调整为可能复杂的形状,而无需将单个符号切成两半。我希望有一个解决方案可以随机填充区域,
- 符号要么全部显示,要么根本不显示
- 符号的密度和大小可以变化
- 符号永不重叠
- 这些图案可以轻松调整以在某个方向上倾斜随机性,例如在山脊中间显示更大的山脉,或在森林中间显示更高密度的树木。
我已经玩了几个小时,但无法想出一个令人满意的解决方案,所以我来这里寻求一些想法和指导。
有没有一些软件包可以完成我所寻找的功能,而我却没有找到,而这对我来说只是使用 TikZ 进行绘图的练习?或者你认为这是一条可行的路线?如何用这些符号随机填充一个区域?
编辑:
由于已经提出要求,这里是我的一次尝试,基于这个答案:自定义和内置 TikZ 填充图案
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{patterns}
\usetikzlibrary{decorations.pathmorphing}
\makeatletter
\newlength{\maxmountainsize}
\newlength{\minmountainsize}
\newlength{\mountainspread}
\tikzset{maxmountainsize/.code={\setlength{\maxmountainsize}{#1}},
minmountainsize/.code={\setlength{\minmountainsize}{#1}},
mountainspread/.code={\setlength{\mountainspread}{#1}}}
\tikzset{maxmountainsize=.2cm,
minmountainsize=.3cm,
mountainspread=1cm}
\pgfdeclarepatternformonly[\mountainspread,\maxmountainsize]
{mountainrange}
{\pgfpointorigin}
{\pgfqpoint{\mountainspread}{\mountainspread}}
{\pgfqpoint{\mountainspread}{\mountainspread}}
{
\pgfmathsetmacro\thismountainsize{rnd*(\maxmountainsize-\minmountainsize)+\minmountainsize}
\draw[decorate,decoration={random steps,segment length=3pt,amplitude=1pt,pre length=1pt,post length=1pt}] (0,0) --++ (\thismountainsize pt,\thismountainsize pt) --++ (\thismountainsize pt,-\thismountainsize pt);
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw[fill=red,pattern=mountainrange] (0,0) to [bend right] (10,0) to[bend right] (0,0);
\end{tikzpicture}%
\end{document}
我的问题是:
- 山峰不是随机的——每座山峰都是一样的
- 山的位置并不是随机的——这可能吗
pattern
? - 绘图区域结束时山脉被切断。
- 无法控制较大的山峰应该显示在中心而不是区域的边界上。
另一个可能的解决方案如下所示(tikz:均匀随机分布圆圈),但这并没有以填充图案的形式表现出来,因此不能轻易地被限制在某个区域内——而且我担心,通过使用剪切路径来克服这个限制,我最终总是会得到符号本身被剪切的结果。
答案1
您可以通过计算从外部到点的线与轮廓的交点数来检查随机点是否在轮廓内。这样,只有当山峰的起点位于轮廓内时,您才能绘制山峰。这样可以避免外部部分被剪掉。
\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{decorations.pathmorphing,intersections,calc}
\newlength{\maxmountainsize}
\newlength{\minmountainsize}
\newlength{\mountainspread}
\tikzset{maxmountainsize/.code={\setlength{\maxmountainsize}{#1}},
minmountainsize/.code={\setlength{\minmountainsize}{#1}},
mountainspread/.code={\setlength{\mountainspread}{#1}}}
\tikzset{maxmountainsize=.4cm,
minmountainsize=.2cm,
mountainspread=1cm}
\begin{document}
\begin{tikzpicture}
\begin{scope}[local bounding box=my shape]
\draw[name path global=boundary] (0,0) to [bend right] (10,0) to[bend right] (0,0);
\end{scope}
\begin{scope}[shift={(my shape.south west)},
x={($(my shape.south east)-(my shape.south west)$)},
y={($(my shape.north west)-(my shape.south west)$)}]
\pgfmathsetseed{12}
\foreach \X in {1,...,20}
{\pgfmathsetmacro{\myX}{rnd}
\pgfmathsetmacro{\myY}{rnd}
\path (\myX,\myY) coordinate (aux);
\path[overlay,name path=test] ([yshift=1cm]my shape.north) --(aux);
\pgfmathsetmacro\thismountainsize{rnd*(\maxmountainsize-\minmountainsize)+\minmountainsize}
\typeout{(\myX,\myY):\thismountainsize}
\path[name intersections={of=boundary and test,total=\t}]
\ifodd\t
[draw,decorate,decoration={random steps,segment length=3pt,amplitude=1pt,
pre length=1pt,post length=1pt}]
(\myX,\myY) --++ (\thismountainsize pt,\thismountainsize pt) --++ (\thismountainsize pt,-\thismountainsize pt);
\fi ;
}
\end{scope}
\end{tikzpicture}%
\end{document}