Tikz:: shift and rotate in 3d?
Here's a solution, but only for translation (so far). It uses the fact that internaly TikZ
handles 3D points as 2D ones. So your 3D shift vector is saved in the coordinate mytranslation
which then is a 2D point and thus can be passed to shift
. The thick lines are just to illustrate that the translation is done correctly:
\documentclass{standalone}
\usepackage{tikz}
\newcommand{\translatepoint}[1]%
{ \coordinate (mytranslation) at (#1);
}
\newcommand{\somedrawing}%
{ \coordinate (a) at (0,0,0);
\coordinate (b) at (5,1,0);
\coordinate (c) at (2,4,0);
\coordinate (d) at (1,-1,-4);
\draw (a) -- (b) (a) -- (c) (a) -- (d) (b) -- (c) (b) -- (d) (c) -- (d);
}
\begin{document}
\begin{tikzpicture}[x={(0.866cm,0.5cm)},y={(-0.866cm,0.5cm)},z={(0cm,1cm)}]
\somedrawing
\translatepoint{5,0,0}
\draw[very thick,red] (0,0,0) -- (5,0,0);
\begin{scope}[shift=(mytranslation),draw=red]
\somedrawing
\end{scope}
\translatepoint{0,6,0}
\draw[very thick,blue] (0,0,0) -- (0,6,0);
\begin{scope}[shift=(mytranslation),draw=blue]
\somedrawing
\end{scope}
\translatepoint{0,0,8}
\draw[very thick,green!50!gray] (0,0,0) -- (0,0,8);
\begin{scope}[shift=(mytranslation),draw=green!50!gray]
\somedrawing
\end{scope}
\translatepoint{-5,0,-2}
\draw[very thick,orange] (0,0,0) -- (-5,0,-2);
\begin{scope}[shift=(mytranslation),draw=orange]
\somedrawing
\end{scope}
\end{tikzpicture}
\end{document}
Edit 1: I finally managed the rotation, but, that was a bitch. I put the mathematical foundation for RPY rotations first, a really nice matrix. Then I borrowed an idea from Andrew Stacey from this question: finding out where the (cartesian) unit vectors point via \pgfgetlastxy
. Then it was only writing the matrix in Tikz
notation, using \pgfgetlastxy
once again and there you go!
\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{arrows}
\usepackage{amsmath}
\newcommand{\rotateRPY}[3]% roll, pitch, yaw
{ \pgfmathsetmacro{\rollangle}{#1}
\pgfmathsetmacro{\pitchangle}{#2}
\pgfmathsetmacro{\yawangle}{#3}
% to what vector is the x unit vector transformed, and which 2D vector is this?
\pgfmathsetmacro{\newxx}{cos(\yawangle)*cos(\pitchangle)}
\pgfmathsetmacro{\newxy}{sin(\yawangle)*cos(\pitchangle)}
\pgfmathsetmacro{\newxz}{-sin(\pitchangle)}
\path (\newxx,\newxy,\newxz);
\pgfgetlastxy{\nxx}{\nxy};
% to what vector is the y unit vector transformed, and which 2D vector is this?
\pgfmathsetmacro{\newyx}{cos(\yawangle)*sin(\pitchangle)*sin(\rollangle)-sin(\yawangle)*cos(\rollangle)}
\pgfmathsetmacro{\newyy}{sin(\yawangle)*sin(\pitchangle)*sin(\rollangle)+ cos(\yawangle)*cos(\rollangle)}
\pgfmathsetmacro{\newyz}{cos(\pitchangle)*sin(\rollangle)}
\path (\newyx,\newyy,\newyz);
\pgfgetlastxy{\nyx}{\nyy};
% to what vector is the z unit vector transformed, and which 2D vector is this?
\pgfmathsetmacro{\newzx}{cos(\yawangle)*sin(\pitchangle)*cos(\rollangle)+ sin(\yawangle)*sin(\rollangle)}
\pgfmathsetmacro{\newzy}{sin(\yawangle)*sin(\pitchangle)*cos(\rollangle)-cos(\yawangle)*sin(\rollangle)}
\pgfmathsetmacro{\newzz}{cos(\pitchangle)*cos(\rollangle)}
\path (\newzx,\newzy,\newzz);
\pgfgetlastxy{\nzx}{\nzy};
}
\tikzset{RPY/.style={x={(\nxx,\nxy)},y={(\nyx,\nyy)},z={(\nzx,\nzy)}}}
\begin{document}
$R=\begin{pmatrix}
\cos \alpha \cos \beta
& \textcolor{red}{\cos \alpha \sin \beta \sin \gamma - \sin \alpha \cos \gamma}
& \cos \alpha \sin \beta \cos \gamma + \sin \alpha \sin \gamma \\
\textcolor{red}{\sin \alpha \cos \beta}
& \sin \alpha \sin \beta \sin \gamma + \cos \alpha \cos \gamma
& \textcolor{red}{\sin \alpha \sin \beta \cos \gamma - \cos \alpha \sin \gamma} \\
- \sin \beta
& \textcolor{red}{\cos \beta \sin \gamma}
& \cos \beta \cos \gamma
\end{pmatrix}\\p'=R\cdot p$
\begin{tikzpicture}
\draw[-latex] node at (3.5,0,0) {x} (0,0,0) -- (3,0,0);
\draw[-latex] node at (0,3.5,0) {y} (0,0,0) -- (0,3,0);
\draw[-latex] node at (0,0,3.5) {z} (0,0,0) -- (0,0,3);
\rotateRPY{0}{0}{45}
\begin{scope}[draw=red, text=red,fill=red,densely dashed,RPY]
\draw[-latex] node at (3.5,0,0) {x} (0,0,0) -- (3,0,0);
\draw[-latex] node at (0,3.5,0) {y} (0,0,0) -- (0,3,0);
\draw[-latex] node at (0,0,3.5) {z} (0,0,0) -- (0,0,3);
\end{scope}
\node[fill=white,fill opacity=0.7,text opacity=1] {RPY: 0,0,45};
\end{tikzpicture}
\begin{tikzpicture}
\draw[-latex] node at (3.5,0,0) {x} (0,0,0) -- (3,0,0);
\draw[-latex] node at (0,3.5,0) {y} (0,0,0) -- (0,3,0);
\draw[-latex] node at (0,0,3.5) {z} (0,0,0) -- (0,0,3);
\rotateRPY{0}{30}{0}
\begin{scope}[draw=red, text=red,fill=red,densely dashed,RPY]
\draw[-latex] node at (3.5,0,0) {x} (0,0,0) -- (3,0,0);
\draw[-latex] node at (0,3.5,0) {y} (0,0,0) -- (0,3,0);
\draw[-latex] node at (0,0,3.5) {z} (0,0,0) -- (0,0,3);
\end{scope}
\node[fill=white,fill opacity=0.7,text opacity=1] {RPY: 0,30,0};
\end{tikzpicture}
\begin{tikzpicture}
\draw[-latex] node at (3.5,0,0) {x} (0,0,0) -- (3,0,0);
\draw[-latex] node at (0,3.5,0) {y} (0,0,0) -- (0,3,0);
\draw[-latex] node at (0,0,3.5) {z} (0,0,0) -- (0,0,3);
\rotateRPY{80}{0}{0}
\begin{scope}[draw=red, text=red,fill=red,densely dashed,RPY]
\draw[-latex] node at (3.5,0,0) {x} (0,0,0) -- (3,0,0);
\draw[-latex] node at (0,3.5,0) {y} (0,0,0) -- (0,3,0);
\draw[-latex] node at (0,0,3.5) {z} (0,0,0) -- (0,0,3);
\end{scope}
\node[fill=white,fill opacity=0.7,text opacity=1] {RPY: 80,0,0};
\end{tikzpicture}
\begin{tikzpicture}[x={(0.866cm,-0.5cm)},y={(-0.866cm,-0.5cm)},z={(0cm,1cm)}]
\draw[-latex] node at (3.5,0,0) {x} (0,0,0) -- (3,0,0);
\draw[-latex] node at (0,3.5,0) {y} (0,0,0) -- (0,3,0);
\draw[-latex] node at (0,0,3.5) {z} (0,0,0) -- (0,0,3);
\rotateRPY{13}{171}{55}
\begin{scope}[draw=red, text=red,fill=red,densely dashed,RPY]
\draw[-latex] node at (3.5,0,0) {x} (0,0,0) -- (3,0,0);
\draw[-latex] node at (0,3.5,0) {y} (0,0,0) -- (0,3,0);
\draw[-latex] node at (0,0,3.5) {z} (0,0,0) -- (0,0,3);
\end{scope}
\node[fill=white,fill opacity=0.7,text opacity=1] {RPY: 13,171,55};
\end{tikzpicture}
\end{document}
Edit 2: Now you can pass a point to the command and determine to what new xyz coordinates it is mapped. Also, inspired by Herbert's solution, there now is a better example featuring cubes and arrows:
\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{arrows,3D}
\newcommand{\savedx}{0}
\newcommand{\savedy}{0}
\newcommand{\savedz}{0}
\newcommand{\somedrawing}%
{ \coordinate (a) at (-2,-2,-2);
\coordinate (b) at (-2,-2,2);
\coordinate (c) at (-2,2,-2);
\coordinate (d) at (-2,2,2);
\coordinate (e) at (2,-2,-2);
\coordinate (f) at (2,-2,2);
\coordinate (g) at (2,2,-2);
\coordinate (h) at (2,2,2);
\draw (a)--(b) (a)--(c) (a)--(e) (b)--(d) (b)--(f) (c)--(d) (c)--(g) (d)--(h) (e)--(f) (e)--(g) (f)--(h) (g)--(h);
\fill (a) circle (0.1cm);
\fill (d) ++(0.1cm,0.1cm) rectangle ++(-0.2cm,-0.2cm);
}
\newcommand{\rotateRPY}[4][0/0/0]% point to be saved to \savedxyz, roll, pitch, yaw
{ \pgfmathsetmacro{\rollangle}{#2}
\pgfmathsetmacro{\pitchangle}{#3}
\pgfmathsetmacro{\yawangle}{#4}
% to what vector is the x unit vector transformed, and which 2D vector is this?
\pgfmathsetmacro{\newxx}{cos(\yawangle)*cos(\pitchangle)}% a
\pgfmathsetmacro{\newxy}{sin(\yawangle)*cos(\pitchangle)}% d
\pgfmathsetmacro{\newxz}{-sin(\pitchangle)}% g
\path (\newxx,\newxy,\newxz);
\pgfgetlastxy{\nxx}{\nxy};
% to what vector is the y unit vector transformed, and which 2D vector is this?
\pgfmathsetmacro{\newyx}{cos(\yawangle)*sin(\pitchangle)*sin(\rollangle)-sin(\yawangle)*cos(\rollangle)}% b
\pgfmathsetmacro{\newyy}{sin(\yawangle)*sin(\pitchangle)*sin(\rollangle)+ cos(\yawangle)*cos(\rollangle)}% e
\pgfmathsetmacro{\newyz}{cos(\pitchangle)*sin(\rollangle)}% h
\path (\newyx,\newyy,\newyz);
\pgfgetlastxy{\nyx}{\nyy};
% to what vector is the z unit vector transformed, and which 2D vector is this?
\pgfmathsetmacro{\newzx}{cos(\yawangle)*sin(\pitchangle)*cos(\rollangle)+ sin(\yawangle)*sin(\rollangle)}
\pgfmathsetmacro{\newzy}{sin(\yawangle)*sin(\pitchangle)*cos(\rollangle)-cos(\yawangle)*sin(\rollangle)}
\pgfmathsetmacro{\newzz}{cos(\pitchangle)*cos(\rollangle)}
\path (\newzx,\newzy,\newzz);
\pgfgetlastxy{\nzx}{\nzy};
% transform the point given by #1
\foreach \x/\y/\z in {#1}
{ \pgfmathsetmacro{\transformedx}{\x*\newxx+\y*\newyx+\z*\newzx}
\pgfmathsetmacro{\transformedy}{\x*\newxy+\y*\newyy+\z*\newzy}
\pgfmathsetmacro{\transformedz}{\x*\newxz+\y*\newyz+\z*\newzz}
\xdef\savedx{\transformedx}
\xdef\savedy{\transformedy}
\xdef\savedz{\transformedz}
}
}
\tikzset{RPY/.style={x={(\nxx,\nxy)},y={(\nyx,\nyy)},z={(\nzx,\nzy)}}}
\begin{document}
\begin{tikzpicture}
\somedrawing
\rotateRPY{0}{0}{101}
\begin{scope}[draw=red, text=red,fill=red,densely dashed,RPY]
\somedrawing
\end{scope}
\draw[canvas is xy plane at z=2,-latex,thick, blue] (-2,2) arc (135:236:2.828);
\node[fill=white,fill opacity=0.7,text opacity=1] {RPY: 0,0,101};
\end{tikzpicture}
\begin{tikzpicture}
\somedrawing
\rotateRPY{0}{55}{0}
\begin{scope}[draw=red, text=red,fill=red,densely dashed,RPY]
\somedrawing
\end{scope}
\draw[canvas is xz plane at y=2,-latex,thick, blue] (-2,2) arc (135:80:2.828);
\node[fill=white,fill opacity=0.7,text opacity=1] {RPY: 0,55,0};
\end{tikzpicture}
\begin{tikzpicture}
\somedrawing
\rotateRPY{61}{0}{0}
\begin{scope}[draw=red, text=red,fill=red,densely dashed,RPY]
\somedrawing
\end{scope}
\draw[canvas is yz plane at x=-2,-latex,thick, blue] (2,2) arc (45:106:2.828);
\node[fill=white,fill opacity=0.7,text opacity=1] {RPY: 71,0,0};
\end{tikzpicture}
\begin{tikzpicture}%[x={(1cm,1cm)},y={(-1cm,1cm)},z={(-2cm,-1cm)}]
\somedrawing
\rotateRPY[-2/2/2]{13}{171}{55}
\node[fill=white,fill opacity=0.7,text opacity=1,align=left,text=blue] at (5,2) {-2 $\longrightarrow$ \savedx \\ 2 $\longrightarrow$ \savedy \\ 2 $\longrightarrow$ \savedz};
\begin{scope}[draw=red, text=red,fill=red,densely dashed,RPY]
\somedrawing
\end{scope}
\draw[blue,ultra thick] (-2,2,2) -- (\savedx,2,2) -- (\savedx,\savedy,2) -- (\savedx,\savedy,\savedz) circle (0.25);
\rotateRPY[-2/-2/-2]{13}{171}{55}
\node[fill=white,fill opacity=0.7,text opacity=1,align=left,text=green!50!gray] at (5,0) {-2 $\longrightarrow$ \savedx \\ -2 $\longrightarrow$ \savedy \\ -2 $\longrightarrow$ \savedz};
\draw[green!50!gray,ultra thick] (-2,-2,-2) -- (\savedx,-2,-2) -- (\savedx,\savedy,-2) -- (\savedx,\savedy,\savedz) circle (0.25);
\node[fill=white,fill opacity=0.7,text opacity=1] {RPY: 13,171,55};
\end{tikzpicture}
\end{document}
an example with PStricks. Run it with xelatex
\documentclass{article}
\pagestyle{empty}
\setlength\parindent{0pt}
\usepackage{pst-solides3d}
\begin{document}
\psset{viewpoint=20 60 20 rtp2xyz,lightsrc=10 15 7,Decran=20}
\begin{pspicture}(-5,-5)(6,5)
\psSolid[object=grille,base=-3 3 -3 3,fillcolor=red!50]
\axesIIID(4,4,3)
\psSolid[object=cube,a=2,ngrid=3,RotX=45,RotY=30,fillcolor=yellow!50](-2,0,0)
\psSolid[object=cube,a=2,ngrid=3,transform={.75 3 .5 scaleOpoint3d}](2,0,1)
\psSolid[object=cube,a=2,ngrid=3,RotZ=30,transform={ 3 -2 0 addv3d },action=draw](-2,0,0)
\end{pspicture}
\end{document}
- 1st cube: rotated at the x and y axis (center of the box at (-2,0,0) )
- 2nd: scaled by x=0.75, y=3, z=0.5 (center at (2,0,1) )
- 3rd: rotated at the z axis and moved by (3,-2,0) (center at (-2,0,0) )