% Copyright 2022 by Qrrbrbirlbel
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Free Documentation License.
%
\usepgflibrary{shapes.geometric,intersections}
\unless\ifcsname pgfextset\endcsname
  \input tikzext-util.tex
\fi

\pgfextset{
  superellipse x exponent/.initial=2.5,
  superellipse y exponent/.initial=2.5,
  superellipse step/.initial=4,
  superellipse exponent/.style={/pgf/ext/superellipse x exponent={#1},/pgf/ext/superellipse y exponent={#1}}}

% Evaluates the x-value of a superellipse around the center
% #1 = t (0≤t≤90)
% #2 = 2/m (x-exp)
% #3 = a (x-rad)
\pgfmathdeclarefunction{ext_superellipsex}{3}{%
  \pgfmathcos@{#1}%
  \pgfmathpow@{\pgfmathresult}{#2}%
  \pgfmathmultiply@{\pgfmathresult}{#3}}

% Evaluates the y-value of a superellipse around the center
% #1 = t (0≤t≤90)
% #2 = 2/n (y-exp)
% #3 = a (y-rad)
\pgfmathdeclarefunction{ext_superellipsey}{3}{%
  \pgfmathsin@{#1}%
  \pgfmathpow@{\pgfmathresult}{#2}%
  \pgfmathmultiply@{\pgfmathresult}{#3}}

\expandafter\let\expandafter\pgfmathextsuperellipsex\csname pgfmathext_superellipsex\endcsname
\expandafter\let\expandafter\pgfmathextsuperellipsex@\csname pgfmathext_superellipsex@\endcsname
\expandafter\let\expandafter\pgfmathextsuperellipsey\csname pgfmathext_superellipsey\endcsname
\expandafter\let\expandafter\pgfmathextsuperellipsey@\csname pgfmathext_superellipsey@\endcsname

% Evaluates the x- and y- value of superellipse around the center
% #1 = t (0≤t≤90)
% #2 = 2/m (x-exp)
% #3 = 2/n (y-exp)
% #4 = a (x-rad)
% #5 = b (y-rad)
\def\pgfextmathsuperellipseXY#1#2#3#4#5{%
  \begingroup
    \pgfmathextsuperellipsex@{#1}{#2}{#4}%
    \let\pgfmath@temp\pgfmathresult
    \pgfmathextsuperellipsey@{#1}{#3}{#5}%
    \edef\pgfmath@temp{\def\noexpand\pgfmathresultX{\pgfmath@temp}%
                       \def\noexpand\pgfmathresultY{\pgfmathresult}}%
    \expandafter
  \endgroup\pgfmath@temp}

\pgfdeclareshape{ext_superellipse}{%
  \inheritsavedanchors[from=ellipse]
  \inheritanchor[from=ellipse]{text}\inheritanchor[from=ellipse]{center}
  \inheritanchor[from=ellipse]{mid}\inheritanchor[from=ellipse]{base}
  \inheritanchor[from=ellipse]{north}\inheritanchor[from=ellipse]{south}
  \inheritanchor[from=ellipse]{west}\inheritanchor[from=ellipse]{east}
  \inheritanchor[from=ellipse]{mid west}\inheritanchor[from=ellipse]{base west}
  \inheritanchor[from=ellipse]{mid east}\inheritanchor[from=ellipse]{base east}
  \anchor{north east}{%
    \pgf@process{\radius}%
    \pgfmathpow@{.70710678118}{\xexponent}%
    \pgf@x=\pgfmathresult\pgf@x
    \pgfmathpow@{.70710678118}{\yexponent}%
    \pgf@y=\pgfmathresult\pgf@y
    \pgfpointadd{}{\centerpoint}%
  }
  \anchor{north west}{%
    \pgf@process{\radius}%
    \pgfmathpow@{.70710678118}{\xexponent}%
    \pgf@x=-\pgfmathresult\pgf@x
    \pgfmathpow@{.70710678118}{\yexponent}%
    \pgf@y=\pgfmathresult\pgf@y
    \pgfpointadd{}{\centerpoint}%
  }
  \anchor{south west}{%
    \pgf@process{\radius}%
    \pgfmathpow@{.70710678118}{\xexponent}%
    \pgf@x=-\pgfmathresult\pgf@x
    \pgfmathpow@{.70710678118}{\yexponent}%
    \pgf@y=-\pgfmathresult\pgf@y
    \pgfpointadd{}{\centerpoint}%
  }
  \anchor{south east}{%
    \pgf@process{\radius}%
    \pgfmathpow@{.70710678118}{\xexponent}%
    \pgf@x=\pgfmathresult\pgf@x
    \pgfmathpow@{.70710678118}{\yexponent}%
    \pgf@y=-\pgfmathresult\pgf@y
    \pgfpointadd{}{\centerpoint}%
  }
  \savedmacro\xexponent{%
    \pgfmathreciprocal{\pgfkeysvalueof{/pgf/ext/superellipse x exponent}}%
    \pgfmathmultiply@{\pgfmathresult}{2}%
    \let\xexponent\pgfmathresult
  }
  \savedmacro\yexponent{%
    \pgfmathreciprocal{\pgfkeysvalueof{/pgf/ext/superellipse y exponent}}%
    \pgfmathmultiply@{\pgfmathresult}{2}%
    \let\yexponent\pgfmathresult
  }
  \savedmacro\step{%
    \pgfmathtruncatemacro\step{\pgfkeysvalueof{/pgf/ext/superellipse step}}%
  }
  \backgroundpath{%
    \pgf@process{\radius}%
    \pgfmathsetmacro\xradius{\pgf@x-(\pgfkeysvalueof{/pgf/outer xsep})}%
    \pgfmathsetmacro\yradius{\pgf@y-(\pgfkeysvalueof{/pgf/outer ysep})}%
    \let\pgf@tempa\pgfutil@empty\let\pgf@tempb\pgfutil@empty
    \let\pgf@tempc\pgfutil@empty\let\pgf@tempd\pgfutil@empty
    \c@pgf@counta=\step
    \pgfutil@loop
    \ifnum\c@pgf@counta<90
      \pgfextmathsuperellipseXY{\the\c@pgf@counta}{\xexponent}{\yexponent}{\xradius}{\yradius}%
      \edef\pgf@temp{\noexpand\pgfplotstreampoint{\noexpand\pgfqpoint{\pgfmathresultX pt}{\pgfmathresultY pt}}}%
      \pgfutil@append@macrotomacro\pgf@tempa\pgf@temp
      \edef\pgf@temp{\noexpand\pgfplotstreampoint{\noexpand\pgfqpoint{-\pgfmathresultX pt}{\pgfmathresultY pt}}}%
      \tikzextutil@prefix@macrotomacro\pgf@tempb\pgf@temp
      \edef\pgf@temp{\noexpand\pgfplotstreampoint{\noexpand\pgfqpoint{-\pgfmathresultX pt}{-\pgfmathresultY pt}}}%
      \pgfutil@append@macrotomacro\pgf@tempc\pgf@temp
      \edef\pgf@temp{\noexpand\pgfplotstreampoint{\noexpand\pgfqpoint{\pgfmathresultX pt}{-\pgfmathresultY pt}}}%
      \tikzextutil@prefix@macrotomacro\pgf@tempd\pgf@temp
      \advance\c@pgf@counta by\step
    \pgfutil@repeat
    \pgftransformshift{\centerpoint}%
    \pgfplothandlerclosedcurve
    \pgfplotstreamstart
    \pgfplotstreampoint{\pgfqpoint{\xradius pt}{0pt}}% east
    \pgf@tempa
    \pgfplotstreampoint{\pgfqpoint{0pt}{\yradius pt}}% north
    \pgf@tempb
    \pgfplotstreampoint{\pgfqpoint{-\xradius pt}{0pt}}% west
    \pgf@tempc
    \pgfplotstreampoint{\pgfqpoint{0pt}{-\yradius pt}}% south
    \pgf@tempd
    \pgfplotstreamend
    \pgftransformshift{\centerpoint\pgf@x=-\pgf@x\pgf@y=-\pgf@y}
  }
  \anchorborder{%
    \pgfextract@process\externalpoint{}%
    \ifdim\pgf@x=0pt % catch special case x = 0
      \ifdim\pgf@y<0pt
        \csname pgf@anchor@ext_superellipse@south\endcsname
      \else
        \csname pgf@anchor@ext_superellipse@north\endcsname
      \fi
    \else
      \ifdim\pgf@y=0pt % catch special case y = 0
        \ifdim\pgf@x<0pt
          \csname pgf@anchor@ext_superellipse@west\endcsname
        \else
          \csname pgf@anchor@ext_superellipse@east\endcsname
        \fi
      \else % both are not zero
        % save original direction
        \pgf@xa=\pgf@x
        \pgf@ya=\pgf@y
        % make both positive, we're not looking at one quadrant
        \ifdim\pgf@xa<0pt \pgf@x=-\pgf@x\fi
        \ifdim\pgf@ya<0pt \pgf@y=-\pgf@y\fi
        % save that point again
        \pgfextract@process\externalpoint{}%
        % we need to do the calculations without any transformations
        % since we're using plots and \pgfpointborderrectangle
        \pgftransformreset
        \pgfintersectionofpaths{%
          % from center to point on rectangle that encompasses superellipse
          \pgf@relevantforpicturesizefalse
          \pgfpathmoveto{\pgfpointorigin}%
          \pgfpathlineto{\pgfpointborderrectangle{\externalpoint}{\radius}}%
        }{%
          \pgf@relevantforpicturesizefalse
          \pgf@process{\radius}
          \edef\xradius{\pgf@sys@tonumber\pgf@x}%
          \edef\yradius{\pgf@sys@tonumber\pgf@y}%
          \let\pgf@tempa\pgfutil@empty
          \c@pgf@counta=\step
          \pgfutil@loop
          \ifnum\c@pgf@counta<90
            \pgfextmathsuperellipseXY{\the\c@pgf@counta}{\xexponent}{\yexponent}{\xradius}{\yradius}%
            \edef\pgf@temp{\noexpand\pgfplotstreampoint{\noexpand\pgfqpoint{\pgfmathresultX pt}{\pgfmathresultY pt}}}%
            \pgfutil@append@macrotomacro\pgf@tempa\pgf@temp
            \advance\c@pgf@counta by\step
          \pgfutil@repeat
          % we're only using curveto since closedcurve
          % messes with our other path
          \pgfplothandlercurveto
          \pgfplotstreamstart
          \pgfplotstreampoint{\pgfqpoint{\xradius pt}{0pt}}% east
          \pgf@tempa
          \pgfplotstreampoint{\pgfqpoint{0pt}{\yradius pt}}% north
          \pgfplotstreamend
        }%
        \ifnum\pgfintersectionsolutions>0 % only if a solution was found
          \pgf@process{\pgfpointintersectionsolution{1}}%
        \else % otherwise take the border on the rectangle (close enough?)
          \pgf@process{\pgfpointborderrectangle{\externalpoint}{\radius}}%
        \fi
        \ifdim\pgf@xa<0pt \pgf@x=-\pgf@x\fi
        \ifdim\pgf@ya<0pt \pgf@y=-\pgf@y\fi
        \pgf@process{\pgfpointadd{}{\centerpoint}}%
      \fi
    \fi
  }
}
%%% Compatibility
\pgfkeysifdefined{/tikz/ext/compat/shapes/.@cmd}{}{\pgfextset{/tikz-ext/compat/add library={shapes}{pre 0.6}}}
\tikzextset{
  compat/shapes/warn/.append style=/tikz/ext/compat/shapes.superellipse/warn,
  compat/shapes/pre 0.6/.append style=/tikz/ext/compat/shapes.superellipse/pre 0.6,
  compat/shapes.superellipse/warn/.code={%
    \tikzextutil@compatwarning@key     {shapes}{pre 0.6}{/pgf/superellipse exponent}  {/pgf/ext/superellipse exponent}%
    \tikzextutil@compatwarning@valuekey{shapes}{pre 0.6}{/pgf/superellipse x exponent}{/pgf/ext/superellipse x exponent}%
    \tikzextutil@compatwarning@valuekey{shapes}{pre 0.6}{/pgf/superellipse y exponent}{/pgf/ext/superellipse y exponent}%
    \tikzextutil@compatwarning@valuekey{shapes}{pre 0.6}{/pgf/superellipse step}      {/pgf/ext/superellipse step}%
    \tikzextutil@compat@cloneshape{superellipse}{text,north,north west,north east,center,west,east,mid,mid west,mid east,base,base west,base east,south,south west,south east,center}%
    \def\tikzext@temp{\tikzextutil@compatmaybewarning{shape 'superellipse'}{'ext_superellipse'}{shapes = pre 0.6}}%
    \tikzextutil@prefix@macrotomacro\pgf@sh@s@superellipse\tikzext@temp
  },
  compat/shapes.superellipse/pre 0.6/.code={%
    \pgfkeysdef{/pgf/superellipse exponent}{\pgfkeysvalueof{/pgf/ext/superellipse exponent/.@cmd}##1\pgfeov}%
    \pgfkeysdef{/pgf/superellipse x exponent}{\pgfkeyssetvalue{/pgf/ext/superellipse x exponent}{##1}}%
    \pgfkeysdef{/pgf/superellipse y exponent}{\pgfkeyssetvalue{/pgf/ext/superellipse y exponent}{##1}}%
    \pgfkeysdef{/pgf/superellipse steps}{\pgfkeyssetvalue{/pgf/ext/superellipse steps}{##1}}%
    \pgfkeyssetvalue{/pgf/superellipse x exponent}{\pgfkeysvalueof{/pgf/ext/superellipse x exponent}}%
    \pgfkeyssetvalue{/pgf/superellipse y exponent}{\pgfkeysvalueof{/pgf/ext/superellipse y exponent}}%
    \pgfkeyssetvalue{/pgf/superellipse step}      {\pgfkeysvalueof{/pgf/ext/superellipse step}}%
    \tikzextutil@compat@cloneshape{superellipse}{text,north,north west,north east,center,west,east,mid,mid west,mid east,base,base west,base east,south,south west,south east,center}%
  },
  compat/shapes.superellipse/\pgfkeysvalueof{/tikz/ext/compat/shapes}%
}
\endinput