I'd like to draw a rectilinear path by starting at a particular location, and then prescribing increments in the horizontal and vertical directions.

I am currently doing something like this

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
    \draw [ultra thick] (20,12) -- (18,12);
    \draw [ultra thick] (18,12) -- (18,10);
    \draw [ultra thick] (18,10) -- (16,10);
    \draw [ultra thick] (16,10) -- (16,8);
    \draw [ultra thick] (16,8) -- (12,8);
    \draw [ultra thick] (12,8) -- (12,10);
    \draw [ultra thick] (12,10) -- (8,10);
    \draw [ultra thick] (8,10) -- (8,12);
    \draw [ultra thick] (8,12) -- (6,12);
    \draw [ultra thick] (6,12) -- (6,14);
    \draw [ultra thick] (6,14) -- (4,14);
    % etc ...

\end{tikzpicture}
\end{document}

enter image description here

But this requires that I locate each point, when what is much easier (for my particular case) is to just indicate the horizontal or vertical distance from one point to the next.

I have tried something like this

\documentclass{standalone}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
   \node (A) at (20,12) {};
   \node (B) at (18,12) {};
   \node (C) at (18,10) {};
   \node (D) at (16,10) {};

   \draw (A) |- ++ (-2,0)  -| (B);
   \draw (B) |- ++ (0, -2) -| (C);
   \draw (C) |- ++ (-2, 0) -| (D);
   % etc
\end{tikzpicture}
\end{document}

It looks like the ++ (-2,0) bit seems to be on the right track, but naming the nodes is tedious, and this doesn't produce what I have in mind.

Is there some way to do what I have in mind with simple notation? Something like

Start at (20,12)
Go left 2 units
Go down 2 units
Go left 2 units
% etc

Aka, Etch-a-Sketch style?

up vote 13 down vote accepted

\draw (20,12) -- ++(2,0) -- ++(0,2) -- ++(-3,0) -- ++(45:3);

Use ++ before each new incremental coordinate to make it relative to the last one and put the pencil there.

Here's a complete example:

\documentclass{article}
\usepackage{tikz}
\begin{document}
\tikz\draw (20,12) -- ++(2,0) -- ++(0,2) -- ++(-3,0) -- ++(30:3) {[rounded corners=10pt]-- ++(5,0) -- ++(0,-6)} -- ++(-7,0) -- cycle;
\end{document}

enter image description here

Of course, combining this with the -| or |- path operators can simplify the code even further; the following two pieces of code produce the same result:

\tikz\draw (20,12) -- ++(2,0) -- ++(0,2) -- ++(3,0) -- ++(0,1) -- ++(1,0) -- ++(0,-3) -- ++(2,0);\par\bigskip

and

\tikz\draw (20,12) -| ++(2,2) -| ++(3,1) -- ++(1,0) |- ++(2,-3);

I don't think that defining commands in this case adds anything; in fact, I think it reduces the functionality of the existing syntax (which is already simple). The example demonstrates that you can use, for example, polar coordinates and modify (up to TikZ limitations) the path attributes midways; even if the current question doesn't require this, it's a good thing to have the possibility to do those kind of modification if they are required.

  • Thanks - this is in fact exactly what I wanted. And it doesn't have the problem that segments aren't meeting up exactly at the corners. Perfect! – Donna Sep 26 '15 at 21:57
  • 1
    @Donna You're welcome. Please see my updated answer. – Gonzalo Medina Sep 26 '15 at 23:25
  • Thanks! So it looks like there are a couple of new features here, at least one of which I was wondering about. It looks like you can change the line style midstream, which is very handy, and exactly something I wanted to do. I want to fill the resulting rectilinear polygons, so always need closed polygons, but only want portions of the border to be, say, ultra thick. So I'll try your trick above for getting rounded corners midway. But what does the (30:3) notation do? And cycle? – Donna Sep 27 '15 at 11:14
  • Trying this out, I see that the (30:3) indicates an angle (30 degrees), and cycle means "return to the beginning" (or so it seems). Turns out, though, it is not possible to change the line style midway. Oh well. – Donna Sep 27 '15 at 11:50
  • @Donna Yes, (<angle>:<distance>) has the meaning you guesses, and yes, line width (as well as color and other attributes) cannot be changed midway for a single path due to TikZ limitations. – Gonzalo Medina Sep 27 '15 at 14:56

Not sure it is what is required, but here is a rectilinear decoration which sort of achieves the required effect:

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{decorations}
\pgfdeclaredecoration{rectilinear}{start}{%
\state{start}[width=\pgfdecorationsegmentlength/2,
  next state=draw above]{%
  \pgfpathmoveto{\pgfpointorigin}%
  \pgfcoordinate{@1}{\pgfpointorigin}%
}
\state{draw above}[width=\pgfdecorationsegmentlength/2, 
  next state=draw below]{%
  \pgfcoordinate{@2}{\pgfpointorigin}%
  \pgftransformreset%
  \pgfpointanchor{@1}{center}\pgfgetlastxy\a\b%
  \pgfpointanchor{@2}{center}\pgfgetlastxy\c\d%
  \pgfpathlineto{\pgfqpoint{\a}{\d}}%
  \pgfpathlineto{\pgfqpoint{\c}{\d}}%
  \pgfnodealias{@1}{@2}%
}
\state{draw below}[width=\pgfdecorationsegmentlength/2, 
  next state=draw above]{%
  \pgfcoordinate{@2}{\pgfpointorigin}%
  \pgftransformreset%
  \pgfpointanchor{@1}{center}\pgfgetlastxy\a\b%
  \pgfpointanchor{@2}{center}\pgfgetlastxy\c\d%
  \pgfpathlineto{\pgfqpoint{\c}{\b}}%
  \pgfpathlineto{\pgfqpoint{\c}{\d}}%
  \pgfnodealias{@1}{@2}%
}
\state{final}{%
  \pgftransformreset%
  \pgfpointanchor{@1}{center}\pgfgetlastxy\a\b%
  \pgfpointdecoratedpathlast\pgfgetlastxy\c\d%
  \pgfpathlineto{\pgfqpoint{\a}{\d}}%
  \pgfpathlineto{\pgfqpoint{\c}{\d}}%
}
}
\tikzset{rectilinear/.style={
  decoration={rectilinear, #1}, decorate
}}
\begin{document}
\begin{tikzpicture}[very thick, line join=round, line cap=round]
\draw [gray, postaction={rectilinear, draw=red}]
  (0,4) -- ++(30:2) -- ++(300:3);
\draw [gray, postaction={rectilinear, draw=green!50!black}]
  (0,2) circle [radius=1];
\draw  [gray, postaction={rectilinear={segment length=0.25cm}, draw=blue}]
  (0,0) -- (3,1) arc (90:-90:1) .. controls ++(180:1) and ++(225:1) .. cycle;
\end{tikzpicture}
\end{document}

enter image description here

Here four macro \Start, \Goleft, \Godown and \Goup to creat the desired path.

Code

\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}

\tikzset{every node/.style={inner sep=0pt,minimum size=0pt}}

\newcommand{\Start}[1]{\node (A) at #1 {};}
\newcommand{\Goleft}[1]{\draw($(A)+( -0.5\pgflinewidth ,0.5\pgflinewidth)$)--+(#1,0)node(A){};}
\newcommand{\Godown}[1]{\draw($(A)+(-0.5\pgflinewidth,0)$)--+(0,-#1)node(A){};}
\newcommand{\Goup}[1]{\draw($(A)+(-0.5\pgflinewidth,0)$)--+(0,#1)node(A){};}

\begin{document}

\begin{tikzpicture}
   \Start{(20,12)}
   \Goleft{2}
   \Godown{2}
   \Goleft{3}
   \Godown{1}
   \Goleft{4}
   \Goup{3}
\end{tikzpicture}

\end{document}

Output

enter image description here

  • Thanks - that helps alot. i'd like to also adjust the line width, which did by adding `[line width=8pt] for example. The problem, though is that the lines don't match up, and so the line edges are visible at the corners. it seems like I need to add something like a small filled square at each corner. – Donna Sep 26 '15 at 21:10
  • Just add line width=1pt (or what satisfy you) in the front of tikzpicture environment like this \begin{tikzpikture}[line width=1pt] – Salim Bou Sep 26 '15 at 21:11
  • Yes, I did that. But it still seemed to suffer from this problem that the corner segments don't match up. The solution from @GonzaloMedina doesn't have this problem. – Donna Sep 26 '15 at 22:02
  • My bad. I fixed a bug, and this solution works just as the one below. Thanks! – Donna Sep 26 '15 at 22:12

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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