
У меня есть документ с некоторыми изображениями 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
pushing некоторого рода буквальный 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
который имеет ожидаемое поведение. Он получает три числовых значения для компонентовr
,g
иb
в диапазоне от 0 до 255. Таким образом, мы можем использовать этот макрос для установки цвета заливки непосредственно перед командой заполнения.
Вот код, который показывает несколько вариантов:
\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: раскрашиваем (3D) прибой, используя произвольные цвета RGB) .
Даже после сокращения памяти у вас есть «много» точек данных (говоря в терминах того, что 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}