Estoy escribiendo un documento (escrito en PlainTeX) sobre las vidas de importantes matemáticos y físicos en la historia de la humanidad.
Ahora tengo un problema que me gustaría abordar. necesito podervisualizarsu esperanza de vida (para que el lector pueda ver quién fue contemporáneo/coetáneo de quién). Desafortunadamente, no soy muy hábil para crear macros de TeX. ¿Alguien puede darme una pista de cómo hacerlo?
Específicamente, imagino que funcionaría de esta manera:
\person{name}{surname}{year_of_birth}{year_of_death}
\person{name}{surname}{year_of_birth}{year_of_death}
...
\renderpeople
que produciría (por ejemplo, con ejemplos de Bach y Mozart)
Bach J.S. |----------------|
Mozart A. |-----------------|
...
|----------|-----------|----------|-----------|---------|
1750 1800 1850 1900 1950 2000
Principalmente, ¿cómo se implementaría el cambio de escala de las líneas para que encajen?
Respuesta1
Un truco rápido en TeX simple usando Vanilla TeX. Primero se recopilan los datos de la persona y se calculan algunos valores (año mínimo, año máximo, ancho de los nombres), luego se configuran los datos de la persona recopilados y finalmente se imprime toda la línea de tiempo.
\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
Observaciones:
Preferiría los e-TeX
\dimexpr
y\numexpr
si están disponibles; son más cómodos. Sin embargo las divisiones son diferentes porque\...expr
se redondean el resultado.El poderoso
pgf/TikZ
también está disponible en TeX simple.
Respuesta2
aquí hay una solución TeX similar:
\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