我想绘制一把修剪过的尺子,例如,从2.3cm
到3.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}