如何绘制一定高度且可破坏的网格

如何绘制一定高度且可破坏的网格

我正在写一套讲义,应该有两个版本:一个是给我的,包含全部文本;另一个是给学生的,其中某些部分用网格替换,以便他们自己做笔记。

为了实现这一点,我尝试定义一个函数\gap,它可以包含我的讲义中的一些对象(段落/图形/定理/等),当布尔值gaps关闭时,它不执行任何操作,而当布尔值打开时,它会用具有文本宽度和适当高度的网格替换该对象。

考虑到手写文字比排版文本大,网格的高度应该是被替换对象的某个放大倍数。我将其定义\heightmultiplier为我已设置为的比例因子2.5

从表面上看,使用\fillwithgrid可从考试类中复制的函数很容易实现这exam.cls一点。此函数采用单个数值参数 - 要绘制的网格的高度。问题是,它产生的网格不可破坏,因此结果会在讲义中留下大量空白。因此,我正在尝试调整该函数以创建可破坏的网格。

我定义的第一个函数是\fillwithgridbreakable,像\fillwithgrid将要绘制的网格高度作为参数。首先,它将这个高度与当前页面上剩余的空间量进行比较\remainingspace,我将其定义为\textheight-\pagetotal。如果有足够的空间,它将绘制网格,否则它将绘制尽可能大的网格,然后再调用自身来绘制剩余大小的网格:

\newcommand{\fillwithgridbreakable}[1]{
    \newlength{\remainingspace}%
    \setlength{\remainingspace}{\textheight-\pagetotal}%
    \ifdim #1>\remainingspace%
    \fillwithgrid{\remainingspace}%
    \fillwithgridbreakable{#1-\remainingspace}%
    \else%
    \fillwithgrid{#1}%
    \fi
}

然后我定义了一个函数\gap,该函数以一些 LaTeX 代码作为输入。如果布尔值gaps关闭,它将运行代码,否则,它将测量\height该代码将生成的任何内容的高度,然后使用\fillwithgridbreakable参数调用\heightmultiplier\height

\newcommand{\gap}[1]{%
     \ifthenelse{\boolean{gaps}}{%
        \newdimen\height
        \setbox0=\vbox{#1}
        \height=\ht0 \advance\height by \dp0
        \fillwithgridbreakable{\heightmultiplier\height}
     }
     {%
        #1
     }
 }

我的问题是,我收到错误消息,说\gap缺少一个数字且单位被视为 0,并且它绘制的网格不可破坏。

这是 MWE

\documentclass{exam}

\usepackage{lipsum} 

\newboolean{gaps}
\setboolean{gaps}{true}

\newcommand{\heightmultiplier}{2.5}

\newcommand{\fillwithgridbreakable}[1]{
    \newlength{\remainingspace}%
    \setlength{\remainingspace}{\textheight-\pagetotal}%
    \ifdim #1>\remainingspace%
    \fillwithgrid{\remainingspace}%
    \fillwithgridbreakable{#1-\remainingspace}%
    \else%
    \fillwithgrid{#1}%
    \fi
}

\newcommand{\gap}[1]{%
     \ifthenelse{\boolean{gaps}}{%
        \newdimen\height
        \setbox0=\vbox{#1}
        \height=\ht0 \advance\height by \dp0
        \fillwithgridbreakable{\heightmultiplier\height}
     }
     {%
        #1
     }
 }

\begin{document}

\lipsum[1-5]

\gap{\lipsum[1-3]}

\end{document}

在第一个分页符处,其输出如下所示: MWE 的输出显示第一页底部有大片空白,并且仅在第二页的开头绘制网格 我将非常感激任何关于为什么这不起作用以及我可以做些什么来修复它的见解。我在 SE 上搜索了类似主题的帖子。这就是我发现如何像在函数中一样测量某物的高度\gap以及如何计算\remainingspace和使用 的方法\ifdim...\else。但我找不到任何可以从头开始创建易破坏环境的东西。

这也是我在 SE 上的第一篇文章,因此如果我能做些什么来改进它,请告诉我。

解决方案

几乎完全借鉴下面 John Kormylo 的解决方案,我想我会在这里提出一个可行的解决方案,修复一些错误,并可以更自由地调整网格大小和颜色等内容。

\usepackage{xcolor} %to adjust the grid colour
\usepackage{ifthen} %to create the boolean for turning the functionality of \gaps on and off

\newboolean{gaps}
\setboolean{gaps}{true}

\newcommand{\heightmultiplier}{2.5} %how much taller the grid is than the object it is replacing
\newcommand{\mygridsize}{.5cm} %the size of the grid squares
\colorlet{gridcolor}{gray!50} %the colour of the gridlines
\newcommand{\rulewidth}{0.8pt} %the width of the vertical rules

\newsavebox{\row}
\savebox{\row}{\begin{minipage}[b]{\textwidth}
  {\color{gridcolor}\hrule}
  \dimen9=\mygridsize\relax
  \count9=\numexpr \textwidth / \dimen9\relax
  {\color{gridcolor}\rule{\rulewidth}{\dimen9}}%
  \loop\ifnum\count9>1
    \advance\count9 by -1
    \hfill{\color{gridcolor}\rule{\rulewidth}{\dimen9}}%
  \repeat
  {\color{gridcolor}\hrule}
\end{minipage}}

\newcommand{\fillwithgridbreakable}[1]{% #1 = total height
  \setstretch{1} %if setstretch is changed elsewhere in the document, this prevents it from messing with the grid row spacing
  \setlength{\parskip}{0pt} %If included inside a list environment, the prevents the paragraph spacing from messing up with the grid row spacing
  \vfill
  \dimen8=#1\relax
  \dimen9=\mygridsize\relax
  \count8=\numexpr \dimen8 / \dimen9\relax
  \loop\ifnum\count8>0
    \advance\count8 by -1
    \noindent\usebox\row\par\vskip-\lineskip
  \repeat}
  
\newcommand{\gap}[1]{% #1 = text to be replaced
     \ifthenelse{\boolean{gaps}}{%
        \setbox0=\vbox{#1}%
        \fillwithgridbreakable{\dimexpr \heightmultiplier\ht0 + \heightmultiplier\dp0}%
     }
     {%
        #1
     }
 }

答案1

这展示了如何创建一个真正可破坏的网格(而不是一个损坏的网格)。

寄存器 0-9 据称可以自由使用一些例外\hrule是一个 TeX 基元,它 (a) 绘制一条线,(b) 作用类似于\par和 (c) 忽略\baselineskip\lineskip\loop\if... \repeat正是这样做的 。\repeat代替。\fi\if...

请注意,\fullwidth不可破坏。

\documentclass{exam}

\usepackage{lipsum}
\usepackage{showframe}

\newboolean{gaps}
\setboolean{gaps}{true}

\newcommand{\heightmultiplier}{2.5}

\newcommand{\fillwithgridbreakable}[1]% #1 = total height
{\bgroup
  \sbox9{\begin{minipage}[b]{\linewidth}% one row of grid
    \hrule
    \dimen9=\heightmultiplier\baselineskip\relax
    \count9=\numexpr \textwidth / \dimen9\relax
    \rule{0.4pt}{\dimen9}%
    \loop\ifnum\count9>1
      \advance\count9 by -1
      \hfill\rule{0.4pt}{\dimen9}%
    \repeat
    \hrule
  \end{minipage}}%
  \ht9=\dimexpr \ht9-0.4pt\relax% overlap borders
  \vfill
  \dimen8=#1\relax
  \count8=\numexpr \dimen8 / \ht9\relax
  \loop\ifnum\count8>0
    \advance\count8 by -1
    \noindent\usebox9\hrule height0pt
  \repeat
\egroup}
  
\newcommand{\gap}[1]{% #1 = text to be replaced
     \ifthenelse{\boolean{gaps}}{%
        \setbox0=\vbox{#1}%
        \fillwithgridbreakable{\dimexpr \heightmultiplier\ht0 + \heightmultiplier\dp0}%
     }
     {%
        #1
     }
 }

\begin{document}

\lipsum[1-5]

\gap{\lipsum[1-3]}

\end{document}

答案2

这实际上不是对你好问题的回答,但对于评论来说太长了,它可能会有所帮助。我建议做一些概念上更简单的事情(?):(滥用)使用可以分成几页的表格环境(longtable?也许现在有更好的东西可用?)。然后你几乎可以免费获得所有内容,尤其是页面上的分隔符。你不会测量另一种选择并乘以 2.5,但无论如何,说你想要一定数量的网格线不是更容易吗?

我很抱歉,但我对 LaTeX 不太了解,所以我不知道如何对那里建议的内容进行编码,但您可以在下面找到 ConTeXt 版本:

没什么好说的。前两个设置只设置了纸张大小和文本块的宽度,并不重要。然后我们定义一个宏 \MyGrid,它以网格线数作为参数。它排版一个可以分割的表格。在宏内部,设置并使用了自然表格机制,并且有一个循环。s\samplefile只是为了输入一些文本。

\setuppapersize[A5]

\setuplayout
  [width=10cm]

\starttexdefinition MyGrid #1
\startplacefloat
  [table]
  [location={force,nonumber,split}]
  \setupTABLE
    [width=0.5cm,
     height=0.5cm,
     split=yes]
  \bTABLE
    \dorecurse{#1}{\bTR\dorecurse{20}{\bTD\eTD}\eTR}
  \eTABLE
\stopplacefloat
\stoptexdefinition

\starttext
\samplefile{ward}

\MyGrid {10}

\samplefile{knuthmath}

\MyGrid {40}

\samplefile{ward}
\stoptext

上下文结果

相关内容