我有一个文档,其中包含一些 TikZ 图像,这些图像是由我编写的程序自动生成的。所有图像都非常相似,并且每个图像都包含大量具有不同、任意 RGB 颜色的方块。我的问题是:给这么多的正方形涂上颜色的最好方法是什么?
到目前为止,我使用的方法是fillcolor
在绘制每个正方形之前使用宏定义颜色\definecolor
,然后使用该颜色填充正方形。这意味着每次绘制新正方形时,我都会fillcolor
再次定义。
但是,我不太确定这是不是可行的方法。pdflatex 在编译文档时似乎需要大量内存,而且出于某种奇怪的原因,如果我包含超过 5 张图像,内存就会耗尽(即使我将内存量从 5 张增加到 6 张时增加了十倍)。它是否有可能存储我定义的所有颜色,我需要让 pdflatex 在再次fillcolor
调用之前“忘记”这些颜色\definecolor
?
更新:下面是我想要在文档中包含的 TikZ 图像之一的示例(它是使用有限体积法和流体体积法对两相流体模拟中的相分数场进行可视化,是的,我知道,流体界面并不十分清晰):
此特定图像由 1990 个填充正方形和 4 个未填充正方形组成。
首先,对于每个正方形,fillcolor
定义为\definecolor
,并且正方形用该颜色填充:
\definecolor{fillcolor}{rgb}{1.000000,0.241735,0.000000}
\fill[fillcolor] (0.203125,0.578125) rectangle (0.218750,0.593750);
然后画出每个正方形的边,例如
\draw (0.203125,0.578125) rectangle (0.218750,0.593750);
答案1
正如我在评论中所说,如果\definecolor
只是将颜色定义存储在 TeX 宏中,那么重新定义它将回收相同的宏,因此不会使用更多内存。
但是,也有可能正在\defincolor
推送某种文字 PDF 代码,该代码定义 PDF 引擎的颜色。在这种情况下,据我所知,不应使用更多内存来多次重新定义相同的颜色。
无论如何,为了以防万一,可以使用没有预先定义的 RGB 颜色。方法如下。
原则上,
tikz
识别形式为 的颜色规范{rgb:red,255;green,255;blue:255}
。但它的解释并不像人们所期望的那样。例如,[fill={rgb:red,255;green,255;blue,0}]
不会产生黄色,而是产生黑色调的黄色(见下图)。我找不到有关此规范如何工作的文档。显然,所有red
、green
、blue
值都被相加,然后将每个特定值除以总数。也就是说,我们指定的不是绝对字节值,而是相对权重。因此,要获得黄色,我们可以写:{rgb:red,1;green:1;blue:-1}
。我发现这种语法相当不方便(此外,我们怎么才能得到“白色”?)PGF 使用内部宏:,其行为符合预期。它接收、和组件
\pgfsys@color@rgb@fill
的三个数值,范围为 0-255。因此,我们可以使用此宏在填充命令之前设置填充颜色。r
g
b
以下代码显示了几个选项:
\documentclass{article}
\usepackage{tikz}
% Define a more convenient macro without @ in its name
\makeatletter
\def\fillRGB#1#2#3{\pgfsys@color@rgb@fill{#1}{#2}{#3}}
\makeatother
\begin{document}
% Standard xcolor defined color
\definecolor{RGByellow}{RGB}{255,255,0}
% Some examples
\tikz{\node[draw,fill=RGByellow]{defined colour};}
\tikz{\node[draw,fill={rgb:red,255;green,255;blue,0}]{Tikz rgb: 255,255,0};}
\tikz{\node[draw,fill={rgb:red,1;green,1;blue,-1}]{Tikz rgb: 1,1,-1};}
\tikz{\fillRGB{255}{255}{0}\node[fill,draw]{{\tt fillRGB: 255,255,0} };}
\end{document}
结果:
答案2
我认为您的方法\definecolor
是好的。
我的建议是使用 PGF 基本层而不是 tikz,即使用类似
\definecolor{fillcolor}{...}
\pgfsetfillcolor{fillcolor}
\pgfsetstrokecolor{fillcolor!80!black}
\pgfpathrectangle{...}{...}
\pgfusepathqfillstroke
% next one, no scope in-between...
\definecolor{fillcolor}{...}
\pgfsetfillcolor{fillcolor}
\pgfsetstrokecolor{fillcolor!80!black}
\pgfpathrectangle{...}{...}
\pgfusepathqfillstroke
请查找 pgfmanual.pdf 中提到的命令,因为我可能拼写错误了其中一些(我凭记忆引用的)。
我的建议是将描边和填充路径结合起来,只改变颜色,这可能对你有意义,也可以应用于 tikz 路径。这还可以减少内存消耗和排版时间。
有一条评论实际上超出了你的问题的范围:我建议使用绘制颜色,这fillcolor!80!black
是受默认颜色的启发pgfplots
,我发现与黑色轮廓相比,默认颜色不那么刺眼。而 pgfplots 具有与此处相同的用例:你在此处编写的实际上是一种具有多面阴影和显式颜色输入的网格/曲面(在 pgfplots 中:\addplot3[surf]
,比较pgfplots:使用任意 RGB 颜色对(3D)曲面进行着色) 。
即使在内存减少之后,您仍然有“大量”数据点(就 TeX 应该处理的数据而言)。因此,即使减少内存最终也可能达到 TeX 的极限。如果一个图像有效但多个图像失败,则可以使用图像外部化。您还可以使用lualatex
而不是pdflatex
动态lualatex
内存分配来获益。您还应该在\clearpage
相邻figure
环境之间进行实验,以确保 TeX 的内存中没有旧图形(正如@JLDiaz 在评论中所建议的那样)。图像外部化和内存消耗的详细信息总结在“内存和速度考虑因素”一节中http://pgfplots.sourceforge.net/pgfplots.pdf
答案3
为了在红色和蓝色(通过橙色、黄色、绿色和青色)之间做出平滑而简单的阴影,您可以使用Hsb
颜色模型(由xcolor
包提供):
\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\foreach \x in {0,...,9}{
\foreach \y in {0,...,9}{
\pgfmathtruncatemacro{\myhue}{(\y*10+\x)*2.5}
\definecolor{col}{rgb:Hsb}{\myhue,1,1}
\draw[fill=col] (\x,\y) rectangle ++(1,1);
}
}
\end{tikzpicture}
\end{document}
或者(使用另一种语法):
\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\colorlet{redhsb}[hsb]{red}%
\colorlet{bluehsb}[hsb]{blue}%
\foreach \x in {0,...,9}{
\foreach \y in {0,...,9}{
\pgfmathtruncatemacro{\rat}{\y*10+\x}
\colorlet{col}[rgb]{bluehsb!\rat!redhsb}
\draw[fill=col] (\x,\y) rectangle ++(1,1);
}
}
\end{tikzpicture}
\end{document}
此方法可用于大量小正方形(此处为 100 x 100):
\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\colorlet{redhsb}[hsb]{red}%
\colorlet{bluehsb}[hsb]{blue}%
\foreach \x in {0,...,100}{
\foreach \y in {0,...,100}{
\pgfmathtruncatemacro{\rat}{(cos(\x*4)+sin(\y*4))*25+50}
\colorlet{col}[rgb]{bluehsb!\rat!redhsb}
\draw[fill=col,line width=.1pt] (\x*.1,\y*.1) rectangle ++(.1,.1);
}
}
\end{tikzpicture}
\end{document}