我正在努力绘制一个平面和一条相交线。我希望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}