# Using TiKz to draw cobordisms

As @Heidar says in the comments I see there is now a package for doing the cobordism diagrams (Topological Quantum Field Theory diagrams with pstricks or tikz) and I encourage others to use it as well. But my specific question is about a particular failed syntax in TikZ that I would still like to know the answer to.

I am writing my own package for drawing cobordisms. One of the features I want to implement is to have the option of coloring the cobordisms. One way of achieving that is to draw a continuous path tracing the outline of the cobordism, e.g. a pair of pants.

Let me give you an example of something I want to draw:

One way of drawing this is as follows (save the genus):

    \begin{tikzpicture}[thick]
\filldraw[fill=green!25, fill opacity=0.8]
(1,2.6) .. controls (0.75,2.6) and (0.75,3.4) .. (1,3.4) ..
controls (3,3.4) and (3,4.3) .. (6,4.3) ..
controls (3.25,4.3) and (3.25,3.5) .. (6,3.5) ..
controls (4.8,3.5) and (4.8,2.5) .. (6,2.5) ..
controls (6.25,2.5) and (6.25,1.7) .. (6,1.7) ..
controls (3,1.7) and (3,2.6) .. (1,2.6);
\draw[dashed]
(1,2.6) .. controls (1.25,2.6) and (1.25,3.4) .. (1,3.4);
\draw
(6,4.3) .. controls (5.75,4.3) and (5.75,3.5) .. (6,3.5);
\draw
(6,2.5) .. controls (5.75,2.5) and (5.75,1.7) .. (6,1.7);
\end{tikzpicture}


But this is not as general as I would like it. For one thing I would like to able to have one command that helps me draw any cobordism from n circles to m circles. My question is then:

How to get tikz to draw a continuous path tracing the outline of the cobordism?

My initial attempt was to use the \foreach command:

   \newcommand{\outline}[2]{
\pgfmathsetmacro{\in}{#1}
\pgfmathsetmacro{\out}{#2}
\pgfmathsetmacro{\intop}{2*\in - 4}
\pgfmathsetmacro{\intopp}{2*\in - 2}

% Connected piece
\draw
(0,0) .. \foreach \a in {0,2,...,\intop}{
controls (-0.25,\a) and (-0.25,\a+1) .. (0,\a+1) ..
controls (0.5,\a+1) and (0.5,\a+2) .. (0,\a+2) ..
} controls (-0.25,\intopp) and (-0.25,\intopp+1) ..
(0,\intopp+1);
}


When I try to compile it I get ! Undefined control sequence. \pgfutil@reserved@c ->\tikz@curveto@auto. I would be very grateful for any helpful suggestions.

-
This tex.stackexchange.com/questions/17031/… might be of minor relevance. –  Heidar Oct 6 '11 at 13:16
@Heidar: You beat me to it! Nonetheless, the actual question remains: why is that path going wrong? –  Loop Space Oct 6 '11 at 13:22

The answer is surprisingly simple. It transpires that the \foreach command can't come at arbitrary places in a path command. My guess, based on experiment, would be that it can only come when TikZ is looking for the next type of path, namely just after a coordinate. Once TikZ knows the type of path, it goes into a different mode where it looks just for those things it knows can be part of that path.

As a simpler example, try:

\draw (0,0) -- \foreach \a in {0,1,...,10} {(\a,0) -- (\a,1) -- } (11,0);


Here, TikZ is looking for a coordinate when it encounters the \foreach, so it complains. The simplest solution is to switch things around a little to ensure that the \foreach comes when TikZ is expecting it. In the baby example, this would be:

\draw (0,0) \foreach \a in {0,1,...,10} { -- (\a,0) -- (\a,1) } -- (11,0);


To a human, these are the same, but the second compiles (and gives a nice sawtooth wave) because TikZ encounters the \foreach when it is able to cope with it.

In your example, you would have:

\pgfmathsetmacro{\in}{#1}
\pgfmathsetmacro{\out}{#2}
\pgfmathsetmacro{\intop}{2*\in - 4}
\pgfmathsetmacro{\intopp}{2*\in - 2}

% Connected piece
\draw
(0,0) \foreach \a in {0,2,...,\intop}{
.. controls (-0.25,\a) and (-0.25,\a+1) .. (0,\a+1) ..
controls (0.5,\a+1) and (0.5,\a+2) .. (0,\a+2)
} .. controls (-0.25,\intopp) and (-0.25,\intopp+1) ..
(0,\intopp+1);


So I've shifted the first .. inside the \foreach, and the last .. that was inside the loop outside again. This now works.

Thinking about this a bit more, I suspect it might be an expansion thing. TikZ is happy to expand a macro to see if it will give a coordinate, so  -- \foreach ... {(coordinate)} would work if \foreach were expandable. Since (if I remember aright) it isn't, it doesn't. –  Loop Space Oct 6 '11 at 16:48
@AndrewStacey \foreach cannot be expandable even in principle, since it requires an assignment of your variable \a to each value in the list. Any expandable method would require you to define a function \def\mycoord#1{(#1,0)--(#1,1)--} then feed integers from 0 to 10 to \mycoord (that could be done rather easily expandably). –  Bruno Le Floch Oct 7 '11 at 22:10