14

I have this picture:

enter image description here

generated by:

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{calc, shapes, positioning}

\begin{document}
\begin{tikzpicture}
  \node (A) [draw, ellipse, minimum width=3cm, minimum height=6cm] at (0,0) {};
  \foreach \i in {0,...,3} {
    \node (A\i) [draw, circle, yshift=-0.5cm, outer sep=0.3cm] at ($(A.north)!\i/5!(A.south)$) {\i};
  }

  \node (B) [draw, ellipse, minimum width=3cm, minimum height=6cm] at (6,0) {};
  \foreach \i in {0,...,3} {
    \node (B\i) [draw, circle, yshift=-0.5cm, outer sep=0.3cm] at ($(B.north)!\i/5!(B.south)$) {\i};
  }

  \draw[rounded corners=0.5cm, thick, red] (A0.north west)--(B0.north east)--(B0.south east)--(A0.south west)--cycle;

  \draw[rounded corners=0.5cm, thick, red] (A0.north west)--(B2.north east)--(B2.south east)--(A0.south west)--cycle;

  \draw[rounded corners=0.5cm, thick, green] (A1.north west)--(B1.north east)--(B1.south east)--(A1.south west)--cycle;
  \draw[rounded corners=0.5cm, thick, green] (A1.north west)--(B3.north east)--(B3.south east)--(A1.south west)--cycle;

  \draw[rounded corners=0.5cm, thick, blue] (A3.north west)--(B1.north east)--(B1.south east)--(A3.south west)--cycle;
\end{tikzpicture}


\end{document}

Obviously, the lines do not really go nicely around the nodes. I tried to guide them around, by using (south east) -- (south west) control points, but still not really nice.

How can I make the lines flow nicely around the circles?

Thanks!

3 Answers 3

17

north, west, etc. refer to absolute directions of nodes, not to directions with respect to the line that you draw between your specified nodes. Furthermore, the radius of your rounds is too big, so even for the first (horizontal) connection the rounds don't turn out nicely. You might also want to create a tikz style to automate the process of drawing these connections.

Here is a solution using the calc library, a to path tikz style and – in line with your initial approach – rounded corners. The solution essentially creates 4 control nodes around the two specified nodes to draw a rectangle, and its corners are then rounded. The rounding can also be modified or removed, as shown in the example below. The input of the tikz style is half the width of the rectangle, which by default I set to 4mm (which is also the default round radius).

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{calc, shapes, positioning}

\tikzset{connect/.style={rounded corners=#1,
        to path= ($(\tikztostart)!-#1!(\tikztotarget)!-#1!-90:(\tikztotarget)$) -- ($(\tikztotarget)!-#1!(\tikztostart)!-#1!90:(\tikztostart)$) --
        ($(\tikztotarget)!-#1!(\tikztostart)!#1!90:(\tikztostart)$) -- ($(\tikztostart)!-#1!(\tikztotarget)!-#1!90:(\tikztotarget)$) -- cycle (\tikztotarget)
}}
\tikzset{connect/.default=4mm}

\begin{document}
\begin{tikzpicture}
  \node (A) [draw, ellipse, minimum width=3cm, minimum height=6cm] at (0,0) {};
  \foreach \i in {0,...,3} {
    \node (A\i) [draw, circle, yshift=-0.5cm, outer sep=0.3cm] at ($(A.north)!\i/5!(A.south)$) {\i};
  }

  \node (B) [draw, ellipse, minimum width=3cm, minimum height=6cm] at (6,0) {};
  \foreach \i in {0,...,3} {
    \node (B\i) [draw, circle, yshift=-0.5cm, outer sep=0.3cm] at ($(B.north)!\i/5!(B.south)$) {\i};
  }

    \draw (A0) to[connect] (B0); % default
    \draw[green] (A1) to[connect=6mm] (B1); % coloured, different size
    \draw[red,dashed,ultra thick] (A1) to[connect] (B3); % coloured,dashed,thick, etc...
    \draw[blue] (A3) to[connect,rounded corners=2mm] (B2); % different round
    \draw[blue] (A2) to[connect,sharp corners] (B3); % or sharp
    \draw[lightgray] (B1) to[connect] (A2) to[connect] (B2); % multiple at once
\end{tikzpicture}


\end{document}

result

13

You can utilize this awesome answer by Jake. It might be a bit like using a sledgehammer to crack a nut, but it works.

boundary

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{calc, shapes, positioning}

% command by Jake https://tex.stackexchange.com/a/27185/124577
\newcommand{\convexpath}[2]{
[   
    create hullnodes/.code={
        \global\edef\namelist{#1}
        \foreach [count=\counter] \nodename in \namelist {
            \global\edef\numberofnodes{\counter}
            \node at (\nodename) [draw=none,name=hullnode\counter] {};
        }
        \node at (hullnode\numberofnodes) [name=hullnode0,draw=none] {};
        \pgfmathtruncatemacro\lastnumber{\numberofnodes+1}
        \node at (hullnode1) [name=hullnode\lastnumber,draw=none] {};
    },
    create hullnodes
]
($(hullnode1)!#2!-90:(hullnode0)$)
\foreach [
    evaluate=\currentnode as \previousnode using \currentnode-1,
    evaluate=\currentnode as \nextnode using \currentnode+1
    ] \currentnode in {1,...,\numberofnodes} {
-- ($(hullnode\currentnode)!#2!-90:(hullnode\previousnode)$)
  let \p1 = ($(hullnode\currentnode)!#2!-90:(hullnode\previousnode) - (hullnode\currentnode)$),
    \n1 = {atan2(\y1,\x1)},
    \p2 = ($(hullnode\currentnode)!#2!90:(hullnode\nextnode) - (hullnode\currentnode)$),
    \n2 = {atan2(\y2,\x2)},
    \n{delta} = {-Mod(\n1-\n2,360)}
  in 
    {arc [start angle=\n1, delta angle=\n{delta}, radius=#2]}
}
-- cycle
}

\begin{document}
\begin{tikzpicture}
  \pgfmathsetlengthmacro\boundary{.4cm}
  \node (A) [draw, ellipse, minimum width=3cm, minimum height=6cm] at (0,0) {};
  \foreach \i in {0,...,3} {
    \node (A\i) [draw, circle, yshift=-0.5cm, outer sep=0.3cm] at ($(A.north)!\i/5!(A.south)$) {\i};
  }

  \node (B) [draw, ellipse, minimum width=3cm, minimum height=6cm] at (6,0) {};
  \foreach \i in {0,...,3} {
    \node (B\i) [draw, circle, yshift=-0.5cm, outer sep=0.3cm] at ($(B.north)!\i/5!(B.south)$) {\i};
  }

    \draw[thick, red] \convexpath{A0, B0}{\boundary};
    \draw[thick, red] \convexpath{A0, B2}{\boundary};
    \draw[thick, green] \convexpath{A1, B1}{\boundary};
  \draw[thick, green] \convexpath{A1, B3}{\boundary};
  \draw[thick, blue] \convexpath{A3, B1}{\boundary};
\end{tikzpicture}


\end{document}
11

I believe an easy and very generic approach (but not exactly with same results) is to play with line width, background and transparency. That way it is even possible use more elaborated paths:

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{shapes}

\pgfdeclarelayer{bg}
\pgfsetlayers{bg,main}

\tikzset{
  wrap/.style={
    line cap=round,
    #1,
    line width=21pt,
    opacity=0.3,
  },
  mynode/.style={
    draw,
    circle,
    yshift=-0.5cm,
    outer sep=0.3cm
  },
  group/.style={
    draw,
    ellipse,
    minimum width=3cm,
    minimum height=6cm
  },
}

\begin{document}
\begin{tikzpicture}
  \node (A) [group] at (0,0) {};
  \foreach \i in {0,...,3} {
    \node (A\i) [mynode] at ($(A.north)!\i/5!(A.south)$) {\i};
  }

  \node (B) [group] at (6,0) {};
  \foreach \i in {0,...,3} {
    \node (B\i) [mynode] at ($(B.north)!\i/5!(B.south)$) {\i};
  }

  \begin{pgfonlayer}{bg}
    \draw[wrap=red](A0.center)   to[out=0,in=180](B0.center);
    \draw[wrap=red](A0.center)   to[out=0,in=180](B2.center);
    \draw[wrap=green](A1.center) to[out=0,in=180](B1.center);
    \draw[wrap=green](A1.center) to[out=0,in=180](B3.center);
    \draw[wrap=blue](A3.center)  to[out=0,in=180](B1.center);
  \end{pgfonlayer}

\end{tikzpicture}

\end{document}

And we would get:

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .