有没有更好的方法来检查 LaTeX 中的可除性?

有没有更好的方法来检查 LaTeX 中的可除性?

我想绘制一把修剪过的尺子,例如,从2.3cm3.9cm,两个连续标记之间的距离为1mm

我很难有效地检查计数器是否是 5 或 10 的倍数。如果计数器是 5 的倍数,则标记很6pt长,否则,如果计数器是 10 的倍数,则标记很9pt长,并且将商打印为标签。

以下是我的完整代码。

\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}

在此处输入图片描述

有没有更好的方法来检查 LaTeX 中的可除性?

答案1

\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}

在此处输入图片描述

答案2

为了进行比较,这里是 Metapost 代码来实现这样的宏(使用 ConTeXt;因为我不知道如何在 LaTeX 中嵌入 Metapost)。

\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

在此处输入图片描述

答案3

使用 TikZ(和 PGFkeys)来获得一点乐趣。

还可以使用库添加刻度decoration.markings,这样就可以沿曲线创建标尺(但显然不是固定长度,而是特定的坐标(Bézier/ to)。

下列的SDrolet的评论,我已修复代码,以便它实际上使用英寸作为英寸标尺。我还更改了刻度,以便用户可以更轻松地对其进行个性化设置\Ruler

使用该array函数并不快(因为我们每次迭代只能遍历列表)但它是最短的实现。

代码

\documentclass[tikz,border=12pt]{standalone}
\tikzset{
  ruler from/.initial=0,
  ruler to/.initial=10,
  ruler steps/.initial=10,
  ruler ticks/.initial={9,3,3,3,3,6,3,3,3,3},
  ruler rotate/.initial=0,
  every ruler picture/.style={line cap=rect},
  % presets
  ruler/.is choice,
  ruler/cm/.style={
    x=1cm,
    ruler ticks={9,3,3,3,3,6,3,3,3,3},
    ruler steps=10},
  ruler/in/.style={
    x=1in,
    ruler ticks={9,3,5,3,7,3,5,3},
    ruler steps=8}}
\makeatletter
\newcommand\Ruler[1][]{%
\begin{tikzpicture}[
  every ruler picture/.try,#1,rotate=\pgfkeysvalueof{/tikz/ruler rotate}]
  \pgfmathtruncatemacro\ruler@steps{\pgfkeysvalueof{/tikz/ruler steps}}
  \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=
              array({\pgfkeysvalueof{/tikz/ruler ticks}},\ruler@CntMod)}
  ] 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,
             rotate=\pgfkeysvalueof{/tikz/ruler rotate}]
          {$\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[ruler rotate=30, ruler to=-5]
\end{document}

输出(不按比例)

剪下厘米尺

英寸标尺

旋转厘米尺

答案4

赫伯特 (Herbert) 的解决方案采用修改算法来避免冗余。

\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}

相关内容