I have added this as a new answer since the approach is different from my previous work.
3D is possible and it is surprisingly easy. Well, it is still fake by any means (occlusion for example still depends on drawing order) but you can now place points on the canvas based on radius, phi and theta. The important word here is points: All arc
or curve to
functions do not respect 3D (neither this one nor any prior instance) and therefore have to be drawn by eye. That also means that if you want to draw a circle properly, you will have to do that with a finely graded \foreach
.
The coordinate system is defined on top of the existing xyz coordinate system, mapping to it via the coordinate transformation as given on wikipedia. Angles are to be given in degree, phi ∈ [0:360], theta ∈ [0:180]. There is residue slanting due to the xyz system being naturally turned. For completion, I have build a spherical system around each axis, i.e. longitude around each axis.
Pictures of each spherical coordinate system: (click to enlarge)
This then enables you to reference points based on a spherical system. An improved version of the heart drawing is found below. Note that occlusion depends on the order of drawing, not on 3D position. The polar grid overlaps the heart in the back because it is drawn after it (in terms of code). Note that there appears to be a problem with angle calculation, as the labels of the grid are significantly distorted. If you use something like this, either make the pins long enough or go for debugging. Maybe the mistake is obvious, I have not spent much time it. Wiser minds are invited to comment below.
Figure 1, a heart with pins in it.
Finally, there is code for coordinate calculation that gives a spherical coordinate system.
%along x axis
\makeatletter
\define@key{x sphericalkeys}{radius}{\def\myradius{#1}}
\define@key{x sphericalkeys}{theta}{\def\mytheta{#1}}
\define@key{x sphericalkeys}{phi}{\def\myphi{#1}}
\tikzdeclarecoordinatesystem{x spherical}{% %%%rotation around x
\setkeys{x sphericalkeys}{#1}%
\pgfpointxyz{\myradius*cos(\mytheta)}{\myradius*sin(\mytheta)*cos(\myphi)}{\myradius*sin(\mytheta)*sin(\myphi)}}
%along y axis
\makeatletter
\define@key{y sphericalkeys}{radius}{\def\myradius{#1}}
\define@key{y sphericalkeys}{theta}{\def\mytheta{#1}}
\define@key{y sphericalkeys}{phi}{\def\myphi{#1}}
\tikzdeclarecoordinatesystem{y spherical}{% %%%rotation around x
\setkeys{y sphericalkeys}{#1}%
\pgfpointxyz{\myradius*sin(\mytheta)*cos(\myphi)}{\myradius*cos(\mytheta)}{\myradius*sin(\mytheta)*sin(\myphi)}}
%along z axis
\makeatletter
\define@key{z sphericalkeys}{radius}{\def\myradius{#1}}
\define@key{z sphericalkeys}{theta}{\def\mytheta{#1}}
\define@key{z sphericalkeys}{phi}{\def\myphi{#1}}
\tikzdeclarecoordinatesystem{z spherical}{% %%%rotation around x
\setkeys{z sphericalkeys}{#1}%
\pgfpointxyz{\myradius*sin(\mytheta)*cos(\myphi)}{\myradius*sin(\mytheta)*sin(\myphi)}{\myradius*cos(\mytheta)}}
The code is pretty much the same in all three instances; Define three variables, one each for radius, theta and phi. Define new coordinate system [xyz] spherical and map the new coordinates to each entry in the xyz coordinate system. The [xyz] system is then a permutation of to which coordinate to map each coordinate transformation. The three spheres are drawn with variations of
\begin{tikzpicture}
\draw[->] (0,0,0) -- (4,0,0) node[at end, below right, gray]{x};
\draw[->] (0,0,0) -- (0,4,0) node[at end, above left, gray]{y};
\draw[->] (0,0,0) -- (0,0,4) node[at end, below left, gray]{z};
\foreach \one in {0,10,...,180}
\foreach \two in {220, 230,...,360}
\draw {-- (y spherical cs: radius=3, theta=\one, phi=\two) circle (0.5pt)};
\end{tikzpicture}
The code for figure 1 is given below. For the text on the gray labels, it now requires usetikzlibrary{decorations.text}
.
\begin{tikzpicture}
%side gray strips and label on it
\draw[line width = 10pt, gray!40] (y spherical cs: radius=5.5, phi=180, theta=135) foreach \angle in {134, 133,...,90} {-- (y spherical cs: radius = 5.5, phi=180, theta=\angle)} -- (y spherical cs: radius=5, phi=180, theta=90);
\path decorate [decoration={text along path, text={Bottom left label},text align= {align=center},reverse path}] {(y spherical cs: radius=5.5, phi=180, theta=135) foreach \angle in {134, 133,...,90} {-- (y spherical cs: radius = 5.6, phi=180, theta=\angle)}};
\draw[line width = 10pt, gray!40] (y spherical cs: radius = 5, phi= 180, theta=90) foreach \angle in {90, 89,...,0} { -- (y spherical cs: radius = 5.5, phi=180, theta=\angle)} -- (y spherical cs: radius = 5, phi = 0, theta= 0);
\path decorate [decoration={text along path, text={Bottom left label},text align= {align=center}}] {(y spherical cs: radius = 5, phi= 180, theta=90) foreach \angle in {90, 89,...,0} { -- (y spherical cs: radius = 5.4, phi=180, theta=\angle)}};
%3D coordinate system
\draw[->] (0,0,0) -- (7,0,0) node[at end, below right, gray]{x};
\draw[->] (0,0,0) -- (0,7,0) node[at end, above left, gray]{y};
\draw[->] (0,0,0) -- (0,0,7) node[at end, below left, gray]{z};
%Stole my heart
\draw (0,0) node (heart) {\includegraphics[width=5cm]{QwMQn}};
%numbered lables with pricks
\foreach \angle in {20,46,...,280}{
\path (y spherical cs: radius = 5, phi = \angle,theta = 60) node (Outer\angle) {};
\path (y spherical cs: radius = 2, phi = \angle, theta = 60) node (Inner\angle) {};
\draw (Inner\angle) -- (Outer\angle) node {\angle};}
%coordinate system in the plane – Note that the coordinate calculation for outer and inner group seems strange
\draw (y spherical cs: radius = 5, phi = 0, theta= 90) foreach \aangle in {1,2,...,359} { -- (y spherical cs: radius = 5, phi = \aangle, theta = 90)} -- cycle;
\draw (y spherical cs: radius = 5.5, phi=30, theta=90) node[gray] {$\phi$};
\foreach \angle in {0,10,...,350}{
\path (y spherical cs: radius = 5.2, phi = \angle,theta = 90) node (Outer\angle) {};
\path (y spherical cs: radius = 4.5, phi = \angle, theta = 90) node (Inner\angle) {};
\draw (Inner\angle) -- (Outer\angle);}
%Theta angle on the side
\draw[->] (y spherical cs: radius = 5, phi = 0, theta= 70) foreach \aangle in {71,71.2,...,160} { -- (y spherical cs: radius = 5, phi = 0, theta = \aangle)};
\draw (y spherical cs: radius = 5.5, phi=0, theta=120) node[gray] {$\theta$};
\end{tikzpicture}
The coordinate code works out of the box, no library required. I hope this helps you. I extend my gratitude @Tom Bombadil for the answer in the shift and rotate in 3D question, pointing out that cos
and sin
are usable within the low-level pgf
keys.