%% trainmap-doc.tex
%% =========================================================================
%% User manual for the `trainmap' package.
%% Compile with:  pdflatex trainmap-doc.tex   (twice, for the table of
%% contents and cross-references).  Produces trainmap.pdf.
%%
%% Copyright (C) 2026 Pol Sardà Palla.  Distributed under the LPPL v1.3c
%% or later; see LICENSE.
%% =========================================================================
\documentclass[11pt,a4paper]{article}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage[margin=2.6cm]{geometry}
\usepackage{microtype}
\usepackage{xcolor}
\usepackage{booktabs}
\usepackage{array}
\usepackage{enumitem}
\usepackage{parskip}
\usepackage{listings}

% The package being documented (live diagrams below use it directly).
\usepackage{trainmap}

\definecolor{tmDoc}{HTML}{9B1987}   % accent (R8 purple)
\definecolor{tmCodeBg}{HTML}{F6F4F9}
\definecolor{tmRule}{HTML}{C9BCD6}
\definecolor{tmKw}{HTML}{675199}
\definecolor{tmCmt}{HTML}{6B8E23}
\definecolor{tmStr}{HTML}{AE6118}

\usepackage[
  colorlinks=true,
  linkcolor=tmDoc,
  urlcolor=tmDoc,
  citecolor=tmDoc,
  pdftitle={trainmap -- schematic railway and transit maps with TikZ},
  pdfauthor={Pol Sarda Palla},
  pdfsubject={LaTeX package documentation},
  pdfkeywords={LaTeX, TikZ, railway, transit map, Rodalies, FGC}
]{hyperref}

% ---- code listing style --------------------------------------------------
\lstset{
  language=[LaTeX]TeX,
  basicstyle=\ttfamily\small,
  keywordstyle=\color{tmKw}\bfseries,
  commentstyle=\color{tmCmt}\itshape,
  stringstyle=\color{tmStr},
  backgroundcolor=\color{tmCodeBg},
  frame=single,
  rulecolor=\color{tmRule},
  framesep=6pt,
  xleftmargin=6pt, xrightmargin=6pt,
  breaklines=true,
  columns=fullflexible,
  keepspaces=true,
  showstringspaces=false,
  morekeywords={settrunk,addstation,addterminal,addinterchange,track,branch,
    forkup,forkline,forkdown,joinline,tmlastx,tmlasty,usetikzlibrary}
}

% Logos / inline code shortcut.
\providecommand{\TikZ}{Ti\emph{k}Z}
\newcommand{\code}[1]{\texttt{#1}}
% A framed box that centres a live diagram.
\newsavebox{\tmdiagbox}
\newenvironment{diagrambox}
  {\begin{center}\setlength{\fboxsep}{10pt}\setlength{\fboxrule}{0.4pt}%
   \begin{lrbox}{\tmdiagbox}\begin{minipage}{0.9\linewidth}\centering}
  {\end{minipage}\end{lrbox}\fbox{\usebox{\tmdiagbox}}\end{center}}

\title{\vspace{-1.2cm}%
  {\Huge\bfseries\color{tmDoc} trainmap}\\[4pt]
  {\large Schematic railway and transit maps with \TikZ}\\[2pt]
  {\normalsize in the style of FGC / Rodalies de Catalunya line diagrams}}
\author{Pol Sardà Palla\\\small\texttt{psardapalla48@gmail.com}}
\date{Version 1.0.0\quad\textbullet\quad 2026/08/28}

\begin{document}
\maketitle
\thispagestyle{empty}

\begin{abstract}
\noindent
\textbf{trainmap} is a small \LaTeX{} package, built on \TikZ{}, for drawing
schematic railway and transit line diagrams \emph{declaratively}. Instead of
positioning every node by hand you describe a line as a sequence of stations
and terminals, and the package advances an internal cursor, draws the track
segments, places the station symbols and rotated labels, and even folds very
long lines onto several rows. It ships with the official line colours of
\emph{Rodalies de Catalunya} and \emph{FGC}. This manual documents version
1.0.0.
\end{abstract}

\tableofcontents
\bigskip
\hrule
\bigskip

% =========================================================================
\section{Introduction and purpose}
% =========================================================================

Transit line diagrams follow a very regular visual grammar: a coloured track,
tick marks for ordinary stations, filled discs for terminals, capsules where
several services meet, and labels set at a slant so long station names do not
collide. Reproducing that grammar by hand in \TikZ{} is repetitive and
error-prone --- every coordinate has to be computed manually.

\textbf{trainmap} captures the grammar in a handful of commands. You declare
the tracks that form the \emph{trunk}, then call \code{\textbackslash addstation},
\code{\textbackslash addterminal} and \code{\textbackslash addinterchange} in
order. Each call advances a horizontal cursor, draws the connecting track, and
renders the station. Branches and forks are drawn with curved connectors
(\code{\textbackslash forkup}, \code{\textbackslash forkdown},
\code{\textbackslash joinline}, \dots), and lines that are too long to fit on
one row fold automatically into a \emph{serpentine} layout.

The package offers two presentation styles, selected with the \code{mode} key:

\begin{description}[leftmargin=1.4cm,style=nextline]
  \item[\code{mode=fgc} (default)] Every track of the trunk is drawn at once;
    each terminal carries a coloured \emph{badge} with its line code below the
    disc. This is the classic multi-line FGC schematic.
  \item[\code{mode=rodalies}] A single line is drawn, and its code appears on a
    square plate at each end of the whole route. Suited to long single lines,
    usually combined with serpentine wrapping.
\end{description}

% =========================================================================
\section{Installation}
% =========================================================================

The package consists of two files that \textbf{must always travel together}:

\begin{center}
\begin{tabular}{@{}ll@{}}
\toprule
\textbf{File} & \textbf{Role}\\
\midrule
\code{trainmap.sty} & \LaTeX{} wrapper --- enables \code{\textbackslash usepackage\{trainmap\}}.\\
\code{tikzlibrarytrainmap.code.tex} & The implementation, loaded by \code{\textbackslash usetikzlibrary\{trainmap\}}.\\
\bottomrule
\end{tabular}
\end{center}

\subsection{Next to your document (quickest)}

Copy \emph{both} files into the same folder as your \code{.tex} file and
compile with \code{pdflatex}. \LaTeX{} searches the document's own directory
first, so nothing further is needed.

\subsection{Into your personal \texttt{texmf} tree (available everywhere)}

\begin{lstlisting}[language=bash,morekeywords={kpsewhich,mkdir,cp,mktexlsr,initexmf}]
# 1. Locate your personal texmf root
kpsewhich -var-value TEXMFHOME
#   Linux/macOS: usually ~/texmf
#   Windows/MiKTeX: usually C:\Users\<user>\AppData\Roaming\MiKTeX

# 2. Create the destination and copy BOTH files
mkdir -p "$(kpsewhich -var-value TEXMFHOME)/tex/latex/trainmap"
cp trainmap.sty tikzlibrarytrainmap.code.tex \
   "$(kpsewhich -var-value TEXMFHOME)/tex/latex/trainmap/"

# 3. Refresh the filename database
mktexlsr                 # TeX Live
initexmf --update-fndb   # MiKTeX (or use the MiKTeX Console)
\end{lstlisting}

\noindent After a database refresh, \code{\textbackslash usepackage\{trainmap\}}
works from any document. When the package is installed from \textsc{ctan} by
your distribution's package manager this is all handled for you.

\subsection{Loading it}

There are two equivalent ways to load the library:

\begin{lstlisting}
\usepackage{trainmap}        % as a LaTeX package
% or, if TikZ is already loaded:
\usetikzlibrary{trainmap}    % as a TikZ library
\end{lstlisting}

% =========================================================================
\section{A first map}
% =========================================================================

The following complete document draws a single Rodalies-style line. The
\code{mode=rodalies} key puts a square \code{[S1]} plate at each end; station
names are set at 45\textdegree; \code{\textbackslash addinterchange} marks a
transfer stop; and \code{\textbackslash\textbackslash} breaks a long name.

\begin{lstlisting}
\documentclass[border=10pt]{standalone}
\usepackage{trainmap}
\begin{document}
\begin{trainmap}[mode=rodalies, station step=2.0, badge color=tmS1]
  \settrunk{0/tmS1}                  % the single S1 track (orange)
  \addterminal{Pl. Espanya}{S1}      % first end -> sets the line code
  \addstation{Magoria}
  \addstation{Ildefons Cerda}
  \addinterchange{Sant Josep}        % a correspondence / transfer stop
  \addstation[label position=below]{Gornal}
  \addstation{L'Hospitalet\\de Llobregat}
  \addterminal{Cornella}{S1}         % last end -> closing [S1] plate
\end{trainmap}
\end{document}
\end{lstlisting}

\noindent It produces:

\begin{diagrambox}
\begin{trainmap}[mode=rodalies, station step=1.8, badge color=tmS1]
  \settrunk{0/tmS1}
  \addterminal{Pl. Espanya}{S1}
  \addstation{Mag\`oria}
  \addstation{Ildefons Cerd\`a}
  \addinterchange{Sant Josep}
  \addstation[label position=below]{Gornal}
  \addstation{L'Hospitalet\\de Llobregat}
  \addterminal{Cornell\`a}{S1}
\end{trainmap}
\end{diagrambox}

% =========================================================================
\section{Command reference}
% =========================================================================

\subsection{The \texttt{trainmap} environment}

\begin{lstlisting}
\begin{trainmap}[<keys>] ... \end{trainmap}
\end{lstlisting}

Wraps a \code{tikzpicture}, fixes the drawing unit to \(1\,\)cm, and resets the
internal cursor and trunk state. Any \code{/trainmap/} key (see
Section~\ref{sec:keys}) may be given in \code{<keys>} as a map-wide default. You
may freely add ordinary \TikZ{} code (\code{\textbackslash node},
\code{\textbackslash draw}, \code{\textbackslash coordinate}) inside the
environment; that is how the examples place off-trunk terminals.

\subsection{Declaring the trunk}

\begin{lstlisting}
\settrunk{<y>/<colour>, <y>/<colour>, ...}
\end{lstlisting}

Declares the parallel tracks that currently make up the common trunk. Each
entry is a vertical offset in centimetres and the colour of that track. The
tracks are drawn automatically between consecutive stations.
\code{\textbackslash settrunk} may be \textbf{called again at any point} to
change the active bundle --- for example after a line branches away it can be
dropped from the trunk, or a new line added.

\subsection{Stations}

\begin{center}\small
\renewcommand{\arraystretch}{1.35}
\begin{tabular}{@{}>{\raggedright}p{6.6cm}p{7.7cm}@{}}
\toprule
\textbf{Command} & \textbf{What it draws}\\
\midrule
\code{\textbackslash addstation[<keys>]\{<name>\}} &
  A \textbf{standard station}: a perpendicular tick crossing every track of the
  trunk, plus a rotated label.\\
\code{\textbackslash addterminal[<keys>]\{<name>\}\{<line>\}} &
  A \textbf{terminal}: a filled disc in the badge colour, the name in bold.
  In \code{fgc} mode a badge with \code{<line>} is drawn below the disc; in
  \code{rodalies} mode the code appears on the end plates instead.\\
\code{\textbackslash addinterchange[<keys>]\{<name>\}} &
  An \textbf{interchange}: a rounded capsule grouping all trunk tracks, with a
  coloured dot per line, and a bold label.\\
\bottomrule
\end{tabular}
\end{center}

Any \code{<name>} may contain \code{\textbackslash\textbackslash} to break it
across lines. Every station call \textbf{advances the cursor} by
\code{station step} centimetres before drawing, and publishes the reached
position in the macros \code{\textbackslash tmlastx} and
\code{\textbackslash tmlasty}. Capture them to anchor a branch:

\begin{lstlisting}
\addstation[name=gracia]{Gracia}
\edef\gx{\tmlastx}          % \gx now holds Gracia's x coordinate
\end{lstlisting}

Passing \code{name=<id>} additionally creates three reusable coordinates:
\code{(<id>)} at the top track, \code{(<id>-mid)} at the band centre, and
\code{(<id>-bot)} at the bottom track.

\subsection{Tracks, branches and forks}

The \code{<from>} and \code{<to>} arguments are passed \textbf{with their
parentheses}, so they accept explicit coordinates, named nodes or \code{calc}
expressions interchangeably.

\begin{center}
\renewcommand{\arraystretch}{1.3}
\begin{tabular}{@{}>{\raggedright}p{6.6cm}p{7.9cm}@{}}
\toprule
\textbf{Command} & \textbf{What it draws}\\
\midrule
\code{\textbackslash track[<o>]\{<from>\}\{<to>\}\{<c>\}} & A straight track segment.\\
\code{\textbackslash branch[<o>]\{<from>\}\{<to>\}\{<c>\}} & A gentle, near-horizontal curved branch.\\
\code{\textbackslash forkup[<o>]\{<from>\}\{<to>\}\{<c>\}} & A branch peeling \textbf{upwards} (alias \code{\textbackslash forkline}).\\
\code{\textbackslash forkdown[<o>]\{<from>\}\{<to>\}\{<c>\}} & A branch peeling \textbf{downwards}.\\
\code{\textbackslash joinline[<o>]\{<from>\}\{<to>\}\{<c>\}} & A branch \textbf{merging back} into the trunk.\\
\bottomrule
\end{tabular}
\end{center}

\noindent Here \code{<c>} is the colour and \code{<o>} an optional list of raw
\TikZ{} options appended to the \code{\textbackslash draw} (e.g.\
\code{[dashed]}).

% =========================================================================
\section{Configuration keys}\label{sec:keys}
% =========================================================================

All keys live under \code{/trainmap/}. Set them on the environment for a
map-wide default, or in a command's \code{[\,\dots\,]} to override a single
element.

\begin{center}
\renewcommand{\arraystretch}{1.2}
\begin{tabular}{@{}lll@{}}
\toprule
\textbf{Key} & \textbf{Default} & \textbf{Meaning}\\
\midrule
\code{mode}           & \code{fgc}    & \code{fgc} (all lines) or \code{rodalies} (single line).\\
\code{line code}      & (empty)       & Code on the end plates in \code{rodalies} mode.\\
\code{line color}     & \code{black}  & Fallback colour of a single track.\\
\code{track width}    & \code{2pt}    & Stroke width of a track.\\
\code{station color}  & \code{black}  & Colour of the station tick mark.\\
\code{station width}  & \code{1.8pt}  & Stroke width of the tick mark.\\
\code{terminal size}  & \code{8pt}    & Diameter of the terminal disc.\\
\code{terminal border}& \code{1.4pt}  & Border width of the terminal disc.\\
\code{badge color}    & \code{black}  & Background colour of the line badge.\\
\code{capsule width}  & \code{12pt}   & Outer width of the interchange capsule.\\
\code{capsule inner}  & \code{8pt}    & Inner (white) width of the capsule.\\
\code{capsule color}  & \code{black}  & Border colour of the capsule.\\
\code{station step}   & \code{1.6}    & Horizontal distance between stations (cm).\\
\code{track sep}      & \code{0.16}   & Suggested vertical gap between tracks (cm).\\
\code{max width}      & \code{0}      & Wrap to a new row past this x (cm); \code{0} = off.\\
\code{row sep}        & \code{2.6}    & Vertical distance between wrapped rows (cm).\\
\code{label angle}    & \code{45}     & Rotation of the station labels (degrees).\\
\code{label position} & \code{above}  & \code{above} or \code{below} the track.\\
\code{corr}           & (empty)       & List \code{CODE/colour, \dots} of correspondence chips.\\
\bottomrule
\end{tabular}
\end{center}

\subsection{Predefined colours}

The package defines the official line colours of \emph{Rodalies de Catalunya}
(\code{tmR1}, \code{tmR2}, \dots, \code{tmR17}, plus \code{tmRL1}, \code{tmRL2},
\code{tmRG1}, \code{tmRT1}, \code{tmRT2}) and \emph{FGC} (\code{tmL6},
\code{tmL7}, \code{tmL12}, \code{tmS1}, \code{tmS2}, \code{tmL8}, \code{tmR5},
\code{tmR50}, \code{tmR6}, \code{tmR60}). You may of course use any \code{xcolor}
colour, such as \code{red} or \code{blue!60!black}.

% =========================================================================
\section{Worked examples}
% =========================================================================

\subsection{Correspondence chips}

Any station accepts a \code{corr} key listing connecting lines as
\code{CODE/colour} pairs; each becomes a small coloured chip beneath the
station.

\begin{lstlisting}
\begin{trainmap}[mode=rodalies, station step=2.4, badge color=tmR7]
  \settrunk{0/tmR7}
  \addterminal[corr={R8/tmR8}]{Cerdanyola\\Universitat}{R7}
  \addstation[corr={R4/tmR4}]{Cerdanyola\\del Valles}
  \addstation[corr={R3/tmR3, R4/tmR4}]{Montcada\\Bifurcacio}
  \addterminal[corr={R3/tmR3, R4/tmR4}]{Barcelona\\Fabra i Puig}{R7}
\end{trainmap}
\end{lstlisting}

\begin{diagrambox}
\begin{trainmap}[mode=rodalies, station step=2.4, badge color=tmR7]
  \settrunk{0/tmR7}
  \addterminal[corr={R8/tmR8}]{Cerdanyola\\Universitat}{R7}
  \addstation[corr={R4/tmR4}]{Cerdanyola\\del Vall\`es}
  \addstation[corr={R3/tmR3, R4/tmR4}]{Montcada\\Bifurcaci\'o}
  \addterminal[corr={R3/tmR3, R4/tmR4}]{Barcelona\\Fabra i Puig}{R7}
\end{trainmap}
\end{diagrambox}

\subsection{Several lines and a fork (\texttt{mode=fgc})}

In the default \code{fgc} mode the whole trunk is drawn and each terminal shows
its badge. A fork is a pair of curved connectors leaving a captured station
position.

\begin{lstlisting}
\begin{trainmap}[mode=fgc, station step=2.2]
  \settrunk{0/tmS2, 0.18/tmS1}          % two parallel tracks
  \addterminal[badge color=tmS1]{Pl. Catalunya}{FGC}
  \addstation{Provenca}
  \addstation[name=sc]{Sant Cugat}
  \edef\scx{\tmlastx}
  \coordinate (terr) at (\scx+2.0, 1.0);
  \coordinate (saba) at (\scx+2.0,-0.9);
  \forkup  {(\scx,0.18)}{(terr)}{tmS1}
  \forkdown{(\scx,0.00)}{(saba)}{tmS2}
  \node[trainmap terminal, fill=tmS1] at (terr) {};
  \node[trainmap terminal, fill=tmS2] at (saba) {};
\end{trainmap}
\end{lstlisting}

\begin{diagrambox}
\begin{trainmap}[mode=fgc, station step=2.2]
  \settrunk{0/tmS2, 0.18/tmS1}
  \addterminal[badge color=tmS1]{Pl. Catalunya}{FGC}
  \addstation{Proven\c{c}a}
  \addstation[name=sc]{Sant Cugat}
  \edef\scx{\tmlastx}
  \coordinate (terr) at (\scx+2.0, 1.0);
  \coordinate (saba) at (\scx+2.0,-0.9);
  \forkup  {(\scx,0.18)}{(terr)}{tmS1}
  \forkdown{(\scx,0.00)}{(saba)}{tmS2}
  \node[trainmap terminal, fill=tmS1] at (terr) {};
  \node[trainmap label above, font=\footnotesize\bfseries]
       at ($(terr)+(0,0.16)$) {Terrassa};
  \node[trainmap badge, fill=tmS1, anchor=north, yshift=-3pt]
       at ($(terr)-(0,0.16)$) {S1};
  \node[trainmap terminal, fill=tmS2] at (saba) {};
  \node[trainmap label below, font=\footnotesize\bfseries]
       at ($(saba)-(0,0.16)$) {Sabadell};
  \node[trainmap badge, fill=tmS2, anchor=south, yshift=3pt]
       at ($(saba)+(0,0.16)$) {S2};
\end{trainmap}
\end{diagrambox}

\subsection{Long lines: the serpentine layout}

When a line has too many stations to fit on one row, enable \emph{serpentine
wrapping}: set \code{max width} (the x at which to wrap) and optionally
\code{row sep}. The cursor turns automatically at the edge, drawing a nested
U-turn, and you keep calling \code{\textbackslash addstation} as usual. See
\code{examples/rodalies\_r4.tex} in the distribution for the full R4 line folded
over three rows.

% =========================================================================
\section{Licence}
% =========================================================================

\textbf{trainmap} is distributed under the \textbf{\LaTeX{} Project Public
License}, version 1.3c or (at your option) any later version. The full text is
in the file \code{LICENSE} accompanying the distribution, and online at
\url{https://www.latex-project.org/lppl.txt}. The package has LPPL maintenance
status \emph{maintained}; the Current Maintainer is Pol Sardà Palla.

The project's source repository is at \url{https://github.com/Anty48/trainmap}.

\end{document}
