I'm a big fan of TikZ and I've used it a lot to make technical diagrams, but I've recently started gaining interest in a more artistic usage, namely drawing maps.
As far as I can see, there's not really a package for drawing the type of map I'd like to have, so I started out with something simple: drawing a symbol for a mountain. Here's what I came up with:
\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}
}
The result looks like this, which I'm fairly happy with:
Here are a few trees:
\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}
}
Similarly, I envision to have symbols cities, etc. and use the random steps
key with various settings to draw coastlines, rivers, and more.
However, one crucial aspect is the ability to fill areas with these objects. For a mountain range, for example, I'd like to just define the outer area and have it randomly filled with mountains of different size.
I've looked around at different questions asking for randomly filling areas with symbols (mainly circles, for example this one: Filling specified area by random dots in TikZ), but I found it very hard to adapt either of these solutions from the simple-shaped areas they are intended to fill to possibly complicated shapes without cutting individual symbols in half. I'd like to have a solution for randomly filling areas such that
- Symbols are either displayed whole or not at all
- The density and size of the symbols can vary
- The symbols never overlap
- The patterns can be easily adapted to skew the randomness in a certain direction, for example displaying larger mountains in the middle of the mountain ridge, or displaying higher density of trees towards the middle of the forest.
I've played around for a few hours but couldn't come up with a solution that was even close to satisfactory, so I'm coming here for some ideas and guidance.
Is there some package that can already do what I'm looking for that I didn't find, and this was just an exercise in drawing with TikZ for me? Or do you think this is a viable route to go? How would one go about randomly filling an area with these symbols?
EDIT:
Since it has been requested, here one of my attempts, based off of this answer: Custom and built in TikZ fill patterns
\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}
My problems here are:
- The mountains are not randomized - every one is the same
- The mountain positions are not randomized - is this even possible with
pattern
? - The mountains are cut off where the drawing area ends.
- There is no way to steer that larger mountains should be displayed in the center as opposed to at the edges of the area.
One other possible solution is shown here (tikz: Distribute evenly and randomly circles), but this is not expressed as a fill pattern, and can thus not easily be restricted to a certain area - and I fear that by using clipping paths to overcome this limitation, I will always end up with the symbols themselves being clipped.
\documentclass
and ends with\end{document}
and a concrete target (mountains or trees or ... )?