我对在 3D 空间中表示的 2D 表面上的反向剪辑存在问题。
虽然反向剪切有效,但剪切部分并未投影在平面上。
以下是 MWE:
\documentclass{standalone}
\usepackage{amsmath, amssymb}
\usepackage{graphicx}
\usepackage{tikz}
\usetikzlibrary{arrows,decorations.pathmorphing}
\usepackage{tikz-3dplot}
\usetikzlibrary{arrows}
\usetikzlibrary{calc}
\usetikzlibrary{shadings}
\tikzset{>=latex}
\tdplotsetmaincoords{70}{120}
%Cavity
\def \xcav {5}
\def \zcav {5}
\def \ycav {2}
\tikzset{
invclip/.style={clip,insert path={{[reset cm]
(-16383.99999pt,-16383.99999pt) rectangle (16383.99999pt,16383.99999pt)
}}}
}
\begin{document}
\begin{tikzpicture}
[
scale=1,
tdplot_main_coords
]
% Cavity
\draw (-\xcav/2,-\ycav,-\zcav/2) --++ (\xcav,0,0) --++ (0,0,\zcav) --++ (-\xcav,0,0) -- cycle;
\draw (-\xcav/2,-\ycav,-\zcav/2) --++ (0,\ycav,0) --++ (0,0,\zcav) --++ (0,-\ycav,0) -- cycle;
\draw (-\xcav/2,-\ycav,-\zcav/2) --++ (0,\ycav,0) --++ (\xcav,0,0) --++ (0,-\ycav,0) -- cycle;
\begin{scope}[canvas is xz plane at y=0]
\begin{pgfinterruptboundingbox} % useful to avoid the rectangle in the bounding box
\path[invclip](0,0) circle (0.25);
\end{pgfinterruptboundingbox}
\shadedraw[clip] (-\xcav/2,-\zcav/2) --++ (\xcav,0) --++ (0,\zcav) --++ (-\xcav,0) -- cycle;
\end{scope}
\draw (\xcav/2,-\ycav,-\zcav/2) --++ (0,\ycav,0) --++ (0,0,\zcav) --++ (0,-\ycav,0) -- cycle;
\draw (-\xcav/2,-\ycav,+\zcav/2) --++ (0,\ycav,0) --++ (\xcav,0,0) --++ (0,-\ycav,0) -- cycle;
\end{tikzpicture}
\end{document}
有什么想法吗 ?
答案1
一些含糊不清的话:
反转裁剪的显著解决方案是插入尽可能大的路径。目前限制与 TeX 的尺寸有关:大约 2 14 pt。但是,用户可能进行了一些转换,因此勉强有效的路径(例如(-16383pt,16383pt)rectangle(16383pt,16383pt)
)肯定会超出限制。
这就是它reset cm
出现的原因:它会重置所有变换并保证有效路径仍然有效。然而,缺点也很明显。重置后,用户要么需要重建变换,要么在没有变换的情况下更加努力。
因此,解决剪切反转的一个好办法应该是限制 的范围reset cm
,这就是为什么您会在 处看到双括号insert path={{
。但它不起作用,可能是因为该值在宏之间传递了太多次,最终 TeX 会“剥去”所有括号。
解决这个问题的方法是添加更多括号。实验表明四个括号就足够了。所谓足够,我的意思是结果确实发生了变化:圆圈不会被投影的圆圈取代,而是消失。
事实证明,范围会影响绕数的计算。由于非零规则默认为clip
,因此大路径内的所有内容都会被保留,使得裁剪毫无意义。
解决方案是添加预定义选项
clip even odd rule/.code={\pgfseteorule}, % Credit to Andrew Stacey`
insert path
实验表明
invclip/.style={
clip,insert path=
[clip even odd rule]{
[reset cm](-16383.99999pt,-16383.99999pt) rectangle (16383.99999pt,16383.99999pt)
}
}
神奇的是,现在不再需要牙套了。
完整代码
\documentclass{standalone}
\usepackage{amsmath, amssymb}
\usepackage{graphicx}
\usepackage{tikz}
\usetikzlibrary{arrows,decorations.pathmorphing}
\usepackage{tikz-3dplot}
\usetikzlibrary{arrows}
\usetikzlibrary{calc}
\usetikzlibrary{shadings}
\tikzset{>=latex}
\tdplotsetmaincoords{70}{120}
%Cavity
\def \xcav {5}
\def \zcav {5}
\def \ycav {2}
\tikzset{
clip even odd rule/.code={\pgfseteorule},
invclip/.style={clip,insert path=[clip even odd rule]{[reset cm]
(-16383.99999pt,-16383.99999pt) rectangle (16383.99999pt,16383.99999pt)
}}}
\begin{document}
\begin{tikzpicture}
[
scale=1,
tdplot_main_coords
]
% Cavity
\draw (-\xcav/2,-\ycav,-\zcav/2) --++ (\xcav,0,0) --++ (0,0,\zcav) --++ (-\xcav,0,0) -- cycle;
\draw (-\xcav/2,-\ycav,-\zcav/2) --++ (0,\ycav,0) --++ (0,0,\zcav) --++ (0,-\ycav,0) -- cycle;
\draw (-\xcav/2,-\ycav,-\zcav/2) --++ (0,\ycav,0) --++ (\xcav,0,0) --++ (0,-\ycav,0) -- cycle;
\begin{scope}[canvas is xz plane at y=0]
\begin{pgfinterruptboundingbox} % useful to avoid the rectangle in the bounding box
\path[invclip](0,0) circle (0.25);
\end{pgfinterruptboundingbox}
\shadedraw[clip] (-\xcav/2,-\zcav/2) --++ (\xcav,0) --++ (0,\zcav) --++ (-\xcav,0) -- cycle;
\end{scope}
\draw (\xcav/2,-\ycav,-\zcav/2) --++ (0,\ycav,0) --++ (0,0,\zcav) --++ (0,-\ycav,0) -- cycle;
\draw (-\xcav/2,-\ycav,+\zcav/2) --++ (0,\ycav,0) --++ (\xcav,0,0) --++ (0,-\ycav,0) -- cycle;
\end{tikzpicture}
\end{document}