I have a problem for my thesis which is very easy to show in a "handmade" drawing, but quite challenging to sketch in tikz/pgfplot (the reason why I work with these packages is mainly that my thesis is written in latex, so making this drawing in the latex file and compile everything would be great). My tikz/pgfplots skills are not that great since I just started using them.

Problem is the following: I have a vector J in a 3D space defined by a system of three coordinate axes (say x,y,z). The vector starts from the origin of the system and has an arbitrary length and direction. In the 3D space, this vector can define a sphere, with the radius R given precisely by the vector's length. If one rotates the vector around the z-axis, the arrow of the vector will define a parallel of latitude (the dotted circle from the picture). Now, if we denote K as being the projection of the vector J on the z-axis with and the point A being the center of the dotted circle, we can now make A oscillate around a steady position "up" and "down" with respect to the z-axis. If A is oscillating up and down while we also rotate J around z-axis, the trajectory of the arrow will define a cosine-like curve (red curve from the photo)

The vector J in the 3D space with the oscillation of K around a steady position

Question How can I draw this in latex using tikz/pgfplots?

Mathematically, this is quite easy to describe, because the sphere, dotted circle and red curve can be parametrized in spherical coordinates. So far I just draw the sphere, that is all I know. I imagine that I have to add two more plots, one for the dotted circle and one for the red oscillating parallel latitude.

\caption{The wobbling motion viewed in a 3D space generated by the three components of the total angular momentum $\mathbf{J}$.}
        axis equal,
        axis lines = center,
        xlabel = {$x$},
        ylabel = {$y$},
        zlabel = {$z$},
        scale uniformly strategy=units only,
        opacity = 0.2,
        z buffer = sort,
        samples = 20,
        variable = \u,
        variable y = \v,
        domain = 0:180,
        y domain = 0:360,
    ({cos(u)*sin(v)}, {sin(u)*sin(v)}, {cos(v)});

Any help would be much appreciated. I am very sorry for the long question, but I couldn't formulate the problem in a shorter way.

1 Answer 1


Here is a proposal based on Alain Matthes macros (with small adjustments).

\tikzset{hidden lines/.style={opacity=0.4}}
    visible angle A/.store in=\VisibleAngleA,
    visible angle A=0,
    visible angle B/.store in=\VisibleAngleB,
    visible angle B=0,

\newcommand\LongitudePlane[3][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#2} % elevation
  \pgfmathsinandcos\sint\cost{#3} % azimuth

\newcommand\LatitudePlane[3][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#2} % elevation
  \pgfmathsinandcos\sint\cost{#3} % latitude
%  \tikzset{#1/.style={cm={\cost,0,0,\cost*\sinEl,(0,\yshift)}}} %
  \tikzset{#1/.style={x={(\cost,0)},y={(0,\cost*\sinEl)},z={(0,1)},yshift={\yshift*1cm}}} %
\newcommand\NewLatitudePlane[4][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#3} % elevation
  \pgfmathsinandcos\sint\cost{#4} % latitude
  \tikzset{#1/.style={cm={\cost,0,0,\cost*\sinEl,(0,\yshift)}}} %
  \tikzset{current plane/.prefix style={scale=#1}}
   % angle of "visibility"
  \pgfmathsetmacro\angVis{atan(sin(#2)*cos(\angEl)/sin(\angEl))} %
  \draw[current plane] (\angVis:1) arc (\angVis:\angVis+180:1);
  \draw[current plane,hidden lines] (\angVis-180:1) arc (\angVis-180:\angVis:1);
  \tikzset{current plane/.prefix style={scale=1}}
  \pgfmathsetmacro\angVis{atan(sin(#2)*cos(\angEl)/sin(\angEl))} %
  \pgfmathsetmacro\angA{mod(max(\angVis,#3),360)} %
  \pgfmathsetmacro\angB{mod(min(\angVis+180,#4),360} %
  \draw[current plane,#1,hidden lines] (#3:\RadiusSphere) arc (#3:#4:\RadiusSphere);
  \draw[current plane,#1]  (\angA:\RadiusSphere) arc (\angA:\angB:\RadiusSphere);
  \tikzset{current plane/.prefix style={scale=#1}}
  % angle of "visibility"
  \draw[current plane] (\angVis:1) arc (\angVis:-\angVis-180:1);
  \draw[current plane,hidden lines] (180-\angVis:1) arc (180-\angVis:\angVis:1);

  \tikzset{current plane/.prefix style={scale=1}}
  % angle of "visibility"
  \pgfmathsetmacro\angA{max(min(\angVis,#3),-\angVis-180)} %
  \pgfmathsetmacro\angB{min(\angVis,#4)} %
  \tikzset{visible angle A=\angA,visible angle B=\angB}
  \draw[current plane,#1,hidden lines] (#3:\RadiusSphere) arc (#3:#4:\RadiusSphere);
  \draw[current plane,#1] (\angA:\RadiusSphere) arc (\angA:\angB:\RadiusSphere);

%% document-wide tikz options and styles

  >=latex, % option for nice arrows
  inner sep=0pt,%
  outer sep=2pt,%
  mark coordinate/.style={inner sep=0pt,outer sep=0pt,minimum size=3pt,


\begin{tikzpicture} % 
\def\RadiusSphere{3} % sphere radius
\def\angEl{20} % elevation angle 

\draw[->] (0,0,0) -- ({1.2*\RadiusSphere},0,0) coordinate(Y) node[below] {$y$};
\draw[->] (0,0,0) -- (0,{1.2*\RadiusSphere},0) coordinate(Z) node[left] {$z$};
\draw[->] (0,0,0) -- (0,0,{2.2*\RadiusSphere}) coordinate(X) node[below] {$x$};

\shade[ball color = gray!40, opacity = 0.5,name path=circle] (0,0) circle (\RadiusSphere);


\LatitudePlane[my plane]{\angEl}{50}
\draw[my plane,red,samples=100] plot[variable=\x,domain=\VisibleAngleA:\VisibleAngleB] 
({3*cos(\x)},{3*sin(\x)},{-0.6*cos(15*\x)})  coordinate (P);
\draw[my plane,red,samples=100,opacity=0.4] plot[variable=\x,domain=\VisibleAngleB:{\VisibleAngleA+360}] 
\draw[->](0,0,0) coordinate(O) -- (P);

\draw (Z) -- (O) -- (P)
pic [draw=green!50!black, fill=green!20, angle radius=9mm,
             "$\theta$"] {angle = P--O--Z};

\path (O) |- (P) coordinate[pos=0.5] (Q);
\fill (Q) circle (1pt);
\draw[decorate,decoration={brace,raise=1pt}] (O) -- (Q) node[midway,left] {$K$};



enter image description here

Unfortunately, some of the non-hidden part of the red curve is drawn as hidden (because the base of the curve is hidden).

  • This is precisely what I needed. Thank you very much sir :) Jun 14, 2018 at 18:20
  • I have low rank so the upvote is not considered:( Jun 14, 2018 at 18:21

You must log in to answer this question.

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