我想要一个命令,用axis
菱形图案填充该区域。菱形图案可能具有不同的偏移、比例和绘图样式,但重要的是它与轴(它是一个“图”)完全一致。它应该位于其他图的背景中,并且应该适用于 2D 和 3D 图形。
我的第一个解决方案是保存axis
环境内的坐标,然后axis
在之外的 内进行绘制pgfonlayer
。它感觉不是特别干净,但在 2D 中有效。在 3D 中,效果并不好。这是我所拥有的,我试图使其尽可能紧凑:
\documentclass{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\usetikzlibrary{3d,calc,patterns}
\pgfdeclarelayer{background}
\pgfdeclarelayer{main}
\pgfsetlayers{background,main}
\makeatletter
\def\extractcoord#1#2#3{
\path let \p1=(#3) in \pgfextra{
\pgfmathsetmacro#1{\x{1}/\pgf@xx}
\pgfmathsetmacro#2{\y{1}/\pgf@yy}
\xdef#1{#1} \xdef#2{#2}
};
}
\makeatother
\begin{document}
\begin{tikzpicture}
% \begin{scope}[
% x={(-0.7cm,0.4cm)},
% y={(.9cm,.2cm)},
% z={(0cm,1cm)},
% canvas is yx plane at z=0
% ]
\begin{pgfonlayer}{main}
\begin{axis}[axis equal, xmin=-.5, xmax=4.5, ymin=-.5, ymax=4.5]
% Save the coordinates of the axis frame and the unit of the plot
\coordinate (rel axis llc) at (rel axis cs: 0, 0);
\coordinate (rel axis urc) at (rel axis cs: 1, 1);
\coordinate (axis unit llc) at (axis cs: 0, 0);
\coordinate (axis unit urc) at (axis cs: 1, 1);
% Some genuine plotting
\addplot[black, opacity=0.5] {(x-3)^2};
% Debug:
\fill[red] (rel axis llc) circle (3pt);
\fill[red] (rel axis urc) circle (3pt);
\fill[green] (axis unit llc) circle (3pt);
\fill[green] (axis unit urc) circle (3pt);
\end{axis}
\end{pgfonlayer}
\begin{pgfonlayer}{background}
% Debug:
\fill[blue] (rel axis llc) circle (3pt);
\fill[blue] (rel axis urc) circle (3pt);
% Here we set the clip at the axis area
\clip (rel axis llc) rectangle (rel axis urc);
% Do maths to extract the same unit as it was used in the axis.
% This is probably extra cumbersome
\extractcoord{\dx}{\dy}{$(axis unit urc)-(axis unit llc)$}
\extractcoord{\minx}{\miny}{$(rel axis llc)-(axis unit llc)$}
\extractcoord{\maxx}{\maxy}{$(rel axis urc)-(axis unit llc)$}
\pgfmathsetmacro{\minx}{div(\minx, \dx) - 1)}
\pgfmathsetmacro{\miny}{div(\miny, \dy) - 1)}
\pgfmathsetmacro{\maxx}{div(\maxx, \dx) + 1)}
\pgfmathsetmacro{\maxy}{div(\maxy, \dy) + 1)}
\makeatletter
\pgfmathsetlengthmacro{\ux}{\dx * \pgf@xx}
\pgfmathsetlengthmacro{\uy}{\dy * \pgf@yy}
\makeatother
% Shift at the same position and set the correct unit
\begin{scope}[shift={(axis unit llc)}, x=\ux, y=\uy, xstep=1, ystep=1]
% Here goes the diamond writing code, will just use a rectangle
\draw [pattern=north west lines, pattern color=blue, opacity=0.3]
(\minx, \miny) rectangle (\maxx, \maxy);
\draw [pattern=north east lines, pattern color=green, opacity=0.3]
(0, 0) rectangle (1, 1);
\end{scope}
\end{pgfonlayer}
% \end{scope}
\end{tikzpicture}
\end{document}
这是我得到的(没问题):
目标是这样的(这就是为什么我需要轴框架和单位正方形),但我不想用菱形代码使 MVE 膨胀:
事实上,我根据这个创建了一个环境,因为我需要多次复制它。现在,如果我尝试在 3D 中执行此操作,环境外的比例就会关闭。如果我启用上面示例中注释掉的,axis
就会发生这种情况:scope
我真的不明白发生了什么,导致我在使用 3D 图形时保存的坐标“改变视在位置”,而且我认为我缺乏有关 PGF 和 TikZ 的知识,无法找到更可靠的方法来做到这一点。
对于如何重新设计整个项目的任何解释或建议都将不胜感激。
答案1
正如评论中提到的,这已经在这里回答本质上,解决方案不是保存轴环境几何图形以供将来使用,而是使用以下方法直接绘制到轴环境中execute at begin axis
:
\pgfplotsset{draw xy background/.style={%
execute at begin axis={
% Get the axis area and populate macros \myxmin, \myxmax, \myymin, \myymax
\pgfplotsset{get xy window}%
% Drawing code that uses the macros above.
% Here you can use the (axis cs: X, Y) reference frame
}
}
可以像这样使用:
\begin{axis}[xmin=-.5, xmax=4.5, ymin=-.5, ymax=4.5, draw xy background]
% ... ^^^^^^^^^^^^^^^^^^
\end{axis}
这个get xy window
密钥非常有趣,因为它使用 pgfplots 的一些内部函数来获取轴面积:
\makeatletter
\pgfplotsset{
get xy window/.code={%
% Enable floating point processing
\pgfkeys{/pgf/fpu}
% Convert each internal macro of pgfplots into fixed point
% representation and store the result of that operation into
% the corresponding \myXXXX macro
\pgfmathfloattofixed{\pgfplots@xmax}\let\myxmax\pgfmathresult
\pgfmathfloattofixed{\pgfplots@xmin}\let\myxmin\pgfmathresult
\pgfmathfloattofixed{\pgfplots@ymax}\let\myymax\pgfmathresult
\pgfmathfloattofixed{\pgfplots@ymin}\let\myymin\pgfmathresult
% Disable floating point
\pgfkeys{/pgf/fpu=false}
}
}
\makeatother
我不确定为什么它需要浮点引擎,但我猜测\pgfplots@xmax
其他宏实际上都是浮点数,所以我们需要明确将它们转换为固定值。
请注意,由于绘图代码现在运行之内轴环境,我们可以用来rel axis cs:
引用轴边界。但是,由于在这个特定情况下,我需要分别绘制每个 x 和 y,因此使用和朋友比上面定义的宏\pgfplots@minx
要方便得多。\extractcoord
此外,如果在其他地方没有使用,我们可以通过将的代码拉入get xy window
来将所有内容压缩为单个密钥。get xy window
execute at begin axis