评论

评论

我正在使用基于 Tomas M. Trzeciak 的代码立体和圆柱地图投影示例绘制球体。

我在球体上添加了三个大圆:赤道和两个经度圆。我想用点标记赤道和另外两个大圆的(正面)交点(就像我对天顶和天底所做的那样),并将它们标记为 A 和 B。为此,我可能需要以某种方式使用圆的交点坐标。我该怎么做?

这是 MWE。

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

%% Helper macros

\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/.estyle={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/.estyle={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][2]{
  \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{2.5} % sphere radius
\def\angEl{25} % elevation angle
\filldraw[ball color=white] (0,0) circle (\R);
\DrawLatitudeCircle[\R]{0}
\DrawLongitudeCircle[\R]{-110}
\DrawLongitudeCircle[\R]{-50}

\pgfmathsetmacro\H{\R*cos(\angEl)} % distance to north pole
\coordinate (O) at (0,0);
\coordinate[mark coordinate] (Z) at (0,\H);
\coordinate[mark coordinate] (N) at (0,-\H);

\draw[->] (0,-\H) -- (0,1.2*\R) node[above] {Zenith};
\draw[dashed] (0,-\H) -- (0,-\R);
\draw (0,-\R) -- (0,-1.2*\R) node[below] {Nadir};

\end{tikzpicture}

\end{document}

它生成下面的图像(没有明显的修改):

在此处输入图片描述

答案1

以下是使用该库的可能性intersections

在此处输入图片描述

我重新定义了\DrawLongitudeCircle\DrawLatitudeCircle增加了一个强制参数,用于命名路径;命名完成后,intersections将使用该库来获取路径之间的交点。

代码:

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

%% Helper macros

\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[3][1]{
  \LongitudePlane{\angEl}{#2}
  \tikzset{current plane/.prefix style={scale=#1}}
   % angle of "visibility"
  \pgfmathsetmacro\angVis{atan(sin(#2)*cos(\angEl)/sin(\angEl))} %
  \draw[name path=#3,current plane] (\angVis:1) arc (\angVis:\angVis+180:1);
  \draw[name path=dashed#3,current plane,dashed] (\angVis-180:1) arc (\angVis-180:\angVis:1);
}

\newcommand\DrawLatitudeCircle[3][2]{
  \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[name path=#3,current plane] (\angVis:1) arc (\angVis:-\angVis-180:1);
  \draw[name path=dashed#3,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},%
smalldot/.style={
  fill,
  circle,
  inner sep=1.5pt
  }
}

\begin{document}

\begin{tikzpicture} % "THE GLOBE" showcase

\def\R{2.5} % sphere radius
\def\angEl{25} % elevation angle
\filldraw[ball color=white] (0,0) circle (\R);
\DrawLatitudeCircle[\R]{0}{lat}
\DrawLongitudeCircle[\R]{-110}{lon1}
\DrawLongitudeCircle[\R]{-50}{lon2}

% We find the intersection points and then draw little filled circles at them    
\path[name intersections={of= lat and lon1,by={a}}];
\path[name intersections={of= lat and lon2,by={b}}];
\node[smalldot,label={above right:$A$}] at (a) {};
\node[smalldot,label={above left:$B$}] at (b) {};

\pgfmathsetmacro\H{\R*cos(\angEl)} % distance to north pole
\coordinate (O) at (0,0);
\coordinate[mark coordinate] (Z) at (0,\H);
\coordinate[mark coordinate] (N) at (0,-\H);

\draw[->] (0,-\H) -- (0,1.2*\R) node[above] {Zenith};
\draw[dashed] (0,-\H) -- (0,-\R);
\draw (0,-\R) -- (0,-1.2*\R) node[below] {Nadir};

\end{tikzpicture}

\end{document}

评论

对于 PGF/TikZ 版本 3.0,必须修改原始问题中给出的代码,通过更改(如我的示例代码中所示)以产生所需的estyle结果style

  \tikzset{#1/.estyle={cm={\cost,\sint*\sinEl,0,\cosEl,(0,0)}}}

  \tikzset{#1/.estyle={cm={\cost,0,0,\cost*\sinEl,(0,\yshift)}}} %

无论如何,我的解决方案适用于任何版本 > 2.10。

答案2

值得一提的是,这是一个版本元帖子

在此处输入图片描述

使用构造很容易找到交点intersectionpoint。但正如您所看到的,我有点作弊,将北极和南极保持在顶部和底部。要像您的示例一样自由旋转图形,需要计算出所有投影,这在普通 MP 中会有点繁琐(但并非不可能)。

prologues := 3;
outputtemplate := "%j%c.eps";

beginfig(1);

path outline, equator, prime_meridian, ninety_meridian;

r := 100;
outline := fullcircle scaled 2r;

n := 40;
for i = 0 upto n:
  fill outline scaled (1-3i/4n) shifted (-i*r/2.8n,i*r/2.8n) withcolor (0.5+i/1.6n)*white;
endfor

equator         = outline yscaled 0.14;
prime_meridian  = outline xscaled 0.54;
ninety_meridian = outline xscaled 0.84;

drawoptions(dashed withdots withcolor .3 white);
draw subpath(0,4) of equator; 
draw subpath(-2,2) of prime_meridian;
draw subpath(2,6) of ninety_meridian;

drawoptions(dashed evenly withcolor .3 white);
draw r*down -- r*up;

drawoptions();
draw subpath(4,8) of equator;
draw subpath(2,6) of prime_meridian;
draw subpath(-2,2) of ninety_meridian;

dotlabel.urt ("A",subpath  (3,5) of prime_meridian  intersectionpoint subpath (4,6) of equator);
dotlabel.ulft("B",subpath (-1,1) of ninety_meridian intersectionpoint subpath (6,8) of equator);

drawarrow r*up   -- 1.2r*up;
draw      r*down -- 1.2r*down;

label.top("Zenith",1.2r*up);
label.bot("Nadir", 1.2r*down);

endfig;
end.
enter code here

相关内容