TeX 中的寿命线

TeX 中的寿命线

我正在写一份关于人类历史上重要数学家和物理学家生活的文档(以 plainTeX 编写)。

现在我有一个问题想解决。我需要能够可视化它们的寿命(这样读者就能知道谁是谁的同时代人/同代人)。不幸的是,我不太擅长制作 TeX 的宏。有人能给我一点提示吗?

具体来说,我想象它会这样工作:

\person{name}{surname}{year_of_birth}{year_of_death}
\person{name}{surname}{year_of_birth}{year_of_death}
...
\renderpeople

会产生(例如,巴赫和莫扎特的实例)

Bach J.S.              |----------------|
Mozart A.                      |-----------------|
...
          |----------|-----------|----------|-----------|---------|
       1750        1800        1850       1900        1950      2000

主要是,如何实现线条的重新缩放,以使它们能够适应?

答案1

使用 vanilla TeX 快速破解纯 TeX。首先收集个人资料并计算一些值(最小年份、最大年份、姓名宽度),然后设置收集的个人资料,最后打印整个时间线。

\newdimen\NameWidth
\NameWidth=0pt
\newcount\MinYear
\MinYear=100000
\newcount\MaxYear
\MaxYear=-100000
\newtoks\PersonData
\PersonData={}
\newdimen\ScaleWidth
\newdimen\ScaleUnit
\newcount\TempCount
\newdimen\TickMarkWidth
\TickMarkWidth=.4pt
\newdimen\TickMarkHeight
\TickMarkHeight=8pt
\newdimen\LineWidth
\LineWidth=.4pt
\newdimen\LastYearCorr

\def\person#1#2#3#4{%
  \setbox0=\hbox{\makeperson{#1}{#2}\personsep}%
  \ifdim\wd0>\NameWidth
    \NameWidth=\wd0 %
  \fi
  \ifnum#3<\MinYear
    \MinYear=#3\relax
  \fi
  \ifnum#4>\MaxYear
    \MaxYear=#4\relax
  \fi
  \ifnum#3>#4\relax
    \errmessage{#2 #1 has negative live span, born in #3 and died in #4}%
  \fi
  \PersonData=\expandafter{\the\PersonData
    \DoPerson{#1}{#2}{#3}{#4}%
  }%
}
\def\makeperson#1#2{#1, #2}%
\def\personsep{ }
\def\renderpeople{%
  \par
  \divide\MinYear by 50\relax
  \multiply\MinYear by 50\relax
  \advance\MaxYear by 49\relax 
  \divide\MaxYear by 50\relax  
  \multiply\MaxYear by 50\relax
  \ScaleWidth=\hsize
  \advance\ScaleWidth by -\NameWidth
  \setbox0=\hbox{$\textstyle\the\MaxYear$}%
  \LastYearCorr=.5\wd0 %
  \advance\ScaleWidth by -\LastYearCorr
  \ScaleUnit=\ScaleWidth
  \TempCount=\MaxYear   
  \advance\TempCount by -\MinYear
  \divide\ScaleUnit by \TempCount
  \ScaleWidth=\ScaleUnit
  \multiply\ScaleWidth by \TempCount
  \noindent
  \the\PersonData
  \ScaleLine
  \par
}
\def\DoPerson#1#2#3#4{%
  \hbox to \hsize{%
    \hbox to \NameWidth{%
      \makeperson{#1}{#2}%
      \hfill
      \personsep
    }%
    \hfill
    \hbox to \ScaleWidth{%
      \kern#3\ScaleUnit   
      \kern-\MinYear\ScaleUnit
      \SetTickMark
      \TempCount=#4\relax
      \advance\TempCount by -#3\relax
      \SetLine\TempCount
      \SetTickMark
      \hfill
    }%
    \kern\LastYearCorr
  }%
  \hskip0pt\relax
}
\def\ScaleLine{%
  \hbox to \hsize{%
    \hbox to \NameWidth{\hfill}%
    \hfill
    \hbox to \ScaleWidth{%
      \TempCount=\MinYear 
      \SetTickYearMark    
      \loop
      \ifnum\TempCount<\MaxYear
        \SetLine{50}%
        \advance\TempCount by 50 %
        \SetTickYearMark
      \repeat
    }%
    \kern\LastYearCorr
  }%
  \hskip0pt\relax
}
\def\SetTickYearMark{%
  \hbox to 0pt{%
    \hss
    $\mathsurround=0pt\relax
      \mathop{\vcenter{%
        \hrule width \TickMarkWidth
               height .5\TickMarkHeight
               depth .5\TickMarkHeight 
      }}\limits_{\textstyle\the\TempCount}%
    $%
    \hss
  }%
}   
\def\SetTickMark{%
  \hbox to 0pt{%  
    \hss
    $\mathsurround=0pt\vcenter{%
      \hrule width \TickMarkWidth
             height .5\TickMarkHeight
             depth .5\TickMarkHeight 
    }$%
    \hss
  }%
}   
\def\SetLine#1{%
  $\mathsurround=0pt\vcenter{%
    \hrule width#1\ScaleUnit  
           height.5\LineWidth 
           depth.5\LineWidth  
  }$%
}

\person{Pachelbel}{J.}{1653}{1706}
\person{Bach}{J. S.}{1685}{1750}  
\person{Mozart}{W. A.}{1756}{1791}
\person{Euler}{L.}{1707}{1783}

\renderpeople
\bye

通过普通 TeX 实现时间轴

评论:

  • 我更喜欢 e-TeX \dimexpr\numexpr如果有的话;它们更舒服。但是除法不同,因为它们 \...expr对结果进行了四舍五入。

  • 强大的功能pgf/TikZ也可以在纯 TeX 中使用。

答案2

这是一个类似的 TeX 解决方案:

\input pst-grad
\input pstricks-add
\newbox\TBox
\psset{gradbegin=white,gradend=lightgray}
\catcode`\@11\relax

\def\BoxText{\@ifnextchar[\BoxText@i{\BoxText@i[3cm]}}
\def\BoxText@i[#1]#2#3#4{%
  \emergencystretch=3em
  \setbox\TBox\vbox{\hsize #1 #4\par}
  \rput[t](#2){\psframebox[fillstyle=gradient]{\leavevmode\copy\TBox\relax}}%
  \pnode(#2|0,0){A}\pnode(#2){B}
  \ncline{->}{A}{B}%
  \uput*{0.5cm}[-90](A){#3}%
}
\catcode`\@12\relax

\pspicture(0,0.25)(2.5,-10)
\psset{xunit=5}
\psaxes[yAxis=false,Ox=1518]{|->}(0,0)(2.5,-10)% 
\BoxText[4cm]{1.1123,-5.5}{10.2.}{%
Hier muss jetzt irgendetwas hinkommen, was, weiss ich auch nicht genau}
\BoxText{.767,-2}{15.10.}{%
Hier muss jetzt irgendetwas hinkommen, was, weiss ich auch nicht genau}
\endpspicture


\pspicture(0,0.25)(2.5,-10)
\psset{xunit=5cm}
\psaxes[yAxis=false,Ox=1518]{|->}(0,0)(2.5,-10)%
\BoxText{.787,-5}{17.10.}{%
Hier muss jetzt irgendetwas hinkommen, was, weiss ich auch nicht genau}
\pnode(A){A0}
\BoxText{.767,-2}{15.10.}{%
Hier muss jetzt irgendetwas hinkommen, was, weiss ich auch nicht genau}
\uput*{1.2cm}[-90](A0){17.10.}%
\endpspicture

\bye

在此处输入图片描述

相关内容