我正在尝试立体和圆柱地图投影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}