Ich schreibe ein Dokument (in PlainTeX) über das Leben bedeutender Mathematiker und Physiker der Menschheitsgeschichte.
Jetzt habe ich ein Problem, das ich angehen möchte. Ich muss in der Lage sein,visualisierenihre Lebensspanne (damit der Leser sehen kann, wer wessen Zeitgenosse/Gleichalte war). Leider bin ich nicht so geschickt darin, TeX-Makros zu erstellen. Kann mir jemand einen Tipp geben, wie das geht?
Konkret stelle ich mir vor, dass es so funktionieren würde:
\person{name}{surname}{year_of_birth}{year_of_death}
\person{name}{surname}{year_of_birth}{year_of_death}
...
\renderpeople
was (zum Beispiel bei Bach und Mozart) ergeben würde
Bach J.S. |----------------|
Mozart A. |-----------------|
...
|----------|-----------|----------|-----------|---------|
1750 1800 1850 1900 1950 2000
Vor allem: Wie lässt sich die Skalierung der Linien so implementieren, dass sie passen?
Antwort1
Ein schneller Hack in Plain TeX unter Verwendung von Vanilla TeX. Zuerst werden die Personendaten gesammelt und einige Werte berechnet (minimales Jahr, maximales Jahr, Breite der Namen), dann werden die gesammelten Personendaten festgelegt und schließlich wird die gesamte Zeitleiste gedruckt.
\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
Bemerkungen:
Ich würde e-TeX bevorzugen
\dimexpr
und\numexpr
wenn sie verfügbar sind, sind sie komfortabler. Divisionen sind jedoch anders, da sie\...expr
das Ergebnis runden.Das Leistungsstarke
pgf/TikZ
ist auch in reinem TeX verfügbar.
Antwort2
hier ist eine ähnliche TeX-Lösung:
\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