
Tenho um documento com algumas imagens TikZ, que são geradas automaticamente a partir de um programa que escrevi. Todas as imagens são bastante semelhantes e cada uma delas contém um grande número de quadrados com cores RGB diferentes e arbitrárias. Minha pergunta é:Qual a melhor forma de colorir todo esse grande número de quadrados?
O método que usei até agora consiste em definir a cor fillcolor
usando a macro \definecolor
, antes de desenhar cada quadrado, e usar essa cor para preencher o quadrado. Isso significa que cada vez que desenho um novo quadrado, estou definindo fillcolor
novamente.
No entanto, não tenho tanta certeza de que essa seja a maneira de fazer isso. O pdflatex parece exigir muita memória ao compilar o documento e, por algum motivo estranho, fica sem memória se eu incluir mais de 5 imagens (mesmo se eu aumentar a quantidade de memória dez vezes ao passar de 5 para 6 imagens) . Existe alguma chance de ele armazenar todas as cores que defini e de que preciso fazer com que o pdflatex "esqueça" fillcolor
antes de ligar \definecolor
novamente?
Atualizar:Abaixo está um exemplo de uma das imagens TikZ que desejo em meu documento (é uma visualização do campo de fração de fase em uma simulação de fluido bifásico usando o método de volume finito e o método de volume de fluido, e sim, eu sei, o interface fluida não é exatamente nítida):
Esta imagem específica consiste em 1.990 quadrados preenchidos e 4 quadrados não preenchidos.
Primeiro, para cada quadrado, fillcolor
é definido com \definecolor
, e o quadrado é preenchido com essa cor:
\definecolor{fillcolor}{rgb}{1.000000,0.241735,0.000000}
\fill[fillcolor] (0.203125,0.578125) rectangle (0.218750,0.593750);
Em seguida, os lados de cada quadrado são desenhados, por exemplo
\draw (0.203125,0.578125) rectangle (0.218750,0.593750);
Responder1
Como eu disse em um comentário, se \definecolor
simplesmente armazenar a definição de cor em uma macro TeX, então redefini-la reciclará a mesma macro e, portanto, não usará mais memória.
No entanto, também é possível que \defincolor
esteja enviando algum tipo de código PDF literal que defina a cor do mecanismo PDF. Neste caso, pelo que entendi, também não deve ser usada mais memória para redefinir muitas vezes a mesma cor.
De qualquer forma, por precaução, é possível utilizar uma cor RGB sem definição prévia. Aqui está como.
Em princípio,
tikz
reconhece uma especificação de cor da forma{rgb:red,255;green,255;blue:255}
. Mas não é interpretado como seria de esperar. Por exemplo,[fill={rgb:red,255;green,255;blue,0}]
não produzirá amarelo, mas sim um amarelo preto (veja a figura abaixo). Não consegui encontrar documentação sobre como essa especificação funciona. Aparentementered
, todosgreen
osblue
valores são somados e, em seguida, cada valor específico é dividido pelo total. Ou seja, o que especificamos não são valores absolutos de bytes, mas pesos relativos. Então, para ficar amarelo podemos escrever:{rgb:red,1;green:1;blue:-1}
. Acho essa sintaxe bastante inconveniente (além disso, como poderíamos ficar "brancos"?)O PGF usa uma macro interna:
\pgfsys@color@rgb@fill
que tem o comportamento esperado. Ele recebe três valores numéricos para os componentes er
, como valores de 0 a 255. Portanto, podemos usar esta macro para definir a cor de preenchimento logo antes do comando de preenchimento.g
b
Aqui está um código que mostra várias opções:
\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}
O resultado:
Responder2
Eu acredito que sua abordagem \definecolor
está boa.
Minha sugestão seria usar a camada básica PGF em vez de tikz, ou seja, usar algo como
\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
Por favor, procure os comandos mencionados em pgfmanual.pdf, pois posso ter digitado incorretamente alguns deles (citei de cor).
Minha sugestão de combinar traço e contorno de preenchimento e variar apenas a cor pode fazer sentido para você e também pode ser aplicada ao caminho tikz. Isso também deve reduzir o consumo de memória e o tempo de composição.
Uma observação que está realmente fora do escopo da sua pergunta: minha sugestão de usar a cor do desenho fillcolor!80!black
é inspirada no padrão pgfplots
que considero menos severo em comparação aos contornos pretos. E pgfplots tem o mesmo caso de uso que aqui: o que você escreve aqui é na verdade um tipo de malha/superfície com sombreamento facetado e entrada de cor explícita (em pgfplots: \addplot3[surf]
, comparepgfplots: colorir uma navegação (3D) usando cores RGB arbitrárias).
Mesmo após a redução de memória, você tem 'muitos' pontos de dados (falando em termos do que o TeX deve lidar). Portanto, mesmo a redução da memória pode eventualmente atingir os limites do TeX. Se uma imagem funcionar, mas mais de uma falhar, você poderá se beneficiar com o uso da externalização de imagem. Você também pode se beneficiar do uso lualatex
em vez pdflatex
da lualatex
alocação dinâmica de memória. Você também deve fazer experiências \clearpage
entre ambientes adjacentes figure
para garantir que o TeX não tenha figuras antigas em sua memória (como @JLDiaz sugeriu em um comentário). Os detalhes sobre externalização de imagem e consumo de memória estão resumidos na seção "Considerações sobre memória e velocidade" emhttp://pgfplots.sourceforge.net/pgfplots.pdf
Responder3
Para fazer um sombreamento suave e simples entre vermelho e azul (via laranja, amarelo, verde e ciano), você pode usar o Hsb
modelo de cores (fornecido na xcolor
embalagem):
\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}
Ou (com outra sintaxe):
\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}
Este método pode ser usado com um grande número de pequenos quadrados (aqui, 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}