Drawing ramified coverings with tikz

This uses the same in and out trick as Skillmon and puts it into a style dip, which takes as arguments the horizontal position and the depth, where the sign decides whether the dip is a dip (minus) or a bump (plus). (Let me also mention that you do not need to do something like \draw[<-] (0,0.35) -- (0,1.65) node[left, midway] {$f$};. If you name the nodes, you can just do \draw[<-] (Y) -- (X) node[left, midway] {$f$}; and TikZ will make sure to shorten the arrow without you having to compute the coordinates.)

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{positioning}
\newcounter{dip}
\begin{document}
\begin{tikzpicture}[dip/.style args={#1/#2}{/utils/exec=\stepcounter{dip},
insert path={%
coordinate (aux1) ({#1-abs(#2)},0) coordinate (aux2) ({#1+abs(#2)},0) coordinate (aux3)
(aux1) -- (aux2|-aux1) to[out=0,in=180]  
++({abs(#2)},#2) coordinate(dip-\the\value{dip}) to[out=0,in=180]  (aux3|-aux1)
}}]
\begin{scope}[thick,local bounding box=dips]
 \draw (1,2.5) [dip=5.5cm/-2.5mm]-- (7,2.5);
 \fill (dip-1) circle[radius=2pt] node[right=3pt]{$b=1$};
 \draw (1,2) [dip/.list={2.5cm/-2.5mm,5.5cm/2.5mm}] -- (7,2);
 \fill (dip-2) circle[radius=2pt] node[right=3pt]{$b=1$};
 \draw (1,1.5) [dip/.list={2.5cm/2.5mm,5.5cm/-5mm}]  -- (7,1.5);
 \fill (dip-5) circle[radius=2pt] node[above right=0pt and 5pt]{$b=2$};
 \draw (1,1) -- (7,1);
 \draw (1,0.5) [dip=5.5cm/5mm]  -- (7,0.5);
\end{scope}
\node[left=2pt of dips.west] (X) {$X$};
\draw (7,-0.5) -- (1,-0.5)  node[left=2pt] (Y) {$Y$};
\draw[<-] (Y) -- (X) node[left, midway] {$f$};
\foreach \X in {1,2}
 {
  \fill (dip-\X|-Y) circle[radius=2pt];
  \draw[dashed] (dip-\X|-Y) -- (dip-\X|-0,2.75);
 }
\end{tikzpicture}
\end{document}

enter image description here

Just for fun: a variation for Skillmon.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{positioning}
\newcounter{dip}
\begin{document}
\begin{tikzpicture}[dip/.style={/utils/exec=\stepcounter{dip},
insert path={%
 to[out=0,in=180]  
++(0.25,#1) node[bullet](dip-\the\value{dip}){}
 to[out=0,in=180] ++(0.25,-1*#1)
}},bullet/.style={circle,fill,inner sep=1.5pt}]
\begin{scope}[thick,local bounding box=dips]
 \draw (1,2.5) -- (5.25,2.5) [dip=-2.5mm]-- (7,2.5);
 \node[right=3pt of dip-1]{$b=1$};
 \draw (1,2)  -- (2.25,2) [dip=-2.5mm] -- (5.25,2) [dip=2.5mm] --(7,2);
 \node[right=3pt of dip-2]{$b=1$};
 \draw (1,1.5) -- (2.25,1.5) [dip=2.5mm] --(5.25,1.5) [dip=-5mm]  -- (7,1.5);
 \node[above right=-1.5pt and 5pt of dip-5]{$b=2$};
 \draw (1,1) -- (7,1);
 \draw (1,0.5) --(5.25,0.5) [dip=5mm] -- (7,0.5);
\end{scope}
\node[left=2pt of dips.west] (X) {$X$};
\draw (7,-0.5) -- (1,-0.5)  node[left=2pt] (Y) {$Y$};
\draw[<-] (Y) -- (X) node[left, midway] {$f$};
\foreach \X in {1,2}
 {
  \draw[dashed] (dip-\X|-Y) node[bullet]{} -- (dip-\X|-0,2.75);
 }
\end{tikzpicture}
\end{document}

enter image description here


The following is a pretty manual way to do this. I only did it for the first two lines, I hope you can apply it to the other occurrences. It uses the in and out keys of the to path construction:

\documentclass[tikz]{standalone}

\begin{document}
\begin{tikzpicture}
\draw (0,0) node {$Y$};
\draw (0,2) node {$X$};
\draw[<-] (0,0.35) -- (0,1.65) node[left, midway] {$f$};
\draw[thick] (1,2.5) -- (7,2.5) coordinate(a);
\draw[thick] (1,2) -- (7,2) coordinate(b);
\draw[thick] (1,1.5) -- (7,1.5) coordinate(c);
\draw[thick] (1,0) -- (7,0) coordinate(d);
\draw[thick]
  (a) ++(.25,-.25) coordinate(ab) to[out=180,in=0] (a)
  (ab) to[out=180,in=0] (b)
  (ab) to[out=0,in=180] ++(.25,.25)
  (ab) to[out=0,in=180] ++(.25,-.25)
  ;
\filldraw
  (ab) circle(.05)
  ;
\end{tikzpicture}
\end{document}

enter image description here


This is a proof of concept how to use parser library to define the following "language" :

  • = stay at the same level
  • u goes half up
  • U goes one up
  • d goes half down
  • D goes one down
  • x plot a (red) dot
  • . end

Here is the code.

\documentclass[tikz,border=7pt]{standalone}
\usepgfmodule{parser}
% -----------------------------
% macro that add #1 to the current path when used inside \pgfextra
\def\insertpath#1{\tikzset{insert path={#1}}}
% define the parser "sheet path"
\pgfparserdef{sheet path}{initial}{the character =}{\insertpath{ -- ++(1, 0)}}
\pgfparserdef{sheet path}{initial}{the letter u}{\insertpath{ to[out=0,in=180] ++(1, .5)}}
\pgfparserdef{sheet path}{initial}{the letter U}{\insertpath{ to[out=0,in=180] ++(1,  1)}}
\pgfparserdef{sheet path}{initial}{the letter d}{\insertpath{ to[out=0,in=180] ++(1,-.5)}}
\pgfparserdef{sheet path}{initial}{the letter D}{\insertpath{ to[out=0,in=180] ++(1, -1)}}
\pgfparserdef{sheet path}{initial}{the letter x}{\insertpath{ node[red,scale=4]{.}}}
\pgfparserdef{sheet path}{initial}{the character .}{\pgfparserswitch{final}}
% the sheet interface macro
\def\sheet#1.{\pgfextra{\pgfparserparse{sheet path}#1.}}
% -----------------------------
\begin{document}
  \tikz\draw[thick]
    (0,-1) \sheet======du=.
    (0,-2) \sheet==du==uxd=.
    (0,-3) \sheet==uxd==DU=.
    (0,-4) \sheet=========.
    (0,-5) \sheet======UxD=.;
\end{document}

enter image description here

Tags:

Tikz Pgf