6

I have this particular problem with shadings in TikZ. I want to convert quadrilateral patch plot to TikZ.

What I know - vector of vertices coordinates and connectivity list of patches.
What I do not know - order of vertices in connectivity list.

I have managed to get correct clockwise order for rectangular shapes. However in case of arbitrary shaped quadrilaterals, I have a problem to determine which particular vertex is in upper right corner, upper left corner etc.

\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{shadings}

\begin{document}
\begin{tikzpicture}
    \fill [fill,
           upper right=red, 
           upper left=blue, 
           lower left=green,
           lower right=yellow]
          (-1,-1) -- (-1,1) -- (1,1) -- (1,-1) -- cycle;
    % coordinates description was added in picture below 
\end{tikzpicture}
\end{document}

Illustration image.

I need to get something like on the image but with assigning colours to particular vertex (a, b, ...) rather then to particular corner.

Do anyone please know how to achieve this?

2
  • Do you always have oriented quadrilaterals or may the coordinates appear in random orders?
    – user121799
    Commented Jul 9, 2019 at 11:48
  • Unfortunately, connectivity list has mostly random order of vertices. Commented Jul 9, 2019 at 15:17

1 Answer 1

6

Here is a proposal and the syntax is up for negotiation. The basic points are that the shading can be rotated using a shading angle. This shading angle can be computed with calc. The syntax is something like

\path[shaded quadrilateral={(-1,-1)--(-1,1)--(1,1)--(1,-1)}];

where the first color is associated to the first vertex, the second color to the second vertex and so on. The colors are stored in pgf keys, which is illustrated by the following MWE. The restriction is that the shape needs to have 4 corners.

\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{shadings,calc}

\begin{document}
\begin{tikzpicture}[font=\sffamily,
  shaded quadrilateral/.style args={#1--#2--#3--#4}{
  insert path={($0.25*#1+0.25*#2+0.25*#3+0.25*#4$) coordinate (auxsq)
  let \p1=($#1-(auxsq)$),\n1={atan2(\y1,\x1)},
  \p2=($#2-(auxsq)$),\n2={atan2(\y2,\x2)-\n1)}
   in [/utils/exec=\pgfmathtruncatemacro{\itest}{sign(sin(\n2-\n1))}]
    \ifnum\itest=1 
            [upper right=\pgfkeysvalueof{/tikz/sq/color 1}, 
             upper left=\pgfkeysvalueof{/tikz/sq/color 2}, 
             lower left=\pgfkeysvalueof{/tikz/sq/color 3},
             lower right=\pgfkeysvalueof{/tikz/sq/color 4},shading angle=\n1-45] 
      \else
             [upper right=\pgfkeysvalueof{/tikz/sq/color 1}, 
             upper left=\pgfkeysvalueof{/tikz/sq/color 4}, 
             lower left=\pgfkeysvalueof{/tikz/sq/color 3},
             lower right=\pgfkeysvalueof{/tikz/sq/color 2},shading angle=\n1-45] 
       \fi               
      #1--#2--#3--#4-- cycle
  }},sq/.cd,color 1/.initial=red,color 2/.initial=blue,color 3/.initial=green,
  color 4/.initial=yellow]
 \begin{scope}[local bounding box=normal]
  \path[shaded quadrilateral={(-1,-1)--(-1,1)--(1,1)--(1,-1)}];
 \end{scope}
 \node[above] at (normal.north) {normal use};
 %
 \begin{scope}[xshift=3cm,local bounding box=perm]
  \path[shaded quadrilateral={(1,1)--(1,-1)--(-1,-1)--(-1,1)}];
 \end{scope}
 \node[above,align=center] at (perm.north) {permutations\\ of the vertices};
 %
 \begin{scope}[yshift=-3cm,local bounding box=cols,
  sq/.cd,color 1=magenta,color 2=red,color 3=cyan,color 4=black]
  \path[shaded quadrilateral={(1,1)--(1,-1)--(-1,-1)--(-1,1)}];
 \end{scope}
 \node[above] at (cols.north) {color change};
 %
 \begin{scope}[xshift=3cm,yshift=-3cm,local bounding box=rot]
  \path[shaded quadrilateral={(30:{sqrt(2)})--(120:{sqrt(2)})--(210:{sqrt(2)})--(300:{sqrt(2)})}];
 \end{scope}
 \node[above,align=center] at (rot.north) {rotated};
 %
 \pgfmathsetseed{2019}
 \begin{scope}[yshift=-6.5cm,local bounding box=rand1,
  sq/.cd,color 1=magenta,color 2=red,color 3=cyan,color 4=black]
  \path[shaded quadrilateral={(90*rnd:1+0.7*rnd)--(90+90*rnd:1+0.7*rnd)--(180+90*rnd:1+0.7*rnd)--(270+90*rnd:1+0.7*rnd)}];
 \end{scope}
 \node[above] at (rand1.north) {random 1};
 %
 \begin{scope}[xshift=3cm,yshift=-6.5cm,local bounding box=orientation]
  \path[shaded quadrilateral={(-1,-1)--(1,-1)--(1,1)--(-1,1)}];
 \end{scope}
 \node[above,align=center] at (orientation.north) {orientation\\ change};
\end{tikzpicture}
\end{document}

enter image description here

3
  • Thank you for answer. I will try to implement this to my code and write back about results. Commented Jul 9, 2019 at 15:16
  • I am sorry for delayed answer. After several tests, I think it looks exactly how it should look like, however I am waiting for response from my supervisor who still do not reply to me. Commented Jul 11, 2019 at 15:57
  • @HumphreyAppleby OK. If you need to keep the orientation variable, this is actually straightforward to implement. I just added that.
    – user121799
    Commented Jul 12, 2019 at 2:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .