请欣赏以下来自 Jubobs 的非常漂亮的 TikZ 太阳-地球-月球系统绘图(见这里):
代码
\documentclass{article}
\usepackage{lmodern}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[scale=2.5]
\def\rS{0.3} % The Sun's radius.
\def\Earthangle{30} % Angle with respect to horizontal.
\def\rE{0.1} % The Earth's radius.
% 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\rM{0.7*\rE} % The Moon's radius.
\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.
\shade[%
top color=yellow!70,%
bottom color=red!70,%
shading angle={45},%
]({sqrt(1-\bE^2)}, 0) circle (\rS);
% Draw the Earth at \Earthangle.
\pgfmathsetmacro{\radiation}{100*(1 - \eE)/d(\Earthangle)^2}
\colorlet{Earthlight}{yellow!\radiation!blue}
\shade[%
top color=Earthlight,%
bottom color=blue,%
shading angle={90 + f(\Earthangle)},%
]({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});
\shade[%
top color=black!70,%
bottom color=black!30,%
shading angle={45},%
]({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}
输出
问题
我非常希望月亮的阴影(即月亮图中最暗的部分)位于太阳的对面,无论地球和月亮相对于太阳的位置如何。有人能帮我做到这一点吗?(我不了解 TikZ,所以这是一个“请帮我做”的问题;抱歉!)
更新
以下是 Tom Bombadil 的回答,使用动画animate
包裹。
\documentclass{article}
\usepackage[
hmargin=2.4cm,
vmargin=3cm
]{geometry}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{lmodern}
\usepackage{animate}
\def\rS{0.3} % The Sun's radius.
\def\Earthangle{30} % Angle with respect to horizontal.
\def\rE{0.1} % The Earth's radius.
% 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\rM{0.5*\rE} % The Moon's radius.
\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.
\shade[%
inner color=yellow!70,%
outer color=orange!70,%
]({sqrt(1 - \bE^2)}, 0) circle (\rS);
% Draw the Earth at \Earthangle.
\pgfmathsetmacro{\radiation}{100*(1 - \eE)/d(\Earthangle)^2}
\colorlet{Earthlight}{yellow!\radiation!blue}
\shade[%
top color=Earthlight,%
bottom color=blue!75!black,%
shading angle={90 + f(\Earthangle)},%
]({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.
\pgfmathsetmacro{\moonshadinangleangle}{-90 + atan2(\myx, \myy)}
\shade[%
top color=black!90,%
bottom color=black!10,%
shading angle=\moonshadinangleangle,%
]({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}
答案1
基本上,回答这个问题让我回到了我的学生时代,做了一些向量代数;)
代码(动画就绪)
\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{calc}
\usepackage{lmodern}
\begin{document}
\def\rS{0.3} % The Sun's radius.
\def\Earthangle{30} % Angle with respect to horizontal.
\def\rE{0.1} % The Earth's radius.
% 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\rM{0.7*\rE} % The Moon's radius.
\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.
\shade[%
inner color=yellow!70,%
outer color=orange!70,%
%shading angle={45},%
]({sqrt(1-\bE^2)}, 0) circle (\rS);
% Draw the Earth at \Earthangle.
\pgfmathsetmacro{\radiation}{100*(1 - \eE)/d(\Earthangle)^2}
\colorlet{Earthlight}{yellow!\radiation!blue}
\shade[%
top color=Earthlight,%
bottom color=blue!75!black,%
shading angle={90 + f(\Earthangle)},%
]({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
\pgfmathsetmacro{\moonshadinangleangle}{-90+atan2(\myx,\myy)}
\shade[%
top color=black!90,%
bottom color=black!10,%
shading angle=\moonshadinangleangle,%
]({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}