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 draw a trimmed ruler, for example, from 2.3cm to 3.9cm where the distance between two consecutive marks is 1mm.

I have difficulty to efficiently check whether or not the counter is a multiple of 5 or 10. If the counter is a multiple of 5 then the mark is 6pt long else if the counter is a multiple of 10 then the mark is 9pt long plus printing the quotient as a label.

The following is my complete code.

\documentclass[pstricks,border=12pt]{standalone}
\usepackage[nomessages]{fp}
\usepackage{multido}
\newcommand\Ruler[2]{%
\FPeval\start{round(10*#1:0)}%
\FPeval\stop{round(10*#2:0)}%
\FPeval\width{round(stop-start:0)}%
\FPeval\count{round(\width+1:0)}
\psset{xunit=\dimexpr\psxunit/10}
\begin{pspicture}[linecap=2](\width,1)
    \psline(\width,0)
    \multido{\ix=0+1,\i=\start+1}{\count}{%
        \FPeval\quo{trunc(\i/5:0)}
        \FPeval\rem{round(\i-5*quo:0)}
        \psline(\ix,0)(\ix,3pt)
        \FPifzero\rem
            \psline(\ix,0)(\ix,6pt)% if \i can be defined by 5
        \fi
        \FPeval\quo{trunc(\i/10:0)}
        \FPeval\rem{round(\i-10*quo:0)}
        \FPifzero\rem
            \psline(\ix,0)(\ix,9pt)% if \i can be defined by 10
            \uput[90](\ix,6pt){\quo}% if \i can be defined by 10 and put the result of \i divided by 10
        \fi
    }
\end{pspicture}\ignorespaces
}

\begin{document}
\Ruler{2.3}{3.9}
\end{document}

enter image description here

Is there a better way to check divisibility in LaTeX?

share|improve this question
1  
In LaTeX3 you can do \int_compare:nTF{\int_mod:nn {#1}{5} = 0}{true}{false}. I don't think that using fixed point numbers for doing integer arithmetic is the best way to proceed. –  egreg Sep 29 '13 at 17:57
    
Related: How do I calculate n modulo 3 in LaTeX? –  Qrrbrbirlbel Sep 29 '13 at 21:48
add comment

4 Answers

up vote 3 down vote accepted
\documentclass[pstricks,border=12pt]{standalone}
\usepackage{multido}
\makeatletter
\newcommand\Ruler[2]{%
  \pstFPMul\Start{#1}{10}%
  \pstFPMul\Stop{#2}{10}%
  \def\Width{\numexpr\Stop-\Start\relax}%
  \psset{xunit=0.1\psxunit}
  \begin{pspicture}[linecap=2](\Width,1)
    \psline(\Width,0)
    \multido{\ix=0+1,\i=\Start+1}{\numexpr\Width+1}{%
       \pst@mod{\i}{5}\result
       \psline(\ix,0)(\ix,3pt)
       \ifnum\result=0  \psline(\ix,0)(\ix,6pt) \fi  % i mod 5=0
        \pst@mod{\i}{10}\result
        \ifnum\result=0
            \psline(\ix,0)(\ix,9pt)%
            \uput[90](\ix,6pt){\the\numexpr\i/10}%  i mod 10 = 0
        \fi}
  \end{pspicture}\ignorespaces}
\makeatother
\begin{document}
\Ruler{2.3}{3.9}
\end{document}

enter image description here

share|improve this answer
add comment

For comparison, here is Metapost code to implement such a macro (using ConTeXt; because I don't know how to embed Metapost in LaTeX).

\define[2]\drawMPruler% from to (in mm)
    {\startMPcode
        newnumeric height;   height   := 3mm;
        newnumeric distance; distance := 1mm;

        newpath tic, medium_tic, big_tic;
        tic        := origin -- (0,  height);
        medium_tic := origin -- (0, 2height);
        big_tic    := origin -- (0, 3height);

        linecap := butt;

        % Draw base
        draw (#1*distance, 0) -- (#2*distance,0);

        for i = #1 step 1 until #2 :

          % Draw tics
          draw 
            (if (i mod 10) = 0 : big_tic elseif i mod 5 = 0 : medium_tic else : tic fi)
            shifted (i*distance,0);

          % Draw label
          if i mod 10 = 0 :
            draw textext.top (decimal (i/10)) shifted (i*distance, 3*height + 2pt);
          fi
        endfor;

      \stopMPcode}

\starttext

\drawMPruler{23}{39}

\stoptext

enter image description here

share|improve this answer
add comment

Just a little fun with TikZ (and PGFkeys).

Improvements could be implemented that rotate the nodes without transform shape, the ticks can also be added with the decoration.markings library which would make it possible to create a ruler along a curved line (but obviously not with a fixed length but for certain coordinates (Bézier/to).

Code

\documentclass[tikz,border=12pt]{standalone}
\tikzset{
  ruler from/.initial=0,
  ruler to/.initial=10,
  ruler steps/.initial=10,
  ruler step semi/.initial=5,
  every ruler picture x/.style={x=1cm},
  % presets
  ruler/.is choice,
  ruler/cm/.style={
    every ruler picture x/.style={x=1cm},
    ruler steps=10,
    ruler step semi=5},
  ruler/in/.style={
    every ruler picture x/.style={x=1in},
    ruler steps=8,
    ruler step semi=4}}
\makeatletter
\newcommand\Ruler[1][]{%
\begin{tikzpicture}[line cap=rect, every ruler picture x, #1]
  \pgfmathtruncatemacro\ruler@steps{\pgfkeysvalueof{/tikz/ruler steps}}
  \pgfmathtruncatemacro\ruler@steps@semi{\pgfkeysvalueof{/tikz/ruler step semi}}
  \pgfmathtruncatemacro\ruler@Start
                                {floor((\pgfkeysvalueof{/tikz/ruler from})*\ruler@steps)}
  \pgfmathtruncatemacro\ruler@End{ceil((\pgfkeysvalueof{/tikz/ruler to})*\ruler@steps)}
  \draw (\ruler@Start/\ruler@steps,0) -- (\ruler@End/\ruler@steps,0);
  \foreach \ruler@Cnt[
    evaluate={\ruler@CntMod=int(Mod(\ruler@Cnt,\ruler@steps))},
    evaluate={\ruler@CntModLength=
      ifthenelse(\ruler@CntMod==0, 9,
        ifthenelse(\ruler@CntMod==\ruler@steps@semi, 6, 3))}
  ] in {\ruler@Start,...,\ruler@End}
    \draw (\ruler@Cnt/\ruler@steps,0) -- ++(up:\ruler@CntModLength pt)
      \ifnum\ruler@CntMod=0
        node[above, text depth=+2pt, inner sep=+0pt]
          {$\pgfmathprint{int(\ruler@Cnt/\ruler@steps)}$}
      \fi;
\end{tikzpicture}\ignorespaces}

\begin{document}
\Ruler[ruler from=2.3, ruler to=3.9]
\Ruler[ruler=in, ruler to=8]
\Ruler[rotate=30, transform shape, ruler to=-5]% weird but works
\end{document}

Output (not to scale)

enter image description here

enter image description here

enter image description here

share|improve this answer
    
I realize that an inch ruler usually has four different ticks but that will need a different implementation for the steps and the Mod functions (but surely can be done). –  Qrrbrbirlbel Sep 29 '13 at 21:08
add comment

Herbert's solution with modified algorithm to avoid redundancies.

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{multido}
\psset{unit=2cm}
\makeatletter
\newcommand\Ruler[2]{%
\pstFPMul\Start{#1}{10}%
\pstFPMul\Stop{#2}{10}%
\def\Width{\numexpr\Stop-\Start\relax}%
\psset{xunit=.1\psxunit}
\begin{pspicture}[linecap=2](\Width,.325)
    \psline(\Width,0)
    \multido{\ix=0+1,\i=\Start+1}{\numexpr\Width+1}{%
        \pst@mod{\i}{10}\rem
        \ifnum\rem=0
            \psline(\ix,0)(\ix,9pt)
            \uput[90](\ix,6pt){\the\numexpr\i/10}
        \else
            \pst@mod{\i}{5}\rem
            \ifnum\rem=0
                \psline(\ix,0)(\ix,6pt)
            \else
                \psline(\ix,0)(\ix,3pt)
            \fi
        \fi
    }
\end{pspicture}\ignorespaces
}
\makeatother

\begin{document}
\Ruler{2.3}{3.9}
\end{document}
share|improve this answer
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.