Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I want to achieve the following in TikZ:

enter image description here

To get the exact width of the line I have no issues with - the problem lies in adding an arbitrary number of snags along the line which are equally distanced apart. I would also like to be able to add text between the snags (like 0, 1, 2, ..., but that's just an example) And I don't want to add and position the snags manually because I believe TikZ will do a much better job for me. But how?

share|improve this question
add comment

2 Answers

up vote 10 down vote accepted

You could use the border decoration implemented in TikZ (see the manual, page 324). Unfortunately, the decoration does not draw the last tick on a line, so I did some workaround drawing a second decoration backwards:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{decorations}
\usetikzlibrary{decorations.pathreplacing}

\newcommand{\tickedline}[6]{% Start, End, line options, segment length, amplitude, angle
    \begin{scope}[decoration={border, segment length=#4, amplitude=#5, angle=#6}]%
        \draw[#3,postaction={decorate,draw}] (#1) -- (#2);%
        \draw[decoration={border, segment length=#4, amplitude=#5, angle=180-#6, mirror}, #3, postaction={decorate,draw}] (#2) -- (#1);%
    \end{scope}%
}

\begin{document}

\begin{tikzpicture}
\tickedline{0,0}{5.7,0}{thin, green}{3mm}{5mm}{45}
\tickedline{1,1}{6,1}{very thick, red}{5mm}{2mm}{90}
\tickedline{0,2}{5,5}{thick, blue}{2mm}{4mm}{38}
\end{tikzpicture}

\end{document}

Some examples:

enter image description here

You may notice that the first and last blue line are thinner than all the others. This is due to the fact that I draw a forward and a backward decorarion, and that the length of the line is no integer multiple of the line width. So one has to either choose appropriate segment lengths for your linewidth or find a way to force TikZ to draw the decoration line on the last segment.


Edit 1: I solved the issue. Instead of specifying the segment length, you can now either specify the number of segments or the number of ticks (which is segments+1):

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{decorations}
\usetikzlibrary{decorations.pathreplacing}

\newcommand{\tickedline}[6]{% Start, End, line options, segment length, amplitude, angle
    \begin{scope}[decoration={border, segment length=#4, amplitude=#5, angle=#6}]%
        \draw[#3,postaction={decorate,draw}] (#1) -- (#2);%
        \draw[decoration={border, segment length=#4, amplitude=#5, angle=180-#6, mirror}, #3, postaction={decorate,draw}] (#2) -- (#1);%
    \end{scope}%
}

\newcommand{\tikzsegments}[8]{% x1,y1, x2,x2, line options, number of segments, amplitude, angle
    \pgfmathsetmacro{\lengthsegment}{sqrt(pow(#3-#1,2)+pow(#4-#2,2))/#6}
    \begin{scope}[decoration={border, segment length=\lengthsegment cm, amplitude=#7, angle=#8}]%
        \draw[#5,postaction={decorate,draw}] (#1,#2) -- (#3,#4);%
        \draw[decoration={border, segment length=\lengthsegment cm, amplitude=#7, angle=180-#8, mirror}, #5, postaction={decorate,draw}] (#3,#4) -- (#1,#2);%
    \end{scope}%
}

\newcommand{\tikzticks}[8]{% x1,y1, x2,x2, line options, number of ticks, amplitude, angle
    \pgfmathsetmacro{\lengthsegment}{sqrt(pow(#3-#1,2)+pow(#4-#2,2))/(#6-1)}
    \begin{scope}[decoration={border, segment length=\lengthsegment cm, amplitude=#7, angle=#8}]%
        \draw[#5,postaction={decorate,draw}] (#1,#2) -- (#3,#4);%
        \draw[decoration={border, segment length=\lengthsegment cm, amplitude=#7, angle=180-#8, mirror}, #5, postaction={decorate,draw}] (#3,#4) -- (#1,#2);%
    \end{scope}%
}

\begin{document}

%\begin{tikzpicture}
%\tickedline{0,0}{5.7,0}{thin, green}{3mm}{5mm}{45}
%\tickedline{1,1}{6,1}{very thick, red}{5mm}{2mm}{90}
%\tickedline{0,2}{5,5}{thick, blue}{2mm}{4mm}{38}
%\end{tikzpicture}

\begin{tikzpicture}
\tikzsegments{0}{0}{5.7}{0}{thin, green}{19}{5mm}{45}
\tikzsegments{1}{1}{6}{1}{very thick, red}{14}{2mm}{90}
\tikzsegments{0}{2}{5}{5}{thick, blue}{30}{4mm}{38}
\end{tikzpicture}
\hspace{2cm}
\begin{tikzpicture}
\tikzticks{0}{0}{5.7}{0}{thin, green}{11}{5mm}{45}
\tikzticks{1}{1}{6}{1}{very thick, red}{11}{2mm}{90}
\tikzticks{0}{2}{5}{5}{thick, blue}{11}{4mm}{38}
\end{tikzpicture}

\end{document}

Now even on non-horizontal lines it works fine:

enter image description here

share|improve this answer
    
These decorations bring back the AutoCAD days, yuck :) –  percusse Sep 30 '11 at 11:22
add comment

Here you have an example. A new command \drawsnags with three parameters, starting point, line length and number of snags.

\documentclass[border=3mm]{standalone}
\usepackage{tikz}

%\drawsnags{starting point}{line width}{number of snags}
\newcommand{\drawsnags}[3]{
    \draw[line width=3pt, line cap=rect] #1--++(#2,0);
    \foreach \i in {0,...,#3}
        \draw[line width=3pt,shift={#1}] ({\i*#2/#3},0) --++(0,0.2);}

\begin{document}
\begin{tikzpicture}
  \drawsnags{(0,0)}{5}{3};
  \drawsnags{(0,2)}{8}{5};
  \drawsnags{(1,-1)}{3}{4};
\end{tikzpicture}
\end{document}

enter image description here

You will have to adjust joins at starting and ending point.

EDIT: Following Andrew's suggestion I've added line cap=rect option. The new result is: enter image description here

Still not perfect but better.

share|improve this answer
    
With regard to the joins at the starting and ending point, if you put line cap=rect on the horizontal line then it looks better (though I find that on different zooms I get different values of "better"). –  Andrew Stacey Sep 30 '11 at 9:43
    
Re the "still not perfect", this is what I meant about different zooms. If I zoom to 400% then it looks fine, so I think it's a rendering issue. One way to ensure that it looked fine would be for the first and last to be part of the initial path and then use the foreach to draw only the inner ones. –  Andrew Stacey Sep 30 '11 at 13:11
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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