Skip to content

Instantly share code, notes, and snippets.

@nickbailey
Created December 6, 2018 13:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nickbailey/f2cb96cd07ac2a246ce4ead4f861c579 to your computer and use it in GitHub Desktop.
Save nickbailey/f2cb96cd07ac2a246ce4ead4f861c579 to your computer and use it in GitHub Desktop.
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
Copy link
Author

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