答案1
这是一个可行的方法。它有很多计算,但它们很简单(我希望)并且相当重复。
\documentclass {standalone}
\usepackage {tikz}
\usetikzlibrary{3d}
\usetikzlibrary{calc}
\usetikzlibrary{math}
% isometric axes
\pgfmathsetmacro\xx{1/sqrt(2)}
\pgfmathsetmacro\xy{1/sqrt(6)}
\pgfmathsetmacro\zy{sqrt(2/3)}
% some functions (cross products)
\tikzmath%
{%
function crossx(\mx,\my,\mz,\nx,\ny,\nz)
{% cross product, x coordinate, normailized
\pxx = \my*\nz-\mz*\ny;
\pyy = \mz*\nx-\mx*\nz;
\pzz = \mx*\ny-\my*\nx;
return {\pxx/sqrt(\pxx*\pxx+\pyy*\pyy+\pzz*\pzz)};
};
function crossy(\mx,\my,\mz,\nx,\ny,\nz)
{% cross product, y coordinate, normailized
\pxx = \my*\nz-\mz*\ny;
\pyy = \mz*\nx-\mx*\nz;
\pzz = \mx*\ny-\my*\nx;
return {\pyy/sqrt(\pxx*\pxx+\pyy*\pyy+\pzz*\pzz)};
};
function crossz(\mx,\my,\mz,\nx,\ny,\nz)
{% cross product, z coordinate, normailized
\pxx = \my*\nz-\mz*\ny;
\pyy = \mz*\nx-\mx*\nz;
\pzz = \mx*\ny-\my*\nx;
return {\pzz/sqrt(\pxx*\pxx+\pyy*\pyy+\pzz*\pzz)};
};
}
\newcommand{\greatcircle}[6] % pole x, y, z, color, two orientation factors (+1/-1)
{%
\coordinate (P) at (#1,#2,#3); % pole
\coordinate (N) at ($(0,0,0)!#6*1.25cm!(P)$); % these points are
\coordinate (S) at ($-1*(N)$); % used to clip the
\coordinate (E) at ($(0,0,0)!-1.25cm!270:(P)$); % ellipses
\coordinate (W) at ($-1*(E)$); % ...
\coordinate (NW) at ($(N)+(W)$);
\coordinate (NE) at ($(N)+(E)$);
\coordinate (SW) at ($(S)+(W)$);
\coordinate (SE) at ($(S)+(E)$);
\pgfmathsetmacro\ptheta{atan(#2/#1)} % pole, spherical coordinate theta
\pgfmathsetmacro\pphi {#5*acos(#3)} % pole, spherical coordinate phi
\begin{scope}
\clip (W) -- (SW) -- (SE) -- (E) -- cycle;
\draw[rotate around z=\ptheta,rotate around y=\pphi,%
canvas is xy plane at z=0,#4] (0,0) circle (1);
\end{scope}
\begin{scope}
\clip (W) -- (NW) -- (NE) -- (E) -- cycle;
\draw[rotate around z=\ptheta,rotate around y=\pphi,%
canvas is xy plane at z=0,#4,densely dotted] (0,0) circle (1);
\end{scope}
}
\begin{document}
\begin{tikzpicture}[line cap=round,line join=round,scale=2,%
x={({-\xx cm,-\xy cm})},y={(\xx cm,-\xy cm)},z={(0 cm,\zy cm)}]
% points A, B, C in spherical coordinates
\def\atheta{55}
\def\aphi {30}
\def\btheta{10}
\def\bphi {85}
\def\ctheta{70}
\def\cphi {80}
% points A, B, C in cartesian coordinates
\pgfmathsetmacro\ax{cos(\atheta)*sin(\aphi)}
\pgfmathsetmacro\ay{sin(\atheta)*sin(\aphi)}
\pgfmathsetmacro\az{cos(\aphi)});
\pgfmathsetmacro\bx{cos(\btheta)*sin(\bphi)}
\pgfmathsetmacro\by{sin(\btheta)*sin(\bphi)}
\pgfmathsetmacro\bz{cos(\bphi)});
\pgfmathsetmacro\cx{cos(\ctheta)*sin(\cphi)}
\pgfmathsetmacro\cy{sin(\ctheta)*sin(\cphi)}
\pgfmathsetmacro\cz{cos(\cphi)});
% polar points P, Q, R in cartesian coordinates
\pgfmathsetmacro\px{crossx(\ax,\ay,\az,\bx,\by,\bz)}
\pgfmathsetmacro\py{crossy(\ax,\ay,\az,\bx,\by,\bz)}
\pgfmathsetmacro\pz{crossz(\ax,\ay,\az,\bx,\by,\bz)}
\pgfmathsetmacro\qx{crossx(\cx,\cy,\cz,\ax,\ay,\az)}
\pgfmathsetmacro\qy{crossy(\cx,\cy,\cz,\ax,\ay,\az)}
\pgfmathsetmacro\qz{crossz(\cx,\cy,\cz,\ax,\ay,\az)}
\pgfmathsetmacro\rx{crossx(\bx,\by,\bz,\cx,\cy,\cz)}
\pgfmathsetmacro\ry{crossy(\bx,\by,\bz,\cx,\cy,\cz)}
\pgfmathsetmacro\rz{crossz(\bx,\by,\bz,\cx,\cy,\cz)}
% triangles
\greatcircle{\ax}{\ay}{\az}{red} { 1}{1}
\greatcircle{\bx}{\by}{\bz}{red} { 1}{1}
\greatcircle{\cx}{\cy}{\cz}{red} { 1}{1}
\greatcircle{\px}{\py}{\pz}{blue}{-1}{1}
\greatcircle{\qx}{\qy}{\qz}{blue}{ 1}{1}
\greatcircle{\rx}{\ry}{\rz}{blue}{-1}{1}
% sphere and axes
\draw (0,0,0) circle (1 cm);
\draw[gray,dashed] (0,0,0) -- (1,0,0);
\draw[gray,dashed] (0,0,0) -- (0,1,0);
\draw[gray,dashed] (0,0,0) -- (0,0,1);
\draw[gray,-latex] (1,0,0) -- (1.5,0,0) node (X) [left] {$x$};
\draw[gray,-latex] (0,1,0) -- (0,1.5,0) node (Y) [right] {$y$};
\draw[gray,-latex] (0,0,1) -- (0,0,1.5) node (Z) [above] {$z$};
% points
\fill[blue] (\ax,\ay,\az) circle (0.5pt) node [above] {$A$};
\fill[blue] (\bx,\by,\bz) circle (0.5pt) node [below] {$B$};
\fill[blue] (\cx,\cy,\cz) circle (0.5pt) node [below left] {$C$};
\fill[red] (\px,\py,\pz) circle (0.5pt) node [below right] {$C'$};
\fill[red] (\qx,\qy,\qz) circle (0.5pt) node [left] {$B'$};
\fill[red] (\rx,\ry,\rz) circle (0.5pt) node [above left] {$A'$};
\fill[gray] (0,0,0) circle (0.5pt) node [left] {$O$};
\end{tikzpicture}
\end{document}
一点解释。首先,为简单起见,我使用单位球体,数据点以球面坐标提供。然后这里的关键是极点。给定球体上的两个点,我们寻找通过它们的大圆,以及如果所述圆周是赤道的话将是北极的点。设A(ax,ay,az)
和B(bx,by,bz)
为点,然后我们可以计算叉积(抱歉,没有 MathJax):
| i j k |
v = A x B = | ax ay az |
| bx by bz |
上述向量v
将为我们提供找到北极的方向,如果我们对其进行归一化(除以其模数),新向量u
将准确指向极点(C'
在我的绘图中)。但这还不是全部,因为这个u
球坐标中的向量将为 tikz 3d 中包含赤道(穿过A
和的大圆B
)的新画布提供角度。由于透视,我们将圆视为椭圆,其半长轴垂直于的投影u
,因此再次,可以使用向量来裁剪椭圆并分离可见部分和不可见部分。