# How to rotate around arbitrary axis in XYZ coordinate system

I am drawing the cartesian coordinate system in XYZ coordinate system and would like to illustrate a point in the 3d space by drawing the projections on each plane. A simple version would be as follows: obtained with this code:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

%: isometric  South West (-150): Y , East : X , North : Z
\tikzset{isometricYXZ/.style={x={(1cm,0cm)}, y={(-1.299cm,-0.75cm)}, z={(0cm,1cm)}}}

\begin{document}
\begin{tikzpicture}[inner sep=0.2cm]
\def \x{2}
\def \y{2}
\def \z{2}

\begin{scope}[isometricYXZ]
% the grid
\begin{scope}[color=gray!50, thin]
\end{scope}

\draw[-latex, ultra thick, color=blue] (0,0,0) -- (4,0,0) node[anchor=west] {X};%
\draw[-latex, ultra thick, color=red] (0,0,0) -- (0,4,0) node[anchor=north] {Y};%
\draw[-latex, ultra thick, color=green] (0,0,0) -- (0,0,4) node[anchor=east] {Z};%

\fill[color=magenta, opacity=0.2] (0,0,0) -- (\x,0,0) -- (\x,\y,0) -- (0,\y,0) -- cycle; %
\fill[color=yellow, opacity=0.2] (0,0,0) -- (0,0,\z) -- (0,\y,\z) -- (0,\y,0) -- cycle; %
\fill[color=cyan, opacity=0.2] (0,0,0) -- (\x,0,0) -- (\x,0,\z) -- (0,0,\z) -- cycle;

\draw[color=gray, thick]%
(0,\y,\z) -- (\x,\y,\z) -- (\x,\y,0) (\x,\y,\z) -- (\x,0,\z);%
\end{scope}

\shade[ball color=yellow] ($\y*(-1.299cm,-0.75cm)+(\x,\z)$) circle (0.1);%
\end{tikzpicture}
\end{document}


To make the drawing nicer, I want to shade these projections, what I managed to do for the XZ plane: This is the code for the shaded part:

\begin{scope}[isometricYXZ]
\def \h{{0.5*sqrt(\x*\x + \z*\z)}}
\clip (0,0,0) -- (\x,0,0) -- (\x,0,\z) -- (0,0,\z) -- cycle; %
\begin{scope}[transform canvas={shift={(\x/2,0,\z/2)}, rotate=45}]
\fill[top color=green!30, bottom color=blue!30]
(-\x,0,-\h) -- (\x,0,-\h) -- (\x,0,\h) -- (-\x,0,\h) -- cycle;
\end{scope}
\end{scope}


Now, when I am trying to do the same for the other planes, it does not work, as it seems that rotate always rotates as usually in the 2-dimensional case (in my case around the Y axis, in the XZ plane). This is the code:

\begin{scope}
\def \h{{0.5*sqrt(\x*\x + \y*\y)}}
\clip (0,0,0) -- (\x,0,0) -- (\x,\y,0) -- (0,\y,0) -- cycle; %
\begin{scope}[transform canvas={shift={(\x/2,\y/2,0)}, rotate=-45}]
\fill[top color=blue!30, bottom color=red!30]
(-\x,-\h,0) -- (\x,-\h,0) -- (\x,\h,0) -- (-\x,\h,0) -- cycle;
\end{scope}
\end{scope}


And the result: So, my question is whether it is possible and if yes, then how to tell Tikz to rotate around an arbitrary axis? Or in my case, in the XY and YZ planes?

A solution with fading which does not require rotating would be also fine.

In the end, I guess I could translate everything to 2d and get what I want, but may be there is a cleaner solution to this.

In my opinion, you are using a too powerful tool for a relatively simpler task. The canvas transformations simply don't care about any other settings like bounding boxes or any other high level constraints. They just happen. Instead, you can modify the default vertical shadings such that they obey the shading angle option. I've randomly rotated the shading below with 45, 120, and -45 degrees hoping that it was the reason for the question :)

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
\tikzoption{top color}{%
\pgfutil@colorlet{tikz@axis@top}{#1}%
\pgfutil@colorlet{tikz@axis@middle}{tikz@axis@top!50!tikz@axis@bottom}%
\tikzoption{bottom color}{%
\pgfutil@colorlet{tikz@axis@bottom}{#1}%
\pgfutil@colorlet{tikz@axis@middle}{tikz@axis@top!50!tikz@axis@bottom}%
\tikzoption{middle color}{%
\pgfutil@colorlet{tikz@axis@middle}{#1}%
\makeatother

%: isometric  South West (-150): Y , East : X , North : Z
\tikzset{isometricYXZ/.style={x={(1cm,0cm)}, y={(-1.299cm,-0.75cm)}, z={(0cm,1cm)}}}

\begin{document}
\begin{tikzpicture}[inner sep=0.2cm]
\def \x{2}
\def \y{2}
\def \z{2}

\begin{scope}[isometricYXZ]
% the grid
\begin{scope}[color=gray!50, thin]
\end{scope}

\draw[-latex, ultra thick, color=blue] (0,0,0) -- (4,0,0) node[anchor=west] {X};%
\draw[-latex, ultra thick, color=red] (0,0,0) -- (0,4,0) node[anchor=north] {Y};%
\draw[-latex, ultra thick, color=green] (0,0,0) -- (0,0,4) node[anchor=east] {Z};%

\fill[shading angle=45, top color=green!30, bottom color=blue!30] (0,0,0) -- (\x,0,0) -- (\x,\y,0) -- (0,\y,0) -- cycle; %
\fill[shading angle=-45, top color=green!30, bottom color=blue!30] (0,0,0) -- (0,0,\z) -- (0,\y,\z) -- (0,\y,0) -- cycle; %
\fill[shading angle=120, top color=green!30, bottom color=blue!30] (0,0,0) -- (\x,0,0) -- (\x,0,\z) -- (0,0,\z) -- cycle;

\draw[color=gray, thick]%
(0,\y,\z) -- (\x,\y,\z) -- (\x,\y,0) (\x,\y,\z) -- (\x,0,\z);%
\end{scope}

\shade[ball color=yellow] ($\y*(-1.299cm,-0.75cm)+(\x,\z)$) circle (0.1);%
\end{tikzpicture}
\end{document} I guess the reason for the shading angle disabled (set to zero) originally is to get the other transformations invalid at the time of shading declaration. You can make these changes local if you have other TikZ pictures that use these options.

• Thanks! it works! What I actually needed was this shading: \fill[shading angle=45, top color=green!30, bottom color=blue!30] (0,0,0) -- (\x,0,0) -- (\x,0,\z) -- (0,0,\z) -- cycle; \fill[shading angle=-60, top color=blue!30, bottom color=red!30] (0,0,0) -- (\x,0,0) -- (\x,\y,0) -- (0,\y,0) -- cycle; \fill[shading angle=-30, top color=green!30, bottom color=red!30] (0,0,0) -- (0,0,\z) -- (0,\y,\z) -- (0,\y,0) -- cycle; But why when I try to make opacity=0.3, the effect is not something transparent, but something dark? Is it because of the shading? Should one use fading here? Jul 8, 2013 at 7:49
• It would still be nice to know how to rotate in a given plane, let's say a triangle drawn in the XY plane. Jul 8, 2013 at 8:17
• @Elena I can't replicate that writelatex.com/219094gjxmfg . Also I don't see any reason why it should be like that. Does it change if you add fill=yellow (maybe the black is still creeping up)? For rotation, I'll look into it later when I have some time. Jul 8, 2013 at 9:04
• why not? it's getting dark (also transparent). In the end I am using fadings: \begin{scope}[opacity=0.3]\draw[draw=none] [postaction={path fading=south,fading angle=45,fill=mygreen}] [postaction={path fading=north,fading angle=45,fill=myblue}] (0,0,0) -- (\x,0,0) -- (\x,0,\z) -- (0,0,\z) -- cycle; \end{scope} See the difference on writelatex Jul 8, 2013 at 12:10
• @ryuk I guess you could try \tikzset{newYXZ/.style={x={(-1cm,0cm)}, y={(1.299cm,0.75cm)}, z={(0cm,1cm)}}} As far as I understand, you do not need to change anything to draw 3d points Dec 28, 2018 at 21:01