28

When I use TikZ tree with nodes with rounded corners, the connecting lines do not touch the nodes (near corners) but end where would rectangle end. Is there an easy way around it?

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture} [sibling distance=100] 
  \node[rectangle, draw, rounded corners = 3]{ }
  child { node { } }
  child { node { } }
  ;
\end{tikzpicture}
\end{document}
2
  • 4
    As far as I'm aware it should work correctly. Could you provide an example?
    – Caramdir
    Aug 8, 2010 at 18:30
  • 2
    I thought you were using rounded rectangle.
    – Caramdir
    Aug 9, 2010 at 12:18

3 Answers 3

40
+300

As already mentioned, the only real solution is to define a new shape, with correct border anchors. So, here it is: rectangle with rounded corners. The radius of the corner is controllable by /pgf/rectangle corner radius.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{intersections}

\begin{document}

\makeatletter

\pgfkeys{/pgf/.cd,
  rectangle corner radius/.initial=3pt
}
\newif\ifpgf@rectanglewrc@donecorner@
\def\pgf@rectanglewithroundedcorners@docorner#1#2#3#4{%
  \edef\pgf@marshal{%
    \noexpand\pgfintersectionofpaths
      {%
        \noexpand\pgfpathmoveto{\noexpand\pgfpoint{\the\pgf@xa}{\the\pgf@ya}}%
        \noexpand\pgfpathlineto{\noexpand\pgfpoint{\the\pgf@x}{\the\pgf@y}}%
      }%
      {%
        \noexpand\pgfpathmoveto{\noexpand\pgfpointadd
          {\noexpand\pgfpoint{\the\pgf@xc}{\the\pgf@yc}}%
          {\noexpand\pgfpoint{#1}{#2}}}%
        \noexpand\pgfpatharc{#3}{#4}{\cornerradius}%
      }%
    }%
  \pgf@process{\pgf@marshal\pgfpointintersectionsolution{1}}%
  \pgf@process{\pgftransforminvert\pgfpointtransformed{}}%
  \pgf@rectanglewrc@donecorner@true
}
\pgfdeclareshape{rectangle with rounded corners}
{
  \inheritsavedanchors[from=rectangle] % this is nearly a rectangle
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{north west}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{mid}
  \inheritanchor[from=rectangle]{mid west}
  \inheritanchor[from=rectangle]{mid east}
  \inheritanchor[from=rectangle]{base}
  \inheritanchor[from=rectangle]{base west}
  \inheritanchor[from=rectangle]{base east}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchor[from=rectangle]{south east}

  \savedmacro\cornerradius{%
    \edef\cornerradius{\pgfkeysvalueof{/pgf/rectangle corner radius}}%
  }

  \backgroundpath{%
    \northeast\advance\pgf@y-\cornerradius\relax
    \pgfpathmoveto{}%
    \pgfpatharc{0}{90}{\cornerradius}%
    \northeast\pgf@ya=\pgf@y\southwest\advance\pgf@x\cornerradius\relax\pgf@y=\pgf@ya
    \pgfpathlineto{}%
    \pgfpatharc{90}{180}{\cornerradius}%
    \southwest\advance\pgf@y\cornerradius\relax
    \pgfpathlineto{}%
    \pgfpatharc{180}{270}{\cornerradius}%
    \northeast\pgf@xa=\pgf@x\advance\pgf@xa-\cornerradius\southwest\pgf@x=\pgf@xa
    \pgfpathlineto{}%
    \pgfpatharc{270}{360}{\cornerradius}%
    \northeast\advance\pgf@y-\cornerradius\relax
    \pgfpathlineto{}%
  }

  \anchor{before north east}{\northeast\advance\pgf@y-\cornerradius}
  \anchor{after north east}{\northeast\advance\pgf@x-\cornerradius}
  \anchor{before north west}{\southwest\pgf@xa=\pgf@x\advance\pgf@xa\cornerradius
    \northeast\pgf@x=\pgf@xa}
  \anchor{after north west}{\northeast\pgf@ya=\pgf@y\advance\pgf@ya-\cornerradius
    \southwest\pgf@y=\pgf@ya}
  \anchor{before south west}{\southwest\advance\pgf@y\cornerradius}
  \anchor{after south west}{\southwest\advance\pgf@x\cornerradius}
  \anchor{before south east}{\northeast\pgf@xa=\pgf@x\advance\pgf@xa-\cornerradius
    \southwest\pgf@x=\pgf@xa}
  \anchor{after south east}{\southwest\pgf@ya=\pgf@y\advance\pgf@ya\cornerradius
    \northeast\pgf@y=\pgf@ya}

  \anchorborder{%
    \pgf@xb=\pgf@x% xb/yb is target
    \pgf@yb=\pgf@y%
    \southwest%
    \pgf@xa=\pgf@x% xa/ya is se
    \pgf@ya=\pgf@y%
    \northeast%
    \advance\pgf@x by-\pgf@xa%
    \advance\pgf@y by-\pgf@ya%
    \pgf@xc=.5\pgf@x% x/y is half width/height
    \pgf@yc=.5\pgf@y%
    \advance\pgf@xa by\pgf@xc% xa/ya becomes center
    \advance\pgf@ya by\pgf@yc%
    \edef\pgf@marshal{%
      \noexpand\pgfpointborderrectangle
      {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}
      {\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
    }%
    \pgf@process{\pgf@marshal}%
    \advance\pgf@x by\pgf@xa% 
    \advance\pgf@y by\pgf@ya%
    \pgfextract@process\borderpoint{}%
    %
    \pgf@rectanglewrc@donecorner@false
    %
    % do southwest corner
    \southwest\pgf@xc=\pgf@x\pgf@yc=\pgf@y
    \advance\pgf@xc\cornerradius\relax\advance\pgf@yc\cornerradius\relax 
    \borderpoint
    \ifdim\pgf@x<\pgf@xc\relax\ifdim\pgf@y<\pgf@yc\relax
      \pgf@rectanglewithroundedcorners@docorner{-\cornerradius}{0pt}{180}{270}%
    \fi\fi
    %
    % do southeast corner
    \ifpgf@rectanglewrc@donecorner@\else
      \southwest\pgf@yc=\pgf@y\relax\northeast\pgf@xc=\pgf@x\relax
      \advance\pgf@xc-\cornerradius\relax\advance\pgf@yc\cornerradius\relax
      \borderpoint
      \ifdim\pgf@x>\pgf@xc\relax\ifdim\pgf@y<\pgf@yc\relax
       \pgf@rectanglewithroundedcorners@docorner{0pt}{-\cornerradius}{270}{360}%
      \fi\fi
    \fi
    %
    % do northeast corner
    \ifpgf@rectanglewrc@donecorner@\else
      \northeast\pgf@xc=\pgf@x\relax\pgf@yc=\pgf@y\relax
      \advance\pgf@xc-\cornerradius\relax\advance\pgf@yc-\cornerradius\relax
      \borderpoint
      \ifdim\pgf@x>\pgf@xc\relax\ifdim\pgf@y>\pgf@yc\relax
       \pgf@rectanglewithroundedcorners@docorner{\cornerradius}{0pt}{0}{90}%
      \fi\fi
    \fi
    %
    % do northwest corner
    \ifpgf@rectanglewrc@donecorner@\else
      \northeast\pgf@yc=\pgf@y\relax\southwest\pgf@xc=\pgf@x\relax
      \advance\pgf@xc\cornerradius\relax\advance\pgf@yc-\cornerradius\relax
      \borderpoint
      \ifdim\pgf@x<\pgf@xc\relax\ifdim\pgf@y>\pgf@yc\relax
       \pgf@rectanglewithroundedcorners@docorner{0pt}{\cornerradius}{90}{180}%
      \fi\fi
    \fi
  }
}

\makeatother

\begin{tikzpicture}
  \draw node(rc)[
    rectangle with rounded corners,draw,rectangle corner radius=10pt,align=center]
    {\large rectangle with rounded corners\\\large rectangle with rounded corners\\\large rectangle with rounded corners};
  \fill[red,every node/.style={font=\tiny}]
        \foreach \d/\p in {before north east/right,after north east/above,
                           before north west/above,after north west/left,
                           before south west/left,after south west/below,
                           before south east/right,after south east/right}
                       { (rc.\d) circle(1pt) node[\p]{\d} };
  \draw[blue,draw opacity=0.3]\foreach\a in {0,...,360} {(rc)--+(\a:5cm)};
\end{tikzpicture}

\end{document}

All border anchors

5
  • 1
    Brilliant! And I love the way the image shimmers when I scroll the page (screen effect, I know, but nonetheless). How important is the intersections library? Would it be tedious-but-standard to replace it, or is it really quite crucial? Aug 24, 2012 at 11:26
  • 1
    tnx;) intersections is quite crucial... computing the intersection of a line a a circle segment is not exactly trivial (at least for me... and even more so in TeX). Aug 24, 2012 at 11:32
  • Great! That works really good and is, as you said, the only proper solution to this!
    – boothby81
    Aug 25, 2012 at 13:46
  • THANKS to Andrew for raising interest in this question by adding the bounty (I had exactly the same problem and asked for help in the chat) and of course to Saso for coding this solution!
    – boothby81
    Aug 25, 2012 at 13:56
  • +1, great solution, but why were the south east etc. anchors not moved accordingly? Jul 7, 2016 at 12:21
14

It looks a bit different, but you could use the rounded rectangle shape:

\usetikzlibrary{shapes.misc}

\begin{tikzpicture} [sibling distance=100] 
  \node[rounded rectangle, draw]{ }
  child { node { } }
  child { node { } }
  ;
\end{tikzpicture}

This gives

tree with rounded corners

Note that the sides are now complete half-circles, not two quarter-circles joined by a line.

6
  • Thanks, I didnt know rounded rectangle exists. Why do we need rounded corners? ... Maybe to use in paths? Aug 9, 2010 at 17:26
  • Yes, rounded corners draws paths with rounded corners. So In your example, the path around the node was drawn with rounded corners, but the shape of the node was not modified.
    – Caramdir
    Aug 9, 2010 at 18:09
  • 1
    "doesn't work" as in "does not compile" or as in "i do not like how it looks"? In the first case what is the error? In the second: As far as I know there is no easy way, but my knowledge of TikZ's capabilities is not complete.
    – Caramdir
    Aug 9, 2010 at 18:52
  • 1
    I do not like how it looks. I have very vertical nodes so the roundness doesn't look well (even if I set round rectangle=45). It just doesn't look good. I didn't found "rounded corners rectangle" in shapes library, also I don't know how to move anchors towards rounded paths ... Aug 10, 2010 at 11:37
  • 1
    Sorry, in that case I cannot really help you (other than what was already suggested on SO: draw the tree with empty named nodes and then overdraw with the nodes). The only "clean" solution can think of involves defining a "rounded corners rectangle" shape and that is beyond my knowledge of TikZ. Maybe add a feature request for pgf/TikZ: sourceforge.net/tracker/?group_id=142562&atid=752795
    – Caramdir
    Aug 10, 2010 at 15:28
7

If you just want the branches to connect directly to the nodes you can shorten them by a small negative amount:

\documentclass[border=4pt,png]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture} [sibling distance=100,shorten >=-1pt,shorten <=-1pt] 
  \node[rectangle, draw, rounded corners = 3]{ }
  child { node[rectangle, draw, rounded corners = 3] { } }
  child { node[rectangle, draw, rounded corners = 3] { } }
  ;
\end{tikzpicture}

\end{document}

output of code

1
  • 1
    This is a fast and simple way to achieve the desired effect. However, if you have several nodes in various relations to each other or with different values of rounded corners it requires a lot of manual work.
    – boothby81
    Aug 25, 2012 at 13:43

You must log in to answer this question.

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