# Using TikZ to draw a water channel profile

I want to draw a relatively simple sketch using TikZ but I can't do it.

What I want is a representation of an open water channel with 4 pools, a dam upstream, and a waste reservoir downstream, as depicted in the picture below:

I would like to label the pools, dam and waste as I did in the drawing. In addition, I also would like to label the interface locations (numbered from 4 to 8, in this example).

Those inclined lines are supposed to represent the ground. The water representation itself, in blue, is not mandatory, I included it in the drawing just for better understanding. I may not include it in the final sketch.

I like to use LaTeX and TikZ and I like to do these things in a flexible way that let me easily adjust sizes or reuse parts of the code in other pictures.

-
Welcome to TeX.SX. Questions about how to draw specific graphics that just post an image of the desired result are really not reasonable questions to ask on the site. Please post a minimal compilable document showing that you've tried to produce the image and then people will be happy to help you with any specific problems you may have. See minimal working example (MWE) for what needs to go into such a document. – Papiro Aug 31 '14 at 12:04
Why don't you just draw it in Inkscape and export it to TikZ? I guess it shouln't take more than half an hour. – Uwe Ziegenhagen Aug 31 '14 at 13:48
You could also consider including your nicely-drawn artwork as it is (although you are right about the convenience of being able to reuse parts of pictures done in TikZ etc). – Thruston Sep 1 '14 at 9:10
@Papiro Thanks for pointing me to that welcoming post. I know I should've been objective about the particular problem I was having, but the thing is I was not even aware of how to start doing that drawing at all, I mean, how to structure it. Anyway, thanks for warning me and I'll try to follow better the guidelines on my next question. – POliveira Sep 7 '14 at 14:52
@UweZiegenhagen I actually tried to do it. The problem is that I've never used Inkscape before and even though I followed some tutorials, I concluded I would take longer to get a satisfactory result than using TikZ. (May be I was wrong) – POliveira Sep 7 '14 at 14:56

A tikz solution where an L shape pool is drawn by a macro called mypool that takes 6 arguments, displayed below.

#1=starting point, #2=vertically down  length, #3=for Label L4-L8,
#4=horizontal length of the pool #5=end point #6=Pool label 1-5.


Update: The OP wants the Labels be somewhere above the water border and center. Well, here just modify the macro to what is shown below.

\newcommand\mypool[6]{
% draw L shape line
\draw[line width=1pt] ([yshift=1cm]#1) -- +(0,#2)coordinate[](a){}node[below=0.5cm](){#3} --node[above=0.2cm, pos=0.5]{#6} +(#4,#2)coordinate[](#5){}; <---- see #6 there
% fill water and patterns
\path[fill=blue!30](a) -- ([yshift=0.3cm]a)-- ([yshift=0.3cm]#5) -- (#5)--cycle;
\path[pattern=north east lines](a) -- ([yshift=-0.3cm]a)-- ([yshift=-0.3cm]#5) -- (#5)--cycle;
\draw[line width=1pt]([yshift=1cm]#1) |-(#5);
}


and yields

Code

\documentclass[border=10pt]{standalone}%[11pt]{article}

\usepackage{tikz}
\usetikzlibrary{positioning,patterns}
\newcommand\mypool[6]{
% draw L shape line
\draw[line width=1pt] ([yshift=1cm]#1)node[right=0.5cm]{#6} -- +(0,#2)coordinate[](a){}  node[below=0.5cm](){#3} -- +(#4,#2)coordinate[](#5){};
% fill water and patterns
\path[fill=blue!30](a) -- ([yshift=0.3cm]a)-- ([yshift=0.3cm]#5) -- (#5)--cycle;
\path[pattern=north east lines](a) -- ([yshift=-0.3cm]a)-- ([yshift=-0.3cm]#5) -- (#5)--cycle;
\draw[line width=1pt]([yshift=1cm]#1) |-(#5);
}
\begin{document}
%#1=starting point, #2=vertically down  length, #3=L4-L8, #4=length of the pool #5=end point #6=pool1-5.
\begin{tikzpicture}
\node[inner sep=0pt, outer sep=0pt] at (0,0) (O){};
\mypool{O}{-1}{}{2}{A}{Dam}
\mypool{A}{-2}{L4}{1}{B}{POOL1}
\mypool{B}{-2}{L5}{2}{C}{POOL2}
\mypool{C}{-2}{L6}{3}{D}{POOL3}
\mypool{D}{-2}{L7}{4}{E}{POOL4}
\mypool{E}{-2}{L8}{3}{F}{Waste}
\end{tikzpicture}
\end{document}

-
Can you explain me where in the code do you set that the first pool (i.e., the dam) does not have that vertical line to the left as all the other pools have? – POliveira Sep 7 '14 at 15:30
@POliveira -- In the first line mypool{0}{-1}{}{2}{A}, the first argument 0 take me to (0,1) for the label Dam due yshift=1, then the second argument -1 take me to the origin again, due to +(0,-1) where (a) is located. The remaining pools all follow the same logic to find their respective positions. Hoping this explanation helps. – Jesse Sep 7 '14 at 15:52
Would it be reasonably feasible to adapt your solution so that the pools' labels (Dam, Pool 1, ..., Waste) would lie more or less centered over the width of the respective pool and also at a constant vertical shift from the water border, just as @HarishKumar did in his solution? – POliveira Sep 7 '14 at 16:12
OK, the label location can be changed too. Currently it is allocated by \node[right=0.5], move the node to the water border as you mentioned is tangible and use [pos=0.5]. Specifically, between #3 and #5. Try node[below=0.5cm](){#3} --node[above=0.2cm, pos=0.5]{#6} +(#4,#2)coordinate[](#5){}; Please insert the node[above=0.2cm, pos=0.5]{#6} correctly. – Jesse Sep 7 '14 at 16:25
Quick note -- you might want to change the second mypool length to 2 which is currently 1 in the code. – Jesse Sep 7 '14 at 16:30

Again with tikz but using pic:

\documentclass[border=3mm]{standalone}

\usepackage{tikz}
\usetikzlibrary{patterns,calc}

\tikzset{%
pics/.cd,
dam/.style args={#1#2#3#4#5}{
code={
\begin{scope}[shift={(#1)}]
\coordinate (a) at (0,0);     %% starting point
\coordinate (b) at +(0,#2);   % height of right side
\coordinate (c) at ([shift={(-#3,0.5)}]$(a)!0.5!(b)$); %top left point of water
\coordinate (d) at ([shift={(-#3,-0.25)}]$(a)!0.5!(b)$); %bottom left point of hatch
\fill [cyan!50] ($(a)!0.5!(b)$) rectangle ([xshift=\pgflinewidth]c)node[black,midway,above=2ex]{#4};
\draw[thick] ($(a)!0.5!(b)$) -- ([yshift=-0.5cm]c);
\fill [pattern = north east lines] ($(a)!0.5!(b)$) rectangle ([xshift=\pgflinewidth]d);
\draw[thick] (a) -- (b);
\path (a) -- +(0,-0.5)node[pos=1.2] {#5};
\end{scope}
}
},
}

\begin{document}
\begin{tikzpicture}
%dam={starting point}{height of right side}{width}{pool label Pool1..}{location label L1...}
\pic {dam={0,0}{2}{3}{Dam}{L4}};
\pic {dam={2,-1}{2}{2}{Pool1}{L5}};
\pic {dam={5,-2.5}{3}{3}{Pool2}{L6}};
\pic {dam={9,-4.5}{4}{4}{Pool3}{L7}};
\pic {dam={10,-5.2}{1.4}{1}{Pool4}{L8}};
\pic {dam={13,-5.2}{0}{3}{Waste}{}};
\end{tikzpicture}

\end{document}


-
Can you explain me what are the advantages (and disadvantages) of using pic instead of macros? – POliveira Sep 7 '14 at 15:35
Comparing your solution with the one from @Jesse, when I change the pool's width (using your implementation) I must redefine also the starting points in order to keep it all aligned, which is a disadvantage. On the other side, I like that the pool label is centered within the pool. – POliveira Sep 7 '14 at 15:43
There is a tiny annoying detail that can be seen in this picture. If you look at the left-down corner of the pool, you'll notice 2 things: the perpendicular lines don't close the path (resulting in a lack of black pixels in the corner) and the ground lines don't go until the left end of the pool. Could you adapt your solution to fix those tiny issues? – POliveira Sep 7 '14 at 16:21
@POliveira I will look in to it after some time (later today). – Harish Kumar Sep 7 '14 at 23:27

A PSTricks solution:

\documentclass{article}

\usepackage[pdf]{pstricks}

\newpsobject{water}{psframe}{
dimen = m,
linestyle = none,
fillstyle = solid,
fillcolor = blue!30
}
\newpsobject{basin}{psframe}{
dimen = m,
linestyle = none,
fillstyle = hlines,
hatchsep = 2pt
}

\def\pool(#1,#2)[#3,#4]#5#6{
\basin(!#1 #2 0.3 sub)(!#1 #4 add #2)
\psline[linestyle = dashed, dash = 3pt 3pt](#1,#2)(!#1 #2 1 sub)
\rput(!#1 #2 1.5 sub){\small $L_{#6}$}
%  \rput(!#1 #2 1.5 sub){\small L#6}
}
% syntax for \pool:
% \pool(<start position of basin; (x,y)>)
%      [<height of left side of basin>,
%       <width of basin>]
%      {<first label>}
%      {<second label>}

\begin{document}

\psset{unit = 0.64} % to avoid overfull \hbox'
\begin{pspicture}(18,8.9)
% dam
\water(0,7.7)(3,8.2)
\basin(0,7.4)(3,7.7)
\psline(0,7.7)(3,7.7)
\rput(1.5,8.7){\small Dam}
% pools
\pool(3,5.7)[3,4]{Pool~1}{4}
\pool(7,4.7)[2,2]{Pool~2}{5}
\pool(9,3.7)[2,3]{Pool~3}{6}
\pool(12,2.7)[2,3.5]{Pool~4}{7}
% waste
\pool(15.5,1.7)[2,2.5]{Waste}{8}
\end{pspicture}

\end{document}


Update

In case you want a uniform vertical distance between the different pools, you can simplify the code a bit:

\documentclass{article}

\usepackage[pdf]{pstricks}

\newpsobject{water}{psframe}{
dimen = m,
linestyle = none,
fillstyle = solid,
fillcolor = blue!30
}
\newpsobject{basin}{psframe}{
dimen = m,
linestyle = none,
fillstyle = hlines,
hatchsep = 2pt
}

\def\pool(#1,#2)[#3]#4#5{
\basin(!#1 #2 0.3 sub)(!#1 #3 add #2)
\psline[linestyle = dashed, dash = 3pt 3pt](#1,#2)(!#1 #2 1 sub)
\rput(!#1 #2 1.5 sub){\small $L_{#5}$}
%  \rput(!#1 #2 1.5 sub){\small L#5}
}
% syntax for \pool:
% \pool(<start position of basin; (x,y)>)
%      [<width of basin>]
%      {<first label>}
%      {<second label>}

\begin{document}

\psset{unit = 0.64} % to avoid overfull \hbox'
\begin{pspicture}(18,7.9)
% dam
\water(0,6.7)(3,7.2)
\basin(0,6.4)(3,6.7)
\psline(0,6.7)(3,6.7)
\rput(1.5,7.7){\small Dam}
% pools
\pool(3,5.7)[4]{Pool~1}{4}
\pool(7,4.7)[2]{Pool~2}{5}
\pool(9,3.7)[3]{Pool~3}{6}
\pool(12,2.7)[3.5]{Pool~4}{7}
% waste
\pool(15.5,1.7)[2.5]{Waste}{8}
\end{pspicture}

\end{document}


-
I never used PSTricks. According to Wikibooks I can't compile the file using pdflatex (well, at least not out of the box), is that right? Therefore I'll opt for one of the TikZ implementations, though I was able to learn some stuff with your solution. – POliveira Sep 7 '14 at 15:09
@POliveira I have updated my answer; you can now compile the document via pdflatex -shell-escape <file-name>. – Svend Tveskæg Sep 7 '14 at 16:10

And here's a slightly different approach using Metapost.

prologues := 3;
outputtemplate := "%j%c.eps";

% routine to make a ragged version of a path
vardef ragged(expr n, r, p) =
save s; s = arclength(p)/n;
point 0 of p
for t=s step s until arclength(p)-s:
-- point arctime t of p of p shifted (r*normaldeviate, r*normaldeviate)
endfor -- point infinity of p
enddef;

beginfig(1);

% define a line of regular steps with varying widths, that finishes on the y-axis
path ground_level;
step_height = 20; x = 0; y = 6*step_height;
ground_level = for dx=70,90,50,70,80,80:
(x,y) -- hide(x:=x+dx)
(x,y) -- hide(y:=y-step_height) endfor (x,0);

% water reaches this far up each step
water_depth = step_height/4;

color earth; earth = (213/255,197/255,165/255);
color water; water = (192/255,212/255,230/255);

% overlay three solid fills to create the desired areas of colour
fill origin -- ground_level shifted (0,water_depth) -- cycle withcolor water;
fill origin -- ground_level                         -- cycle withcolor earth;
fill origin -- ragged(500,1/5,ground_level) shifted (-4,-4) -- cycle withcolor background;

% draw the barriers and the call outs
for i=1 step 2 until 10:
draw ((0,0) -- (0,1.2water_depth)) shifted point i of ground_level;
draw ((0,0) -- (0,-20)) shifted point i+1 of ground_level dashed evenly scaled .4;
endfor

% draw in the ground level with a thicker pen
draw ground_level withpen pencircle scaled 1;

% add the labels in the right places
label.top(btex Dam    etex, point 0.5 of ground_level shifted (0,water_depth));
label.top(btex Pool 1 etex, point 2.5 of ground_level shifted (0,water_depth));
label.top(btex Pool 2 etex, point 4.5 of ground_level shifted (0,water_depth));
label.top(btex Pool 3 etex, point 6.5 of ground_level shifted (0,water_depth));
label.top(btex Pool 4 etex, point 8.5 of ground_level shifted (0,water_depth));
label.top(btex Waste  etex, point 10.4 of ground_level shifted (0,water_depth));

label.bot(btex $L_4$ etex, point  2 of ground_level shifted 20 down);
label.bot(btex $L_5$ etex, point  4 of ground_level shifted 20 down);
label.bot(btex $L_6$ etex, point  6 of ground_level shifted 20 down);
label.bot(btex $L_7$ etex, point  8 of ground_level shifted 20 down);
label.bot(btex $L_8$ etex, point 10 of ground_level shifted 20 down);

% trim the rough edges left and right
setbounds currentpicture to bbox currentpicture shifted (10,0) xscaled 0.95;

endfig;
end.

-