[Tex/LaTex] Rounded corners in TikZ trees.

rounded-cornerstikz-pgftrees

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}

Best Answer

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