3

My quetion may be dumb, but consider that I am very new with Tikz.

I am trying to draw a tower similar to Eifel using the following code

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{shapes.misc}

\begin{document}

\begin{tikzpicture}[{x=(1mm,0)},{y=(0,1mm)}]
\def\towerwd{5}                 % tower width
\def\towerht{10}                % tower height
\def\towerar{4*\towerwd/10}     % tower arc radius

\def\tower#1{% #1=position
    \draw[thick]
        %... tower arc
        {#1++(-\towerar,0)}
            arc(180:0:\towerar)--
            (\towerwd/2,0) to[out=120,in=270]
            (0,\towerht) to[out=270,in=60]
            (-\towerwd/2,0)--
            cycle
        ;
    }

\tower{(0,0)} % this works!
\tower{(0,20)} % this is messy!
\end{tikzpicture}

\end{document}

It works fine when I do \tower{(0,0)}, but becomes messy when I use any other coordinate. What am I doing wrong here?

  • 1
    Welcome to TeX.SX! Can you please expand the code snippet that you have posted to a full minimal working example. It is much easier to help you if we can start with some compilable code that illustrates your problem. A MWE should start with a \documentclass command, include any necessary packages and be as small as possible to demonstrate your problem. At the moment we have to guess what packages etc you are using before we can compile your code. – Andrew Nov 10 '18 at 23:16
  • Yes, sure! I will edit my question. Thank you, @Andrew – Brasil Nov 10 '18 at 23:18
4

It becomes messy because ++ does not add these coordinates, you might use calc for that if there was not a (IMHO) much more elegant way: pics.

What do pics do? A pic is, as its name suggests, a small picture like your tower. pics can be placed and transformed. All I did was to move your \tower code inside the definition of a pic by saying

 \tikzset{pics/.cd,
    tower/.style={code={
        \draw[thick]
            (-\towerar,0)
                arc(180:0:\towerar)--
                (\towerwd/2,0) to[out=120,in=270]
                (0,\towerht) to[out=270,in=60]
                (-\towerwd/2,0)--
                cycle
            ;
    }}}

Here, the .cd switches to the pics subdirectory of pgfkeys tikz directory. The rest is just to teach TikZ the tower code.

\documentclass{article}
\usepackage{tikz}

\begin{document}
\tikzset{pics/.cd,
tower/.style={code={
    \draw[thick]
        (-\towerar,0)
            arc(180:0:\towerar)--
            (\towerwd/2,0) to[out=120,in=270]
            (0,\towerht) to[out=270,in=60]
            (-\towerwd/2,0)--
            cycle
        ;
}}}

\begin{tikzpicture}[{x=(1mm,0)},{y=(0,1mm)}]
\def\towerwd{5}                 % tower width
\def\towerht{10}                % tower height
\def\towerar{4*\towerwd/10}     % tower arc radius
\path (0,0) pic{tower} (0,20) pic{tower};
\end{tikzpicture}

\end{document}

enter image description here

But this example does not at all explain why people are excited about pics. Rather, you might want to add parameters instead of the somewhat clumsy \def\towerwd{5} and so on statements. And you may want to change parameters from "outside". All this can be done with pics.

\documentclass{article}
\usepackage{tikz}

\begin{document}
\tikzset{pics/.cd,
tower/.style args={#1 wide and #2 high}{code={
    \draw[thick]
        (-4*#1/10,0)
            arc(180:0:4*#1/10)--
            (#1/2,0) to[out=120,in=270]
            (0,#2) to[out=270,in=60]
            (-#1/2,0)--
            cycle
        ;
}}}

\begin{tikzpicture}[{x=(1mm,0)},{y=(0,1mm)}]
\path (0,0) pic{tower=5 wide and 15 high}
node[below]{Paris} (20,2) pic[rotate=-30,blue]{tower=5 wide and 10 high}
node[below]{Pisa};
\end{tikzpicture}

\end{document}

enter image description here

  • Hi, @marmot. Thank you very much for the answer. It works perfectly. Could you please explain the role of \tikzset and its arguments pics/.cd and tower/.style? Thank you again. – Brasil Nov 11 '18 at 15:21
  • 1
    @Brasil I added explanations and a more advanced example. – marmot Nov 11 '18 at 15:33
  • Yeah... sorry. In a hurry, I missed the explanations. Everything is very new for me, so I think I will need to read a bit of external explantions too. Let me a final question: is there any difference if I do \tikzset inside the tikz environment? Thank you again, @marmot. Its great! – Brasil Nov 11 '18 at 15:48
  • 1
    @Brasil The answer is: yes and no. No because \tikzset works, in principle, always the same. Yes because its definitions are not global. In your example you have \def\towerwd{5} inside the tikzpicture, so \towerwd is not known outside because by default definitions are not global. Same thing for pgfkeys: the key value is not known outside the tikzpicture if you set it inside. – marmot Nov 11 '18 at 15:52
  • 1
    @Brasil Yes. If I use in the first example \path (0,0) pic{tower} (0,20) pic[rotate=30]{tower};, the upper tower gets rotated, as expected. – marmot Jan 1 at 18:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.