# TikZ: fill a percentual part of a rectangle node

I have a rectangle node, say 2cm times 3cm.
Is there a TikZ-like way to fill a percent value, say p, of that rectangle, similar as shown in the picture (for 34.5%).
So the yellow area shall be e.g. 34.5% of the rectangle area.

I have a methode here, but this way only works, if p is lesser or equal to 50%.
In cases, where p is bigger than 50% the filling should be no longer a triangle as well.
What can I do?

\documentclass[margin=5pt, varwidth]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}

\begin{tikzpicture}[]
\pgfmathsetmacro\a{2}
\pgfmathsetmacro\b{3}

\pgfmathsetmacro\p{0.345} % percent value
% (x*a  *  y*b)/2 = p*a*b  =>
\pgfmathsetmacro\x{sqrt(2*\p)}
\pgfmathsetmacro\y{sqrt(2*\p)}

% Rectangle
\node[draw, minimum width=\a cm, minimum height=\b cm](X){XYZ};
% Fill
\draw[red, fill=yellow] (X.north west) -- ($(X.north west)!\x!(X.south west)$)
-- ($(X.north west)!\x!(X.north east)$) --cycle;
% Annotation
\node[align=left, anchor=north west] at (X.north east){
a = \a cm \\
b =\b cm \\
p=\p \\
x = \x \\
y = \y
};
\end{tikzpicture}
\end{document}

• If you move the vertices outside the rectangle you can clip the yellow triangle. Commented Jun 1, 2021 at 1:09
• Mmmh, yes. But it should be the correct valued yellow area as well.
– cis
Commented Jun 1, 2021 at 1:23
• But you bring me to an idea. I could change the 'filling sides', if bigger than 50%. The question that overlasts: is there maybe a simple TikZ-like way?
– cis
Commented Jun 1, 2021 at 1:27
• You can test if p is greater than .5. Then, change the code according. Commented Jun 1, 2021 at 1:28
• \if \p > 0.5 \else \fi Commented Jun 1, 2021 at 1:30

I'd do it with clips, as Sigur suggests. This way you won't need if-then-else commands. I offer you two possibilities, the first one with the catheti proportional to the rectangle sides a and b, and the second one with an isosceles triangle (x=y).

\documentclass[border=2mm]{standalone}
\usepackage{tikz}

\def\a{2}
\def\b{3}

\begin{document}
\begin{tikzpicture}[line cap=round, line join=round]
\foreach[count=\i]\p in {0.1,0.345,0.5,0.9}
{%
% proportional triangle
\begin{scope}[shift={(\i*\a+0.5*\i,\b+0.5)}]
\node at (0.5*\a,0.5*\b) {$p=\p$};
\draw[clip] (0,0) rectangle (\a,\b);
\draw[fill=yellow,fill opacity=0.5] (2*\p*\a,\b) -| (0,\b-2*\p*\b) -- cycle;
\end{scope}

% isosceles triangle
\begin{scope}[shift={(\i*\a+0.5*\i,0)}]
\node at (0.5*\a,0.5*\b) {$p=\p$};
\draw[clip] (0,0) rectangle (\a,\b);
\draw[fill=yellow,fill opacity=0.5] (-\b,\b) |- ({-(1-\p)*\b+\p*\a},0) --++ (\b,\b) -- cycle;
\end{scope}
}
\end{tikzpicture}
\end{document}


\documentclass[margin=5pt, varwidth]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{backgrounds}
\begin{document}

\begin{tikzpicture}[]
\pgfmathsetmacro\p{0.9} % percent value

\pgfmathsetmacro\a{2}
\pgfmathsetmacro\b{3}
\pgfmathsetmacro\pShow{\p*100}
\pgfmathsetmacro\pTest{\p>0.5 ? 1 : 0}
\pgfmathsetmacro\q{\pTest==1 ? 1-\p : \p}
% (x*a  *  y*b)/2 = p*a*b  =>
\pgfmathsetmacro\x{sqrt(2*\q)}
\pgfmathsetmacro\y{\x}

\ifnum\pTest=1
\colorlet{maincolor}{yellow}
\colorlet{fillcolor}{white}
\else
\colorlet{maincolor}{white}
\colorlet{fillcolor}{yellow}
\fi

% Rectangle
\node[draw, fill=maincolor, minimum width=\a cm, minimum height=\b cm](X){};
\draw[clip] (X.south west) rectangle +(\a,\b);% else not so nice

% Fill
\ifnum\pTest=1
\coordinate[] (C) at (X.south east);
\coordinate[] (A) at ($(X.south east)!\y!(X.north east)$);
\coordinate[] (B) at  ($(X.south east)!\x!(X.south west)$);
\else
\coordinate[] (C) at (X.north west);
\coordinate[] (A) at ($(X.north west)!\y!(X.south west)$);
\coordinate[] (B) at  ($(X.north west)!\x!(X.north east)$);
\fi

\fill[fillcolor] (A) -- (B) -- (C) --cycle;
\draw[red] (A) -- (B);
\node[anchor=north west, inner sep=1pt] at (X.north west) {\pgfmathprintnumber[precision=1]{\pShow}\%};
\end{tikzpicture}
\end{document}


Works for \pgfmathsetmacro\p{0.9} as well: