私は人類の歴史における重要な数学者と物理学者の生涯についての文書(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
バニラ 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
備考:
私は 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