Tikz:线与平面的交点

Tikz:线与平面的交点

我正在努力绘制一个平面和一条相交线。我希望C,P',P图像中的线条在“平面后面”时消失,在不再位于平面后面时重新出现。

我想要得到的结果

现在,我通过将线分成两段来解决这个问题。

以下是 MWE:

\documentclass{minimal}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw[->] (0,0) node[anchor=east]{C} -- (5,0)node[anchor=west] {Z};
\draw[->] (0,0) -- (0,3)node[anchor=south] {Y};
\draw[->] (-1.0,-1.0) -- (1.5,1.5)node[anchor=west] {X};
\draw (0,0) -- (3,1.2);
\filldraw[fill=lightgray] (2.5,-2.5) -- (2.5,1) --  (4,3) -- (4,-0.5) -- (2.5,-2.5);
\draw[->] (3.25,0) -- (3.25,0.75)node[anchor=south] {y};
\draw[->] (3.25,0) -- (3.5,0.5)node[anchor=west] {x};
\draw[->] (3.25,0) -- (5,0);
\draw (3,1.2) -- (5,2);
\fill (5,2) circle[radius=2pt] node[anchor=south] {P};
\fill (3,1.2) circle[radius=2pt] node[anchor=south] {P'};
\draw ((2.5,-2.5)node[anchor=west, font=\footnotesize] {image plane};
\end{tikzpicture}
\end{document}

但是,我相信这个问题一定有一个更简单的解决方案,因为这现在需要相当多烦人的手工计算。所以我的问题是:

绘制与平面相交的线的最简单方法是什么?

答案1

在 TikZ 中自动执行此操作很复杂,因为 TikZ 不是 3D 感知软件包。它按照您绘制的顺序绘制事物,几乎没有能力自动删除已经存在的东西“后面”的东西。有“图层”,但这些只是重新排序绘制事物的一种方式,并没有解决这个根本问题。

因此,当您有诸如 z 轴和线之类的东西时,它们在平面之前和之后都有绘制部分,您必须将它们分成两部分绘制。我不知道有什么办法可以解决这个问题(即使使用剪辑也需要绘制两次)。因此,您需要某种方式告诉 TikZ 在哪里进行中断。由于它本质上是一个 2D 包,它不知道如何计算线和平面的交点,因此不知道何时停止绘制线。所以你必须告诉它。

幸运的是,在经历了所有这些厄运和忧郁之后,你使用 3D 坐标来指定 TikZ 中的点。这些点会立即转换为 2D 坐标进行绘图,但在 3D 坐标中指定交点比在 2D 坐标中指定交点要容易得多,尤其是在此示例中。

以下是我使用 3D 坐标绘制图表的方法。由于您的框架不是通常的 TikZ 框架(基本上,您已经围绕 y 轴旋转),因此我需要在开始时调整框架。不要太担心这一点。

然后主要的事情是整理出哪些部分是在平面后面绘制的,哪些是在前面绘制的。现在,我已经使用了layer在这里使用了 PGF 的功能,它允许我根据指定顺序调整绘制顺序。这意味着我可以将 Z 轴的两个部分放在代码中,使其更易于维护。为此,我借用了TikZ 中的“Z 级别”(作者说我可以)使图片代码更简单。 里面的所有内容都\makeatletter ... \makeatother可以用图片代码更拥挤来弥补。

\documentclass{article}
%\url{https://tex.stackexchange.com/q/104529/86}
\usepackage{tikz}

\makeatletter
\tikzset{
  xyz frame/.code n args={3}{%
    \begingroup
    \tikz@scan@one@point\pgfutil@firstofone#1\relax
    \pgf@xa=\pgf@x
    \pgf@ya=\pgf@y
    \tikz@scan@one@point\pgfutil@firstofone#2\relax
    \pgf@xb=\pgf@x
    \pgf@yb=\pgf@y
    \tikz@scan@one@point\pgfutil@firstofone#3\relax
    \edef\tikz@marshall{\noexpand\endgroup\noexpand\pgfsetxvec{\noexpand\pgfpoint{\the\pgf@xa}{\the\pgf@ya}}%
      \noexpand\pgfsetyvec{\noexpand\pgfpoint{\the\pgf@xb}{\the\pgf@yb}}%
      \noexpand\pgfsetzvec{\noexpand\pgfpoint{\the\pgf@x}{\the\pgf@y}}}%
    \tikz@marshall
  },
  on layer/.code={
    \pgfonlayer{#1}\begingroup
    \aftergroup\endpgfonlayer
    \aftergroup\endgroup
  },
}
\makeatother

\pgfdeclarelayer{behind}
\pgfdeclarelayer{in front}
\pgfsetlayers{behind,main,in front}

\begin{document}
\begin{tikzpicture}[xyz frame={(0,0,-1)}{(0,1,0)}{(1,0,0)}]
\draw[on layer=behind] (0,0,0) node[anchor=east]{C} -- (0,0,3);
\draw[->,on layer=in front] (0,0,3) -- (0,0,5)node[right] {Z};
\draw[->] (0,0,0) -- (0,5,0)node[above] {Y};
\draw[->] (-3,0,0) -- (5,0,0)node[above right] {X};
\filldraw[fill=lightgray] (2.5,-2.5,3) -- (2.5,2.5,3) --  (-2.5,2.5,3) -- (-2.5,-2.5,3) -- cycle;
\draw[->] (0,0,3) -- +(0,1,0) node[above] {y};
\draw[->] (0,0,3) -- +(1,0,0) node[right] {x};
\draw[on layer=behind] (0,0,0) -- (-1,2,3);
\draw[on layer=in front]  (-1,2,3) -- (-2,4,6);
\fill (-2,4,6) circle[radius=2pt] node[anchor=south] {P};
\fill (-1,2,3) circle[radius=2pt] node[anchor=south] {P'};
\draw (-2.5,-2.5,3)node[right, font=\footnotesize] {image plane};
\end{tikzpicture}
\end{document}

有一条线穿过的平面

相关内容