# Relative shadow on TikZ figure

Consider the following very nice TikZ drawing of the Sun--Earth--Moon system from Jubobs (see here):

Code

\documentclass{article}

\usepackage{lmodern}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}[scale=2.5]
\def\Earthangle{30}                      % Angle with respect to horizontal.
% Major radius of the Earth's elliptical orbit = 1.
\def\eE{0.25}                            % Excentricity of the Earth's elliptical orbit.
\pgfmathsetmacro\bE{sqrt(1 - \eE^2)}     % Minor radius of the Earth's elliptical orbit.
\def\Moonangle{-45}                      % Angle with respect to horizontal.
\pgfmathsetmacro\aM{2.5*\rE}             % Major radius of the Moon's elliptical orbit.
\def\eM{0.4}                             % Excentricity of the Earth's elliptical orbit.
\pgfmathsetmacro\bM{\aM*sqrt(1 - \eM^2)} % Minor radius of the Moon's elliptical orbit.
\def\offsetM{30}                         % Angle offset between the major axes of the Earth's and the Moon's orbits.

% This function computes the direction in which light hits the Earth.
\pgfmathdeclarefunction{f}{1}{%
\pgfmathparse{%
(-\eE + cos(#1) <  0) * (180 + atan(\bE*sin(#1)/(-\eE + cos(#1))))
+
(-\eE + cos(#1) >= 0) * atan(\bE*sin(#1)/(-\eE + cos(#1)))
}
}

% This function computes the distance between the Earth and the Sun,
% which is used to calculate the varying radiation intensity on the Earth.
\pgfmathdeclarefunction{d}{1}{%
\pgfmathparse{sqrt((-\eE + cos(#1))^2 + (\bE*sin(#1))^2)}
}

% Draw the elliptical path of the Earth.
\draw[thin,color=gray] (0, 0) ellipse (1 and \bE);

% Draw the Sun at the right-hand-side focus.
top color=yellow!70,%
bottom color=red!70,%
]({sqrt(1-\bE^2)}, 0) circle (\rS);

% Draw the Earth at \Earthangle.
top color=Earthlight,%
bottom color=blue,%
]({cos(\Earthangle)}, {\bE*sin(\Earthangle)}) circle (\rE);
%\draw ({cos(\Earthangle)}, {\bE*sin(\Earthangle) - \rE}) node[below] {Earth};

% Draw the Moon's (circular) orbit and the Moon at \Moonangle.
\draw[thin, color=gray, rotate around={{\offsetM}:({cos(\Earthangle)}, {\bE*sin(\Earthangle)})}]
({cos(\Earthangle)}, {\bE*sin(\Earthangle)}) ellipse ({\aM} and {\bM});
top color=black!70,%
bottom color=black!30,%
]({cos(\Earthangle) + \aM*cos(\Moonangle)*cos(\offsetM) - \bM*sin(\Moonangle)*sin(\offsetM)},%
{\bE*sin(\Earthangle) + \aM*cos(\Moonangle)*sin(\offsetM) + \bM*sin(\Moonangle)*cos(\offsetM)}) circle (\rM);
\end{tikzpicture}

\end{document}


Output

Question

I would very much like to have the shadow of the Moon (i.e., the darkest part of the Moon drawing) at the side opposite to the Sun no matter where the Earth and Moon is drawn relative to the Sun. Can anyone help me do that? (I don't know TikZ so it is a "please do it for me" question; sorry!)

Update

Here is Tom Bombadil's answer as an animation using the animate package.

\documentclass{article}

\usepackage[
hmargin=2.4cm,
vmargin=3cm
]{geometry}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{lmodern}
\usepackage{animate}

\def\Earthangle{30}                      % Angle with respect to horizontal.
% Major radius of the Earth's elliptical orbit = 1.
\def\eE{0.25}                            % Excentricity of the Earth's elliptical orbit.
\pgfmathsetmacro\bE{sqrt(1 - \eE^2)}     % Minor radius of the Earth's elliptical orbit.
\def\Moonangle{-45}                      % Angle with respect to horizontal.
\pgfmathsetmacro\aM{2.5*\rE}             % Major radius of the Moon's elliptical orbit.
\def\eM{0.4}                             % Excentricity of the Earth's elliptical orbit.
\pgfmathsetmacro\bM{\aM*sqrt(1 - \eM^2)} % Minor radius of the Moon's elliptical orbit.
\def\offsetM{30}                         % Angle offset between the major axes of the Earth's and the Moon's orbits.

% This function computes the direction in which light hits the Earth.
\pgfmathdeclarefunction{f}{1}{%
\pgfmathparse{%
(-\eE + cos(#1) <  0) * (180 + atan(\bE*sin(#1)/(-\eE + cos(#1))))
+
(-\eE + cos(#1) >= 0) * atan(\bE*sin(#1)/(-\eE + cos(#1)))
}
}

% This function computes the distance between the Earth and the Sun,
% which is used to calculate the varying radiation intensity on the Earth.
\pgfmathdeclarefunction{d}{1}{%
\pgfmathparse{sqrt((-\eE + cos(#1))^2 + (\bE*sin(#1))^2)}
}

\def\animation#1{%
\begin{tikzpicture}[scale=5]
% Changing parameters for animation.
\pgfmathsetmacro{\Earthangle}{\iA}
\pgfmathsetmacro{\Moonangle}{12*\iA}

% Draw the elliptical path of the Earth.
\draw[thin, color=gray] (0, 0) ellipse (1 and \bE);

% Draw the Sun at the right-hand-side focus.
inner color=yellow!70,%
outer color=orange!70,%
]({sqrt(1 - \bE^2)}, 0) circle (\rS);

% Draw the Earth at \Earthangle.
top color=Earthlight,%
bottom color=blue!75!black,%
]({cos(\Earthangle)}, {\bE*sin(\Earthangle)}) circle (\rE);
%\draw ({cos(\Earthangle)}, {\bE*sin(\Earthangle) - \rE}) node[below] {Earth};

% Draw the Moon's (circular) orbit and the Moon at \Moonangle.
\draw[%
thin,%
color=gray,%
rotate around={{\offsetM}:({cos(\Earthangle)}, {\bE*sin(\Earthangle)})}%
]({cos(\Earthangle)}, {\bE*sin(\Earthangle)}) ellipse ({\aM} and {\bM});

% Makes a path (Moon)-(Sun), e.g., the vector pointing from the Sun to the Moon.
\path ($({cos(\Earthangle) + \aM*cos(\Moonangle)*cos(\offsetM) - \bM*sin(\Moonangle)*sin(\offsetM)},% {\bE*sin(\Earthangle) + \aM*cos(\Moonangle)*sin(\offsetM) + \bM*sin(\Moonangle)*cos(\offsetM)}) - ({sqrt(1 - \bE^2)}, 0)$);
% Get the components of that vector.
\pgfgetlastxy{\myx}{\myy}
% Computing the inclination angle.

top color=black!90,%
bottom color=black!10,%
]({cos(\Earthangle) + \aM*cos(\Moonangle)*cos(\offsetM)
- \bM*sin(\Moonangle)*sin(\offsetM)},%
{\bE*sin(\Earthangle) + \aM*cos(\Moonangle)*sin(\offsetM)
+ \bM*sin(\Moonangle)*cos(\offsetM)}) circle (\rM);
\end{tikzpicture}
}

\pagestyle{empty}

\begin{document}

\begin{figure}[htbp]
\centering
\begin{animateinline}[poster=first,controls,loop]{10}
\multiframe{360}{iA=1+1}{\animation{\iA}}
\end{animateinline}
\end{figure}

\end{document}

-
Try for the moon shading angle={-90+f(\Earthangle)}, instead of shading angle={45}. Is that what you want? It is not 100% precise but its a diagram and not a celestial simulation after all. –  Alexander Jun 4 '13 at 16:15
@Alexander Thank you very much! I'm now exactly sure why this isn't 100 % precise---it looks great to me but if someone can come up with a more accurate shading, please let me know. :-) –  Svend Tveskæg Jun 4 '13 at 16:20
shading angle={-90+f(\Earthangle)} is good, but not 100% precise, because the moon is positioned at a slightly different angle than the the earth. –  Hans-Peter E. Kristiansen Jun 4 '13 at 17:39
@Hans-PeterE.Kristiansen Good point. Do you know how to draw the correct shading of the Moon? –  Svend Tveskæg Jun 4 '13 at 17:50
The correct angle would probably be \path ($(moon)-(sun)$); \pgflastxy{\myx}{\myy} \pgfmathsetmacro{\correctangle}{atan2(\myx,\myy)} –  Tom Bombadil Jun 4 '13 at 20:24

Basically answering this sent me back to my school days, doing a little vector algebra ;)

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{calc}
\usepackage{lmodern}

\begin{document}

\def\Earthangle{30}                      % Angle with respect to horizontal.
% Major radius of the Earth's elliptical orbit = 1.
\def\eE{0.25}                            % Excentricity of the Earth's elliptical orbit.
\pgfmathsetmacro\bE{sqrt(1 - \eE^2)}     % Minor radius of the Earth's elliptical orbit.
\def\Moonangle{-45}                      % Angle with respect to horizontal.
\pgfmathsetmacro\aM{2.5*\rE}             % Major radius of the Moon's elliptical orbit.
\def\eM{0.4}                             % Excentricity of the Earth's elliptical orbit.
\pgfmathsetmacro\bM{\aM*sqrt(1 - \eM^2)} % Minor radius of the Moon's elliptical orbit.
\def\offsetM{30}                         % Angle offset between the major axes of the Earth's and the Moon's orbits.

% This function computes the direction in which light hits the Earth.
\pgfmathdeclarefunction{f}{1}{%
\pgfmathparse{%
(-\eE + cos(#1) <  0) * (180 + atan(\bE*sin(#1)/(-\eE + cos(#1))))
+
(-\eE + cos(#1) >= 0) * atan(\bE*sin(#1)/(-\eE + cos(#1)))
}
}

% This function computes the distance between the Earth and the Sun,
% which is used to calculate the varying radiation intensity on the Earth.
\pgfmathdeclarefunction{d}{1}{%
\pgfmathparse{sqrt((-\eE + cos(#1))^2 + (\bE*sin(#1))^2)}
}

%\foreach \x in {1,...,360}
%{
\begin{tikzpicture}[scale=2.5]
%   % changing parameters for animation
%   \pgfmathsetmacro{\Earthangle}{\x}
%   \pgfmathsetmacro{\Moonangle}{12*\x}

% Draw the elliptical path of the Earth.
\draw[thin,color=gray] (0, 0) ellipse (1 and \bE);

% Draw the Sun at the right-hand-side focus.
inner color=yellow!70,%
outer color=orange!70,%
]({sqrt(1-\bE^2)}, 0) circle (\rS);

% Draw the Earth at \Earthangle.
top color=Earthlight,%
bottom color=blue!75!black,%
]({cos(\Earthangle)}, {\bE*sin(\Earthangle)}) circle (\rE);
%\draw ({cos(\Earthangle)}, {\bE*sin(\Earthangle) - \rE}) node[below] {Earth};

% Draw the Moon's (circular) orbit and the Moon at \Moonangle.
\draw[thin, color=gray, rotate around={{\offsetM}:({cos(\Earthangle)}, {\bE*sin(\Earthangle)})}]
({cos(\Earthangle)}, {\bE*sin(\Earthangle)}) ellipse ({\aM} and {\bM});

% make a path (moon)-(sun), e.g. the vector pointing from sun to moon
\path ($({cos(\Earthangle) + \aM*cos(\Moonangle)*cos(\offsetM) - \bM*sin(\Moonangle)*sin(\offsetM)},{\bE*sin(\Earthangle) + \aM*cos(\Moonangle)*sin(\offsetM) + \bM*sin(\Moonangle)*cos(\offsetM)})-({sqrt(1-\bE^2)}, 0)$);
% get the components of that vector
\pgfgetlastxy{\myx}{\myy}
% compute the inclination angle

top color=black!90,%
bottom color=black!10,%
]({cos(\Earthangle) + \aM*cos(\Moonangle)*cos(\offsetM) - \bM*sin(\Moonangle)*sin(\offsetM)},%
{\bE*sin(\Earthangle) + \aM*cos(\Moonangle)*sin(\offsetM) + \bM*sin(\Moonangle)*cos(\offsetM)}) circle (\rM);

%   %dummy path to keep the size constant for animation
%   \path (-1.5,-1.5) rectangle (1.5,1.5);
\end{tikzpicture}
%}

\end{document}


## Animation

The animation can be created with ImageMagick's convert tool, e.g. convert -loop 0 -delay 5 -dispose previous -size 100x100 source.pdf target.gif –  Tom Bombadil Jun 5 '13 at 11:55
This is seriously cool. :-) Another way of making the animation, is with the animate package. –  Svend Tveskæg Jun 5 '13 at 13:29