Как использовать большое количество произвольных цветов RGB в изображении TikZ?

Как использовать большое количество произвольных цветов RGB в изображении TikZ?

У меня есть документ с некоторыми изображениями TikZ, которые автоматически генерируются из программы, которую я написал. Все изображения довольно похожи, и каждое из них содержит большое количество квадратов с различными, произвольными цветами rgb. Мой вопрос:Как лучше всего раскрасить все это огромное количество квадратов?

Метод, который я использовал до сих пор, состоит в определении цвета fillcolorс помощью макроса \definecolorперед рисованием каждого квадрата и использовании этого цвета для заполнения квадрата. Это означает, что каждый раз, когда я рисую новый квадрат, я определяю его fillcolorснова.

Однако я не уверен, что это правильный способ. Похоже, pdflatex требует очень много памяти при компиляции документа и по какой-то странной причине у него заканчивается память, если я включаю больше 5 изображений (даже если я увеличиваю объем памяти в десять раз при переходе с 5 на 6 изображений). Есть ли вероятность, что он сохраняет все определенные мной цвета, и что мне нужно заставить pdflatex "забыть" об этом fillcolorперед повторным вызовом \definecolor?

Обновлять:Ниже приведен пример одного из изображений TikZ, которые я хочу использовать в своем документе (это визуализация поля фазовой доли при моделировании двухфазной жидкости с использованием метода конечных объемов и метода объема жидкости, и да, я знаю, интерфейс жидкости не совсем четкий):

Изображение TikZ, содержащее 1990 квадратов разных цветов

Это изображение состоит из 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, то его переопределение приведет к повторному использованию того же макроса и, таким образом, не будет использоваться больше памяти.

Однако также возможно, что это \defincolorpushing некоторого рода буквальный 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}

введите описание изображения здесь

Связанный контент