Regular polygon VS circle shapes in TikZ

Using through library of Tikz.

\documentclass[tikz, border=1mm]{standalone}
\usetikzlibrary{shapes.geometric,through}

\begin{document}
    \begin{tikzpicture}[every node/.style={draw, inner sep=0}]
        \node[regular polygon,regular polygon sides=4] (a) {XX};
        \node (b) [draw,blue, circle through=(a.north)] at (a.center) {XX};
        \node[circle] (c) {XX};
         \foreach \a in {north,south,east,west,north east,south east,north west,south west}{
            \fill[red] (a.\a) circle(0.5pt);
            \fill[yellow] (b.\a) circle(0.25pt);
            \fill[orange] (c.\a) circle(0.25pt);
        }

    \end{tikzpicture}
\end{document}

enter image description here


The "inner circle" in shapes.geometric has a radius that is half of the longest side of the content box plus the inner sep, and multiplied by 1.4142136, which is approximately sqrt(2). So to obtain a circle shape that has this behavior you can define a new shape, let's say Circle (with capital C) that is a slight modification of the existing ellipse shape.

\documentclass[tikz, border=7pt, convert={density=4200}]{standalone}
\usetikzlibrary{shapes.geometric}
\makeatletter
\pgfdeclareshape{Circle}
%
% Draws a circle around the text
% (based on the original ellipse shape)
%
{%
  \savedanchor\centerpoint{%
    \pgf@x=.5\wd\pgfnodeparttextbox%
    \pgf@y=.5\ht\pgfnodeparttextbox%
    \advance\pgf@y by-.5\dp\pgfnodeparttextbox%
  }%
  \savedanchor\radius{%
    %
    % Calculate ``height radius''
    %
    \pgf@y=.5\ht\pgfnodeparttextbox%
    \advance\pgf@y by.5\dp\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/inner ysep}}%
    \advance\pgf@y by\pgf@yb%
    %
    % Calculate ``width radius''
    %
    \pgf@x=.5\wd\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/inner xsep}}%
    \advance\pgf@x by\pgf@xb%
    %
    % Adjust
    %
    % ==============================
    % added to ellipse shape to become circle
    \ifdim\pgf@y>\pgf@x%
            \pgf@x\pgf@y%
    \else%
        \pgf@y\pgf@x%
    \fi%
    % ==============================
    \pgf@x=1.4142136\pgf@x%
    \pgf@y=1.4142136\pgf@y%
    %
    % Adjust height, if necessary
    %
    \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/minimum height}}%
    \ifdim\pgf@y<.5\pgf@yc%
      \pgf@y=.5\pgf@yc%
    \fi%
    %
    % Adjust width, if necessary
    %
    \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/minimum width}}%
    \ifdim\pgf@x<.5\pgf@xc%
      \pgf@x=.5\pgf@xc%
    \fi%
    %
    % Add outer sep
    %
    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
    \advance\pgf@x by\pgf@xb%
    \advance\pgf@y by\pgf@yb%
  }%

  %
  % Anchors
  %
  \anchor{center}{\centerpoint}%
  \anchor{mid}{\centerpoint\pgfmathsetlength\pgf@y{.5ex}}%
  \anchor{base}{\centerpoint\pgf@y=0pt}%
  \anchor{north}
  {
    \pgf@process{\radius}
    \pgf@ya=\pgf@y%
    \pgf@process{\centerpoint}
    \advance\pgf@y by\pgf@ya
  }%
  \anchor{south}
  {
    \pgf@process{\radius}
    \pgf@ya=\pgf@y%
    \pgf@process{\centerpoint}
    \advance\pgf@y by-\pgf@ya
  }%
  \anchor{west}
  {
    \pgf@process{\radius}
    \pgf@xa=\pgf@x%
    \pgf@process{\centerpoint}
    \advance\pgf@x by-\pgf@xa
  }%
  \anchor{mid west}
  {%
    \pgf@process{\radius}
    \pgf@xa=\pgf@x%
    \pgf@process{\centerpoint}
    \advance\pgf@x by-\pgf@xa%
    \pgfmathsetlength\pgf@y{.5ex}
  }%
  \anchor{base west}
  {%
    \pgf@process{\radius}
    \pgf@xa=\pgf@x%
    \pgf@process{\centerpoint}
    \advance\pgf@x by-\pgf@xa%
    \pgf@y=0pt
  }%
  \anchor{north west}
  {
    \pgf@process{\radius}
    \pgf@xa=\pgf@x%
    \pgf@ya=\pgf@y%
    \pgf@process{\centerpoint}
    \advance\pgf@x by-0.707107\pgf@xa
    \advance\pgf@y by0.707107\pgf@ya
  }%
  \anchor{south west}
  {
    \pgf@process{\radius}
    \pgf@xa=\pgf@x%
    \pgf@ya=\pgf@y%
    \pgf@process{\centerpoint}
    \advance\pgf@x by-0.707107\pgf@xa
    \advance\pgf@y by-0.707107\pgf@ya
  }%
  \anchor{east}
  {%
    \pgf@process{\radius}
    \pgf@xa=\pgf@x%
    \pgf@process{\centerpoint}
    \advance\pgf@x by\pgf@xa
  }%
  \anchor{mid east}
  {%
    \pgf@process{\radius}
    \pgf@xa=\pgf@x%
    \pgf@process{\centerpoint}
    \advance\pgf@x by\pgf@xa%
    \pgfmathsetlength\pgf@y{.5ex}
  }%
  \anchor{base east}
  {%
    \pgf@process{\radius}
    \pgf@xa=\pgf@x%
    \pgf@process{\centerpoint}
    \advance\pgf@x by\pgf@xa%
    \pgf@y=0pt
  }%
  \anchor{north east}
  {
    \pgf@process{\radius}
    \pgf@xa=\pgf@x%
    \pgf@ya=\pgf@y%
    \pgf@process{\centerpoint}
    \advance\pgf@x by0.707107\pgf@xa
    \advance\pgf@y by0.707107\pgf@ya
  }%
  \anchor{south east}
  {
    \pgf@process{\radius}
    \pgf@xa=\pgf@x%
    \pgf@ya=\pgf@y%
    \pgf@process{\centerpoint}
    \advance\pgf@x by0.707107\pgf@xa
    \advance\pgf@y by-0.707107\pgf@ya
  }%
  \anchorborder{
    \edef\pgf@marshal{%
      \noexpand\pgfpointborderellipse
      {\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}
      {\noexpand\radius}%
    }%
    \pgf@marshal%
    \pgf@xa=\pgf@x%
    \pgf@ya=\pgf@y%
    \centerpoint%
    \advance\pgf@x by\pgf@xa%
    \advance\pgf@y by\pgf@ya%
  }%

  %
  % Background path
  %
  \backgroundpath
  {
    \pgf@process{\radius}%
    \pgfutil@tempdima=\pgf@x%
    \pgfutil@tempdimb=\pgf@y%
    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
    \advance\pgfutil@tempdima by-\pgf@xb%
    \advance\pgfutil@tempdimb by-\pgf@yb%
    \pgfpathellipse{\centerpoint}{\pgfqpoint{\pgfutil@tempdima}{0pt}}{\pgfqpoint{0pt}{\pgfutil@tempdimb}}%
  }%
}%
\makeatother

\begin{document}
    \begin{tikzpicture}[nodes={draw, inner sep=0}]
        \node[regular polygon,regular polygon sides=4] (a) {XX};
        \node[Circle, blue] (b) {XX};
        \node[circle] (c) {XX};
        \foreach \a in {north,south,east,west,north east,south east,north west,south west}{
            \fill[red] (a.\a) circle(0.5pt);
            \fill[yellow] (b.\a) circle(0.25pt);
            \fill[orange] (c.\a) circle(0.25pt);
        }
    \end{tikzpicture}
\end{document}

enter image description here


Addendum:

If you want to go the other way and create a circumscribed polygon around the standard circle node style, that do not use low level tricks, you can define circumscribed polygon that use append after command to add well sized regular polygon. This is not a robust code for meany reasons, it is just a proof of concept :

\documentclass[tikz,border=7pt,convert={density=4200}]{standalone}
\usetikzlibrary{calc,shapes.geometric}

% don't tell me to not use tikzstyle ;)
\tikzstyle{circumscribed polygon}[draw]=[
  circle,draw=none,fill=none,shade=none,
  append after command={
    let \p1=($(\tikzlastnode.west)-(\tikzlastnode.east)$),
        \n1 = {(veclen(\p1)-\pgflinewidth)/2.828427} % 2*sqrt(2) = 2.8284271247461903
    in
    (\tikzlastnode.center) node[regular polygon,  inner sep=\n1, #1]{}
  }
]
\begin{document}
  \begin{tikzpicture}[inner sep=1mm]
    \foreach~in {3,...,7}
      \node[circumscribed polygon={draw=blue!~0!green,regular polygon sides=~}] {XX};
    \node[circle,draw=red] {XX};
  \end{tikzpicture}
\end{document}

enter image description here

Tags:

Tikz Pgf