如何应用 PGF 阴影?

如何应用 PGF 阴影?

请考虑以下 LaTeX 手稿,其中有一张高大的彩虹阴影矩形的 TikZ 图片。该代码基本上是从 TikZ & PGF 手册 3.0.1a 版第 109 章(“阴影”)第 109.3 小节(“使用阴影”)末尾的示例中复制粘贴的,第 1088 页。

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
    \pgfdeclareverticalshading{rainbow}{100bp}{color(0bp)=(red); color(25bp)=(red); color(35bp)=(yellow); color(45bp)=(green); color(55bp)=(cyan); color(65bp)=(blue); color(75bp)=(violet); color(100bp)=(violet)}
    \begin{tikzpicture}[shading=rainbow]
        \shade[shading angle=90] (3,0) rectangle +(1,2);
    \end{tikzpicture}
\end{document}

生成的图像(未按比例)

                                                  彩虹阴影矩形

这个矩形的阴影范围从左边的紫色到右边的红色。我不明白为什么会这样。在我看来,它应该从蓝色到黄色。我根据第\pgfshadepath{〈shading name〉}{〈angle〉}1085-1086 页上的命令描述中给出的阴影算法得出这个观点:

首先,PGF 将设立本地范围。

其次,它使用当前路径来剪切此范围内的所有内容。但是,当前路径在范围之后再次可用,因此可以使用它来描边。

现在,应该〈shading name〉是宽度和高度为 100 bp 的阴影,即 100 个大点。PGF 查看当前路径的边界框。计算路径时会自动计算此边界框;但是,有时它可能(相当)太大,尤其是涉及复杂曲线时。

在范围内,修改了低级变换矩阵。阴影的中心被平移(移动),使其位于路径边界框的中心。低级坐标系也被缩放,使得阴影“覆盖”路径(细节有点复杂,见下文)。然后,坐标系旋转〈angle〉

最后,如果已使用宏\pgfsetadditionalshadetransform,则应用额外的转换。

所有设置完毕后,插入阴影。

如果路径和阴影始终是矩形,并且不涉及旋转,则很容易缩放阴影,使它们始终覆盖路径。但是,当垂直阴影旋转时,显然必须“放大”它,以便它仍然覆盖路径。当路径本身不是矩形时,情况会变得更糟。

由于这些原因,事情在“现实”中略有不同。阴影被缩放和平移,使得点 (50bp,50bp)(阴影中间)位于路径的中间,并且点 (25bp,25bp) 位于路径的左下角,而 (75bp,75bp) 位于右上角。

重申一下,基本步骤是:

  1. 根据规格创建一个大小为 100bpx100pb 的阴影正方形\pgfdeclareverticalshading。我将这个正方形称为背景 正方形
  2. 移动背景方块,使其中心与要着色的形状的边界框的中心重合。
  3. 缩放移位后的背景方块,使得它的子方块(其左下角位于 (25pb,25pb) 并且右上角位于 (75bp,75bp)(移位前的坐标))与要着色的形状的边界框重合。
  4. 按指定的 旋转平移和缩放的背景方块angle
  5. 按照需要着色的形状剪切生成的背景正方形。

具体来说,背景方块的旋转(步骤4)是在它被移动和缩放(步骤3)之后进行的。

让我们将其应用到我们的示例中。在旋转之前,背景方块会进行变换,使得要着色的形状顶部的颜色为紫色,而要着色的形状底部的颜色为红色。现在进行 90 度旋转,由于要着色的形状是一个又高又细的矩形,因此旋转后的背景方块的紫色和红色将落在要着色的形状之外。因此,在剪切之后,只有蓝色到黄色的光谱应该保持可见。

如果旋转是首先要执行的变换,即如果算法的第 2、3 和 4 步按如下方式排列:2->3、3->4、4->2,那么上面获得的图像对我来说是有意义的。

答案1

遮蔽当前路径,但是不丢弃它。

#1- 阴影(见下文)

#2- 一个角度

描述:

\pgfshadepath “尝试”用阴影填充当前路径。阴影的原始大小应完全覆盖 (0,0) 和 (100bp,100bp) 之间的区域。阴影将旋转 #2,然后重新缩放,以便完全覆盖路径。然后路径将(本地)用于剪辑并绘制阴影。

除了旋转之外,设置的任何变换 \pgfsetadditionalshadetransform也将应用。

完成所有这些后,该路径仍然可以用于正常的描边/剪切操作。

阴影绕其中间旋转。如果不旋转,路径的左下角将位于 (25bp, 25bp),右上角位于 (75bp, 75bp)。

例子:

\pgfdeclareverticalshading{myshading}{100bp}{color(0pt)=(red); color(100bp)=(green)}

\pgfpathmoveto{\pgforigin}
\pgfpathlineto{\pgfxy(1,0)}
\pgfpathlineto{\pgfxy(1,1)}
\pgfshadepath{myshading}{0}
\pgfusepath{stroke}

---摘自tex/generic/pgf/basiclayer/pgfcoreshade.code.tex

答案2

源代码可以最好地回答您的问题

\def\pgfshadepath#1#2{%
  \ifdim\pgf@pathminx=16000pt%
    \pgfwarning{No path specified that can be filled}%
  \else%
    \begingroup%  
      % Calculate center:
      \pgf@xb=.5\pgf@pathmaxx%
      \advance\pgf@xb by.5\pgf@pathminx%
      \pgf@yb=.5\pgf@pathmaxy%
      \advance\pgf@yb by.5\pgf@pathminy%
      % Calculate scaling:
      \pgf@xc=\pgf@pathmaxx%
      \advance\pgf@xc by-\pgf@pathminx%
      \pgf@yc=\pgf@pathmaxy%
      \advance\pgf@yc by-\pgf@pathminy%
      \pgf@xc=.01992528\pgf@xc%
      \pgf@yc=.01992528\pgf@yc%
      \ifdim\pgf@xc<0.0001pt\relax\ifdim\pgf@xc>-0.0001pt\relax\pgf@no@shadetrue\fi\fi%
      \ifdim\pgf@yc<0.0001pt\relax\ifdim\pgf@yc>-0.0001pt\relax\pgf@no@shadetrue\fi\fi%
      \ifpgf@no@shade\else%
      \pgfsys@beginscope%
        \pgfsyssoftpath@invokecurrentpath%
        \pgfsys@clipnext%
        \pgfsys@discardpath%
        % Compute new transformation matrix:
        \pgfsys@transformcm{1}{0}{0}{1}{\pgf@xb}{\pgf@yb}%
        \pgfsys@transformcm%
        {\pgf@sys@tonumber{\pgf@xc}}{0}%
        {0}{\pgf@sys@tonumber{\pgf@yc}}{0pt}{0pt}%
        \pgfmathparse{#2}%
        \let\pgfshade@angle=\pgfmathresult%
        \pgfmathsin@{\pgfshade@angle}%
        \let\pgfshade@sin=\pgfmathresult%
        \pgfmathcos@{\pgfshade@angle}%
        \let\pgfshade@cos=\pgfmathresult%
        \pgf@x=\pgfshade@sin pt%
        \pgf@xa=-\pgf@x%
        \pgfsys@transformcm{\pgfshade@cos}{\pgfshade@sin}{\pgf@sys@tonumber{\pgf@xa}}{\pgfshade@cos}{0pt}{0pt}%
        \ifx\pgf@shade@extra@transform\pgfutil@empty%
        \else%
          \pgflowlevel{\pgf@shade@extra@transform}%
        \fi%
        \pgfuseshading{#1}%
      \pgfsys@endscope%
      \fi%  
    \endgroup%
  \fi%
}
  • #1是阴影的名称;rainbow在你的情况下。
  • #2是角度;90就你的情况而言。
  • \pgf@xb\pgf@yb)是路径(BB)的中心。
  • \pgf@xc\pgf@yc)是路径(BB)的大小;单位 = 50bp。
    • .01992528 * 50 bp = 1pt
  • 变换的顺序是
    • 转移
    • 规模
    • 旋转

现在为了简单起见,假设我们有一个正方形。通过缩放,我们将其转换为一个细长的矩形。

所以问题是,如果我们将这个细长矩形旋转 90 度,它会变成细长矩形,还是宽短矩形。答案是前者。例如,尝试一下

\makeatletter
\tikz{
    \path(-3,-3)(3,3);
    \pgfsys@transformcm{.5}{0}{0}{2}{0pt}{0pt}
    \pgfsys@transformcm{0}{1}{-1}{0}{0pt}{0pt} % comment and uncomment this line
    \node[draw]{};                             % and see what happens to this *square*
    \node{ABC};
}

PGF 与此行为无关。这完全与 PDF 标准有关。也许以下 PDF 规范快照可以帮助您

相关内容