summaryrefslogtreecommitdiff
path: root/graphics/pgf/contrib/tikz-ext/pgflibraryext.shapes.superellipse.code.tex
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/pgf/contrib/tikz-ext/pgflibraryext.shapes.superellipse.code.tex')
-rw-r--r--graphics/pgf/contrib/tikz-ext/pgflibraryext.shapes.superellipse.code.tex198
1 files changed, 198 insertions, 0 deletions
diff --git a/graphics/pgf/contrib/tikz-ext/pgflibraryext.shapes.superellipse.code.tex b/graphics/pgf/contrib/tikz-ext/pgflibraryext.shapes.superellipse.code.tex
new file mode 100644
index 0000000000..9a89b5a8a6
--- /dev/null
+++ b/graphics/pgf/contrib/tikz-ext/pgflibraryext.shapes.superellipse.code.tex
@@ -0,0 +1,198 @@
+% 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}
+\pgfset{
+ superellipse x exponent/.initial=2.5,
+ superellipse y exponent/.initial=2.5,
+ superellipse step/.initial=4,
+ superellipse exponent/.style={/pgf/superellipse x exponent={#1},/pgf/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{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{superellipsey}{3}{%
+ \pgfmathsin@{#1}%
+ \pgfmathpow@{\pgfmathresult}{#2}%
+ \pgfmathmultiply@{\pgfmathresult}{#3}}
+
+% 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\pgfmathsuperellipseXY#1#2#3#4#5{%
+ \begingroup
+ \pgfmathsuperellipsex@{#1}{#2}{#4}%
+ \let\pgfmath@temp\pgfmathresult
+ \pgfmathsuperellipsey@{#1}{#3}{#5}%
+ \edef\pgfmath@temp{\def\noexpand\pgfmathresultX{\pgfmath@temp}%
+ \def\noexpand\pgfmathresultY{\pgfmathresult}}%
+ \expandafter
+ \endgroup\pgfmath@temp}
+
+\pgfdeclareshape{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/superellipse x exponent}}%
+ \pgfmathmultiply@{\pgfmathresult}{2}%
+ \let\xexponent\pgfmathresult
+ }
+ \savedmacro\yexponent{%
+ \pgfmathreciprocal{\pgfkeysvalueof{/pgf/superellipse y exponent}}%
+ \pgfmathmultiply@{\pgfmathresult}{2}%
+ \let\yexponent\pgfmathresult
+ }
+ \savedmacro\step{%
+ \pgfmathtruncatemacro\step{\pgfkeysvalueof{/pgf/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
+ \pgfmathsuperellipseXY{\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}}}%
+ \pgfutil@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}}}%
+ \pgfutil@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 \pgf@anchor@superellipse@south\else\pgf@anchor@superellipse@north\fi
+ \else
+ \ifdim\pgf@y=0pt % catch special case y = 0
+ \ifdim\pgf@x<0pt \pgf@anchor@superellipse@west\else\pgf@anchor@superellipse@east\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
+ \pgfmathsuperellipseXY{\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
+ }
+}
+\def\pgfutil@prefix@macrotomacro#1#2{%
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter%
+ #1\expandafter\expandafter\expandafter{\expandafter#2#1}}
+\endinput