使用 tikz 在球体上获取纬度和经度坐标

使用 tikz 在球体上获取纬度和经度坐标

我正在尝试立体和圆柱地图投影Tomas M. Trzeciak 编写的代码,用于重现下面的两个球体。然而,我很难正确理解代码,到目前为止,我至少能够获得平行线和子午线。

纬度和经度

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,fadings,decorations.pathreplacing}
\usepackage{verbatim}

\newcommand\pgfmathsinandcos[3]{%
  \pgfmathsetmacro#1{sin(#3)}%
  \pgfmathsetmacro#2{cos(#3)}%
}
\newcommand\LongitudePlane[3][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#2} % elevation
  \pgfmathsinandcos\sint\cost{#3} % azimuth
  \tikzset{#1/.style={cm={\cost,\sint*\sinEl,0,\cosEl,(0,0)}}}
}
\newcommand\LatitudePlane[3][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#2} % elevation
  \pgfmathsinandcos\sint\cost{#3} % latitude
  \pgfmathsetmacro\yshift{\cosEl*\sint}
  \tikzset{#1/.style={cm={\cost,0,0,\cost*\sinEl,(0,\yshift)}}} %
}
\newcommand\DrawLongitudeCircle[2][1]{
  \LongitudePlane{\angEl}{#2}
  \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,dashed] (\angVis-180:1) arc (\angVis-180:\angVis:1);
}
\newcommand\DrawLatitudeCircle[2][1]{
  \LatitudePlane{\angEl}{#2}
  \tikzset{current plane/.prefix style={scale=#1}}
  \pgfmathsetmacro\sinVis{sin(#2)/cos(#2)*sin(\angEl)/cos(\angEl)}
  % angle of "visibility"
  \pgfmathsetmacro\angVis{asin(min(1,max(\sinVis,-1)))}
  \draw[current plane] (\angVis:1) arc (\angVis:-\angVis-180:1);
  \draw[current plane,dashed] (180-\angVis:1) arc (180-\angVis:\angVis:1);
}

%% document-wide tikz options and styles

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

\begin{document}

\begin{tikzpicture} % "THE GLOBE" showcase
\def\R{4 } % sphere radius
\def\angEl{20} % elevation angle
\def\angAz{-20} % azimuth angle
\filldraw[ball color=white] (0,0) circle (\R);
\filldraw[fill=white] (0,0) circle (\R);

\foreach \t in {0,30} { \DrawLatitudeCircle[\R]{\t} }
\foreach \t in {-120} { \DrawLongitudeCircle[\R]{\t} }

\pgfmathsetmacro\H{\R*cos(\angEl)} % distance to north pole
\coordinate (O) at (0,0);
\node[circle,draw,black,scale=0.3] at (0,0) {};
\draw[left] node at (0,0){O};
\coordinate[mark coordinate] (N) at (0,\H);
\draw[left] node at (0,\H){N};
\coordinate[mark coordinate] (S) at (0,-\H);
\draw[left] node at (0,-\H){S};
\draw[thick, dashed, black](N)--(S);
\end{tikzpicture}

\end{document}

你能帮助我正确得出这些要点并画出相应的图画吗?

答案1

更新我在使用上面的宏时遇到了一些小问题,但这些宏以及下面的宏都非常棒。Henri Menkes 链接。主要问题是我发现yshift仅当球体半径为 1 时才正确。接下来,我将提供 3 个代码,其中最后一个可能是最方便的。不用说,它们充其量只是对 Alain Matthes 的精彩例程的微小修改。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,fadings,decorations.pathreplacing}
\usepackage{verbatim}

\newcommand\pgfmathsinandcos[3]{%
  \pgfmathsetmacro#1{sin(#3)}%
  \pgfmathsetmacro#2{cos(#3)}%
}
\newcommand\LongitudePlane[3][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#2} % elevation
  \pgfmathsinandcos\sint\cost{#3} % azimuth
  \tikzset{#1/.style={cm={\cost,\sint*\sinEl,0,\cosEl,(0,0)}}}
}

\newcommand\LatitudePlane[3][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#2} % elevation
  \pgfmathsinandcos\sint\cost{#3} % latitude
  \pgfmathsetmacro\yshift{\cosEl*\sint}
  \tikzset{#1/.style={cm={\cost,0,0,\cost*\sinEl,(0,\yshift)}}} %
}
\newcommand\NewLatitudePlane[4][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#3} % elevation
  \pgfmathsinandcos\sint\cost{#4} % latitude
  \pgfmathsetmacro\yshift{#2*\cosEl*\sint}
  \tikzset{#1/.style={cm={\cost,0,0,\cost*\sinEl,(0,\yshift)}}} %
}
\newcommand\DrawLongitudeCircle[2][1]{
  \LongitudePlane{\angEl}{#2}
  \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,dashed] (\angVis-180:1) arc (\angVis-180:\angVis:1);
}
\newcommand\DrawLatitudeCircle[2][1]{
  \LatitudePlane{\angEl}{#2}
  \tikzset{current plane/.prefix style={scale=#1}}
  \pgfmathsetmacro\sinVis{sin(#2)/cos(#2)*sin(\angEl)/cos(\angEl)}
  % angle of "visibility"
  \pgfmathsetmacro\angVis{asin(min(1,max(\sinVis,-1)))}
  \draw[current plane] (\angVis:1) arc (\angVis:-\angVis-180:1);
  \draw[current plane,dashed] (180-\angVis:1) arc (180-\angVis:\angVis:1);
}

%% document-wide tikz options and styles

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

\begin{document}

\begin{tikzpicture} % "THE GLOBE" showcase
\def\R{4 } % sphere radius
\def\angEl{20} % elevation angle
\def\angAz{-20} % azimuth angle
\filldraw[ball color=white] (0,0) circle (\R);
\filldraw[fill=white] (0,0) circle (\R);

\foreach \t in {0,30} { \DrawLatitudeCircle[\R]{\t} }
\foreach \t in {-120} { \DrawLongitudeCircle[\R]{\t} }


\pgfmathsetmacro\H{\R*cos(\angEl)} % distance to north pole
\coordinate (O) at (0,0);
\node[circle,draw,black,scale=0.3] at (0,0) {};
\draw[right] node at (0,0){O};
\coordinate[mark coordinate] (N) at (0,\H);
\draw[left] node at (0,\H){N};
\coordinate[mark coordinate] (S) at (0,-\H);
\draw[left] node at (0,-\H){S};
\draw[thick, dashed, black](N)--(S);

\NewLatitudePlane[planeP]{\R}{\angEl}{30};
\path[planeP] (-120:\R) coordinate (P);
\draw[left] node at (P){$P$};

\NewLatitudePlane[equator]{\R}{\angEl}{00};
\path[equator] (-120:\R) coordinate (Pprime);
\draw[left] node at (Pprime){$P'$};

\draw[-,dashed] (O)--(P);
\draw[-,dashed] (O)--(Pprime);

\LongitudePlane[angle]{\angEl}{-120};
\draw[angle,-] (0:1) arc (0:30:1);

\end{tikzpicture}

\end{document}

我所做的唯一一件事就是引入一个命令\NewLatitudePlane,它与的不同之处\LatitudePlane在于它还接受半径。这是计算正确的所必需的yshift。然后您可以定义经度平面和纬度平面并绘制其中的所有特征。上面的代码产生

在此处输入图片描述

我引入了两个纬度平面,一个在 30 度,称为planeP,其中我将点 P 放在经度 -120 度,还有一个赤道平面,其中 P' 放在经度 -120 度。然后我定义了一个用于绘制角度的经度平面。我没有花任何精力将 P 和 P' 放置得更漂亮。

对于另一张图片,你可以从

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,fadings,decorations.pathreplacing}
\usepackage{verbatim}

\newcommand\pgfmathsinandcos[3]{%
  \pgfmathsetmacro#1{sin(#3)}%
  \pgfmathsetmacro#2{cos(#3)}%
}
\newcommand\LongitudePlane[3][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#2} % elevation
  \pgfmathsinandcos\sint\cost{#3} % azimuth
  \tikzset{#1/.style={cm={\cost,\sint*\sinEl,0,\cosEl,(0,0)}}}
}

\newcommand\LatitudePlane[3][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#2} % elevation
  \pgfmathsinandcos\sint\cost{#3} % latitude
  \pgfmathsetmacro\yshift{\cosEl*\sint}
  \tikzset{#1/.style={cm={\cost,0,0,\cost*\sinEl,(0,\yshift)}}} %
}
\newcommand\NewLatitudePlane[4][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#3} % elevation
  \pgfmathsinandcos\sint\cost{#4} % latitude
  \pgfmathsetmacro\yshift{#2*\cosEl*\sint}
  \tikzset{#1/.style={cm={\cost,0,0,\cost*\sinEl,(0,\yshift)}}} %
}
\newcommand\DrawLongitudeCircle[2][1]{
  \LongitudePlane{\angEl}{#2}
  \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,dashed] (\angVis-180:1) arc (\angVis-180:\angVis:1);
}
\newcommand\DrawLatitudeCircle[2][1]{
  \LatitudePlane{\angEl}{#2}
  \tikzset{current plane/.prefix style={scale=#1}}
  \pgfmathsetmacro\sinVis{sin(#2)/cos(#2)*sin(\angEl)/cos(\angEl)}
  % angle of "visibility"
  \pgfmathsetmacro\angVis{asin(min(1,max(\sinVis,-1)))}
  \draw[current plane] (\angVis:1) arc (\angVis:-\angVis-180:1);
  \draw[current plane,dashed] (180-\angVis:1) arc (180-\angVis:\angVis:1);
}

%% document-wide tikz options and styles

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

\begin{document}

\begin{tikzpicture} % "THE GLOBE" showcase
\def\R{4 } % sphere radius
\def\angEl{20} % elevation angle
\def\angAz{-20} % azimuth angle
\filldraw[ball color=white] (0,0) circle (\R);
\filldraw[fill=white] (0,0) circle (\R);



\pgfmathsetmacro\H{\R*cos(\angEl)} % distance to north pole
\coordinate (O) at (0,0);
\node[circle,draw,black,scale=0.3] at (0,0) {};
\draw[right] node at (0,0){O};
\coordinate[mark coordinate] (N) at (0,\H);
\draw[left] node at (0,\H){N};
\coordinate[mark coordinate] (S) at (0,-\H);
\draw[left] node at (0,-\H){S};
\draw[thick, dashed, black](N)--(S);

\tikzset{
    every path/.style={
        color=green
    }
}
\DrawLatitudeCircle[\R]{0}
\tikzset{
    every path/.style={
        color=black
    }
}


\LongitudePlane[angle]{\angEl}{-80};
\draw[angle,-,red] (-70:\R) arc (-70:90:\R); % note : -70 could also be computed! 
\draw[angle,-,red,dashed] (-90:\R) arc (-90:-70:\R); % note : -70 could also be computed! 
\path[angle] (00:\R) coordinate (Pprime);
\draw[right] node at (Pprime){$P'$};


\LongitudePlane[angel]{\angEl}{-120};
\draw[angel,-,blue] (-70:\R) arc (-70:90:\R); % note : -70 could also be computed! 
\draw[angel,-,blue,dashed] (-90:\R) arc (-90:-70:\R); % note : -70 could also be computed! 
\path[angel] (00:\R) coordinate (Oprime);
\draw[left] node at (Oprime){$O'$};

\def\arcrad{2}
\NewLatitudePlane[equator]{\R}{\angEl}{00};
\draw[equator,-,red,dashed] (-120:\arcrad) arc (-120:-80:\arcrad);
\path[equator] (-120:\arcrad) coordinate (m);
\draw[left] node at (m){$m$};
\path[equator] (-80:\arcrad) coordinate (mprime);
\draw[right] node at (mprime){$m'$};

\draw[-,dashed] (Oprime) -- (O) -- (Pprime);

\end{tikzpicture}

\end{document}

在此处输入图片描述

这是一个支持纬度和经度弧的版本。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,fadings,decorations.pathreplacing,shadings}
\usepackage{verbatim}

\newcommand\pgfmathsinandcos[3]{%
  \pgfmathsetmacro#1{sin(#3)}%
  \pgfmathsetmacro#2{cos(#3)}%
}
\newcommand\LongitudePlane[3][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#2} % elevation
  \pgfmathsinandcos\sint\cost{#3} % azimuth
  \tikzset{#1/.style={cm={\cost,\sint*\sinEl,0,\cosEl,(0,0)}}}
}

\newcommand\LatitudePlane[3][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#2} % elevation
  \pgfmathsinandcos\sint\cost{#3} % latitude
  \pgfmathsetmacro\yshift{\RadiusSphere*\cosEl*\sint}
  \tikzset{#1/.style={cm={\cost,0,0,\cost*\sinEl,(0,\yshift)}}} %
}
\newcommand\NewLatitudePlane[4][current plane]{%
  \pgfmathsinandcos\sinEl\cosEl{#3} % elevation
  \pgfmathsinandcos\sint\cost{#4} % latitude
  \pgfmathsetmacro\yshift{#2*\cosEl*\sint}
  \tikzset{#1/.style={cm={\cost,0,0,\cost*\sinEl,(0,\yshift)}}} %
}
\newcommand\DrawLongitudeCircle[2][1]{
  \LongitudePlane{\angEl}{#2}
  \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,opacity=0.4] (\angVis-180:1) arc (\angVis-180:\angVis:1);
}
\newcommand\DrawLongitudeArc[4][black]{
  \LongitudePlane{\angEl}{#2}
  \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,opacity=0.4] (#3:\RadiusSphere) arc (#3:#4:\RadiusSphere);
  \draw[current plane,#1]  (\angA:\RadiusSphere) arc (\angA:\angB:\RadiusSphere);
}%
\newcommand\DrawLatitudeCircle[2][1]{
  \LatitudePlane{\angEl}{#2}
  \tikzset{current plane/.prefix style={scale=#1}}
  \pgfmathsetmacro\sinVis{sin(#2)/cos(#2)*sin(\angEl)/cos(\angEl)}
  % angle of "visibility"
  \pgfmathsetmacro\angVis{asin(min(1,max(\sinVis,-1)))}
  \draw[current plane] (\angVis:1) arc (\angVis:-\angVis-180:1);
  \draw[current plane,opacity=0.4] (180-\angVis:1) arc (180-\angVis:\angVis:1);
}

\newcommand\DrawLatitudeArc[4][black]{
  \LatitudePlane{\angEl}{#2}
  \tikzset{current plane/.prefix style={scale=1}}
  \pgfmathsetmacro\sinVis{sin(#2)/cos(#2)*sin(\angEl)/cos(\angEl)}
  % angle of "visibility"
  \pgfmathsetmacro\angVis{asin(min(1,max(\sinVis,-1)))}
  \pgfmathsetmacro\angA{max(min(\angVis,#3),-\angVis-180)} %
  \pgfmathsetmacro\angB{min(\angVis,#4)} %
  \draw[current plane,#1,opacity=0.4] (#3:\RadiusSphere) arc (#3:#4:\RadiusSphere);
  \draw[current plane,#1] (\angA:\RadiusSphere) arc (\angA:\angB:\RadiusSphere);
}

%% document-wide tikz options and styles

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

\begin{document}

\begin{tikzpicture} % "THE GLOBE" showcase
\def\RadiusSphere{4} % sphere radius
\def\angEl{20} % elevation angle
\def\angAz{-20} % azimuth angle

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

\pgfmathsetmacro\H{\RadiusSphere*cos(\angEl)} % distance to north pole
\coordinate (O) at (0,0);
\node[circle,draw,black,scale=0.3] at (0,0) {};
\draw[right] node at (0,0){O};
\coordinate[mark coordinate] (N) at (0,\H);
\draw[left] node at (0,\H){N};
\coordinate[mark coordinate] (S) at (0,-\H);
\draw[left] node at (0,-\H){S};
\draw[thick, dashed, black](N)--(S);

\tikzset{
    every path/.style={
        color=green!50!black
    }
}
\DrawLatitudeCircle[\RadiusSphere]{0}
\tikzset{
    every path/.style={
        color=black
    }
}


\DrawLatitudeArc[blue]{30}{-90}{90}

\DrawLatitudeArc[blue]{20}{-200}{20}



\LongitudePlane[angle]{\angEl}{-80};
\DrawLongitudeArc[red]{-80}{-90}{90}
\path[angle] (00:\RadiusSphere) coordinate (Pprime);
\draw[right] node at (Pprime){$P'$};


\LongitudePlane[angel]{\angEl}{-120};
\DrawLongitudeArc[blue]{-120}{-90}{90}
\path[angel] (00:\RadiusSphere) coordinate (Oprime);
\draw[left] node at (Oprime){$O'$};

\def\arcrad{2}
\NewLatitudePlane[equator]{\RadiusSphere}{\angEl}{00};
\draw[equator,-,red,dashed] (-120:\arcrad) arc (-120:-80:\arcrad);
\path[equator] (-120:\arcrad) coordinate (m);
\draw[left] node at (m){$m$};
\path[equator] (-80:\arcrad) coordinate (mprime);
\draw[right] node at (mprime){$m'$};

\draw[-,dashed] (Oprime) -- (O) -- (Pprime);

\end{tikzpicture}

\end{document}

在此处输入图片描述

相关内容