Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm writing a document (written in plainTeX) about the lives of important mathematicians and physicists in human history.

Now I have a problem I'd like to tackle. I need to be able to visualize their lifespans (so that reader can see who was whose contemporary/coeval). Unfortunatelly, I'm not that skilled in making TeX's macros. Can anyone give me a hint how to do it?

Specifically, I imagine it would work this way:

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

which would produce (for instance, with instances of Bach & Mozart)

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

Mainly, how would one implement rescaling of lines, so they would fit?

share|improve this question

migrated from stackoverflow.com Aug 21 '12 at 17:50

This question came from our site for professional and enthusiast programmers.

3  
possible duplicate of What package supports this kind of timeline? –  Jake Aug 21 '12 at 17:52
3  
@Jake The question is is about plain, whereas the linked one is about 'packages', and so almost certainly LaTeX. –  Joseph Wright Aug 21 '12 at 17:53
1  
@JosephWright: The solution of Herbert and David a nearly plain ;-) –  Marco Daniel Aug 21 '12 at 17:55
    
@JosephWright: Oops, sorry, missed the PlainTeX info completely. –  Jake Aug 21 '12 at 17:57
add comment

2 Answers 2

up vote 16 down vote accepted

A quick hack in plain TeX using vanilla TeX. First the person data are collected and some values are calculated (minimal year, maximal year, width of names), then the collected person data are set and finally the whole time line is printed.

\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

Timelines via plain and vanilla TeX

Remarks:

  • I would prefer e-TeX's \dimexpr and \numexpr if they are available; they are more comfortable. However divisions are different, because the \...expr are rounding the result.

  • The powerful pgf/TikZ is available in plain TeX, too.

share|improve this answer
add comment

here is a similiar TeX solution:

\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

enter image description here

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.