Skip to content

Instantly share code, notes, and snippets.

@nickbailey nickbailey/gdl.tex
Created Dec 6, 2018

Embed
What would you like to do?
Geometrically Divided Line in tikz
\documentclass{minimal}
\usepackage{tikz,ifthen}
\usetikzlibrary{calc}
% HELPER MACROS
% Proportional postion of the first tick
%
% Arguments: number of segments, ratio
\newcommand{\firstl}[2]{ ((1-#2)/(1-(#2^#1))) }
% Find the position of the nth tick
% as a proportion of the line length
%
% Arguments: first seg len, ratio, index
\newcommand{\nthl}[3]{ ((#1)*(1-((#2)^#3))/(1-(#2))) }
% OPTIONAL ARGUMENT PARSING
\newif\ifshowticks
\pgfkeys{/GDL/.is family, /GDL,
ticklen/.estore in = \ticklen,
majortick/.estore in = \majtick,
marktype/.estore in = \marktype,
r/.estore in = \markradius,
balls/.estore in = \ballcolor,
endballs/.estore in = \endballcolor,
showticks/.is if=showticks,
default/.style = {
marktype=none, ticklen=5mm, r=3mm, majortick=3.75mm,
balls=green, endballs=red,
showticks=true
}
}
% Draw a tikz Geometrically Divided Line.
%
% Arguments:
% #2 Start Point
% #3 End Point
% #4 Number of segments
% #5 Ratio of line-segment lengths
%
% #1 optionally contains ,-separated options.
\newcommand{\GDL}[5][]{
\pgfkeys{/GDL, default, #1}
% Draw the line
\draw #2 -- #3;
\ifshowticks
% Draw ticks.
% This has to be done on the main layer or it might interfere with decorations
\draw [shorten <= -\majtick] #2 -- ($#2!\ticklen!90:#3$);
\foreach \i in {1,...,#4}{
\coordinate (Q) at ($#2!\nthl{\firstl{#4}{#5}}{#5}{\i}!#3$);
% Draw ticks
\draw ($(Q)!\ticklen!-90:#2$) -- (Q);
}
\draw ($(Q)!\majtick!90:#2$) -- (Q);
\fi
% Decorations
\ifthenelse{\equal{\marktype}{none}}{}{
\pgfdeclarelayer{decorations}
\pgfdeclarelayer{quoins}
\pgfsetlayers{main,decorations,quoins}
% Draw decorations. First those at the line's end, then the rest.
\ifthenelse{\equal{\marktype}{balls}}{
\begin{pgfonlayer}{decorations}
\foreach \i [evaluate= {\i-1} as \ball] in {2,...,#4}{
\coordinate (Q) at ($#2!\nthl{\firstl{#4}{#5}}{#5}{\ball}!#3$);
% Draw balls
\shade[ball color=\ballcolor] (Q) circle [radius=\markradius];
}
\end{pgfonlayer}
\begin{pgfonlayer}{quoins}
\foreach \Q in {#2,#3}{
\shade[ball color=\endballcolor] \Q circle [radius=\markradius];
}
\end{pgfonlayer}
}{} % end of if \marktype == balls
}
}
\begin{document}
\begin{tikzpicture}
% Vanilla Geometrically Divided Line
\GDL{(0,9.5)}{(12,9.5)}{10}{0.8}
% Place baubles and set their colour
\GDL[marktype=balls,balls=green,endballs=yellow]{(0,8.5)}{(12,8.5)}{4}{0.5}
% Label the segments using the \nthl macro
\GDL[marktype=balls,balls=gray,r=2mm]{(0,7)}{(12,7)}{5}{0.5}
\node [anchor=south west] at ($(0,7)!\nthl{\firstl{5}{0.5}}{6.5}{0}!(12,7)$){This is the first segment};
\node [anchor=north west] at ($(0,7)!\nthl{\firstl{5}{0.5}}{6.5}{1}!(12,7)$) {\, Second one $\uparrow$};
% A diagonal line with and without ticks and with simple labling
\GDL[showticks=false,marktype=balls,endballs=white,balls=blue]{(0,2.5)}{(12,5.5)}{3}{0.33}
\draw (0,2.5) -- (12,5.5) node [pos=0.3,above,sloped] {Now also works when the line is sloping};
\GDL[majortick=0,ticklen=2mm]{(0,3.5)}{(6,5)}{4}{3}
\GDL[majortick=0,ticklen=2mm]{(12,4.5)}{(6,3)}{4}{3}
\draw (6,3) -- node [above,sloped] {Drawing R-L inverts ticks} (12,4.5) ;
% Overlay two lines for accel./retard.
% Note ``endball'' in the middle. These are drawn in their own layer
\GDL[showticks=false,marktype=balls]{(0,1)}{(7.5,1)}{10}{0.8}
\GDL[showticks=false,marktype=balls]{(7.5,1)}{(12,1)}{10}{1.2}
\end{tikzpicture}
\end{document}
@nickbailey

This comment has been minimized.

Copy link
Owner Author

commented Dec 6, 2018

We wanted to draw a line with ticks or other decorations on it
for a paper talking about musical structure. I decided to write a tikz macro with
some optional arguments in case it might become useful again, but also
to learn more about optional arguments in tikz.

This would have been impossibly difficult without Ryan Reich lucid summary
https://tex.stackexchange.com/a/34318/40927 as I'd been having a lot of trouble
understanding the manual. It seems much clearer now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.