在 TikZ 中将大型二进制矩阵绘制为彩色网格

在 TikZ 中将大型二进制矩阵绘制为彩色网格

我有一个相当大的二进制矩阵,可能有 70 行和 64 列。为了方便查看,我想在 TikZ 中绘制此矩阵,其中例如 1 用红色方块表示,0 用白色方块表示。有人知道我该如何获得这个吗?

理想情况下,我会有一个可以只从文件加载矩阵的东西,TikZ 会处理其他所有事情。否则,我也很乐意使用一个解决方案,即用某个字符串查找/替换每个 0,用另一个字符串替换每个 1。

先感谢您!

示例矩阵:

10110101010
10010101010
01010111010
11110010100
01100011001
11101010111
10101010111

答案1

答案提供了两种解决方案:通过第一种方法,可以自定义正方形的尺寸,也许更适合您的需求。两者都基于此处给出的答案。

解决方案 1 基于使用 pgfplotstable 在表格中创建方形和自定义大小的单元格

\documentclass{article}
\usepackage{filecontents}
\usepackage[table]{xcolor}
\usepackage{pgfplotstable}
\usetikzlibrary{calc}
\pgfplotsset{compat=1.8}

\begin{filecontents}{matrix.cvs}
1 0 1 1 0 1 0 1 0 1 0
1 0 0 1 0 1 0 1 0 1 0
0 1 0 1 0 1 1 1 0 1 0
1 1 1 1 0 0 1 0 1 0 0
0 1 1 0 0 0 1 1 0 0 1
1 1 1 0 1 0 1 0 1 1 1
1 0 1 0 1 0 1 0 1 1 1
\end{filecontents}

\makeatletter
\tikzset{
    zero color/.initial=white,
    zero color/.get=\zerocol,
    zero color/.store in=\zerocol,
    one color/.initial=red,
    one color/.get=\onecol,
    one color/.store in=\onecol,
    cell wd/.initial=1ex,
    cell wd/.get=\cellwd,
    cell wd/.store in=\cellwd,
    cell ht/.initial=1ex,
    cell ht/.get=\cellht,
    cell ht/.store in=\cellht,
}

\newcommand{\drawgrid}[2][]{
\medskip
\begin{tikzpicture}[#1]
  \pgfplotstableforeachcolumn#2\as\col{
    \pgfplotstableforeachcolumnelement{\col}\of#2\as\colcnt{%
      \ifnum\colcnt=0
        \fill[\zerocol]($ -\pgfplotstablerow*(0,\cellht) + \col*(\cellwd,0) $) rectangle+(\cellwd,\cellht);
      \fi
      \ifnum\colcnt=1
        \fill[\onecol]($ -\pgfplotstablerow*(0,\cellht) + \col*(\cellwd,0) $) rectangle+(\cellwd,\cellht);
      \fi
    }
  }
\end{tikzpicture}
\medskip
}
\makeatother

\begin{document}
% read the file
\pgfplotstableread{matrix.cvs}{\matrixfile}

\drawgrid{\matrixfile}

\drawgrid[zero color=green, one color=cyan]{\matrixfile}

\drawgrid[zero color=orange, 
  one color=violet,
  cell ht=2em,
  cell wd=2em]{\matrixfile}
\end{document}

结果:

在此处输入图片描述

解决方案 2 基于通过 TikZ 对表格中的阴影进行参数化

\documentclass{article}
\usepackage{filecontents}
\usepackage[table]{xcolor}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.8}

\begin{filecontents}{matrix.cvs}
1 0 1 1 0 1 0 1 0 1 0
1 0 0 1 0 1 0 1 0 1 0
0 1 0 1 0 1 1 1 0 1 0
1 1 1 1 0 0 1 0 1 0 0
0 1 1 0 0 0 1 1 0 0 1
1 1 1 0 1 0 1 0 1 1 1
1 0 1 0 1 0 1 0 1 1 1
\end{filecontents}

\makeatletter
\pgfplotstableset{
    zero color/.initial=white,
    zero color/.get=\zerocol,
    zero color/.store in=\zerocol,
    one color/.initial=red,
    one color/.get=\onecol,
    one color/.store in=\onecol,
    color cells/.style={
        every head row/.style={output empty row},
        string type,
        postproc cell content/.code={%
           \pgfkeysalso{@cell content=\rule{0cm}{2.4ex}\cellcolor{\zerocol}
           \pgfmathtruncatemacro\number{##1}
           \ifnum\number>0\cellcolor{\onecol}\fi}%
        },
        columns/x/.style={
            column name={},
            postproc cell content/.code={}
        }
    }
}
\makeatother

\begin{document}
% read the file
\pgfplotstableread{matrix.cvs}{\matrixfile}

\begin{table}
\centering
\pgfplotstabletypeset[color cells]\matrixfile
\end{table}

\begin{table}
\centering
\pgfplotstabletypeset[color cells, zero color=green, one color=cyan]\matrixfile
\end{table}
\end{document}

结果:

在此处输入图片描述

答案2

只是为了好玩和比较,我实现了一个 lualatex 解决方案。

在这个解决方案中,我使用 lua 将矩阵从其文本形式(0 和 1 的序列)转换为包含大量绘制图形的 tikz 命令的另一个字符串。

基于 lua 的解决方案似乎比纯 tikz 解决方案慢,但这可能是由于 lualatex 启动。lua 函数的执行非常快,但生成的 tikz 代码的编译显然是瓶颈。可能我的 lua 代码可以生成更高效的 tikz 代码。

要编译我的示例,你需要:

  • 正在运行的 lualatex
  • 该文件的副本matrix2tikz.lua(如下)
  • 该文件sample.tex(下)

样本

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{fit}
\directlua{dofile("matrix2tikz.lua")}  
\newcommand{\bitmapmatrix}[2][10]{%
\begin{scope}[bitmapmatrix]
\directlua{matrix2tikz("#2",#1)}%
\end{scope}
}
\tikzset{
  bitmapmatrix/.style = {line width = 2sp},
  pixel on/.style = {red},
  pixel off/.style = {white},
  pixel err/.style = {pink}
}

\def\mydata{
10110101010
10010101010
01010111010
11110010100
01100011001
11101010111
10101010111
}

\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}[node distance=2mm]
  \bitmapmatrix[5]{\mydata}
  \node[below=of matrix] {This is a test};
\end{tikzpicture}    
\end{document}

矩阵2tikz.lua

local function matrix_to_tikz(tab , size)
  local width = size
  if (size == nil) then size=10 end
  local pixel_width = size / #tab[1]
  local height = pixel_width * #tab
  local pixel_cmd = string.format("\\filldraw[%%s] (%%f, %%f) +(-%f, %f)         → rectangle +(%f, -%f);",
          pixel_width/2, pixel_width/2, pixel_width/2, pixel_width/2)
  local str_tab = {}

  for y=1,#tab do
    row = {}
    for x=1,#tab[y] do
      if tab[y][x] == 1 then
          style = "pixel on"
      elseif tab[y][x] == 0 then
          style = "pixel off"
      else
          style = "pixel err"
      end
      row[x] = string.format(pixel_cmd, style, x*pixel_width, -y*pixel_width)
    end
    str_tab[y] = table.concat(row, "\n")
  end
  local extra = {}
  extra[1] = string.format("\\coordinate (aux1) at (%f,-%f);", pixel_width/2,    → height+pixel_width/2)
  extra[2] = string.format("\\coordinate (aux2) at (%f, %f);", width+            → pixel_width/2, -pixel_width/2)
  extra[3] = "\\node[inner sep=0pt, fit=(aux1) (aux2)] (matrix) {};"
  str_tab[#tab+1] =  table.concat(extra, "\n")
  return table.concat(str_tab,"\n")
end

function justWords(str)
  local t = {}
  local function helper(word) table.insert(t, word) return "" end
  if not str:gsub("%w+", helper):find"%S" then return t end
end

local function text_to_matrix(txt)
  local m = {}
  local l = justWords(txt)
  for i=1,#l do
    if (l[i]~= nil and #l[i]>1) then
        j = 1; row = {}
        for c in l[i]:gmatch(".") do
          row[j] = tonumber(c)
          j = j + 1
        end
        m[i] = row
    end
  end
  return m
end

function matrix2tikz(data, size)
  local t = text_to_matrix(data)
  local s = matrix_to_tikz(t, size)
  tex.print(s)
end

编译

将两者放在同一个文件夹中并运行lualatex sample.tex。结果如下:

结果

答案3

运行xelatex

\documentclass{article}
\usepackage{filecontents}
\usepackage{pstricks-add}

\begin{filecontents*}{matrix.data}
/dotmatrix [
1 0 1 1 0 1 0 1 0 1 0
1 0 0 1 0 1 0 1 0 1 0
0 1 0 1 0 1 1 1 0 1 0
1 1 1 1 0 0 1 0 1 0 0
0 1 1 0 0 0 1 1 0 0 1
1 1 1 0 1 0 1 0 1 1 1
1 0 1 0 1 0 1 0 1 1 1
] def
\end{filecontents*}

\begin{document}

 \begin{pspicture}(-0.5,-0.75)(7,11)
 \psframe*[linecolor=blue!60](0.5,0.5)(11.5,7.5)
 \psMatrixPlot[dotsize=1.1cm,dotstyle=square*,linecolor=red!60]{7}{11}{matrix.data}
\end{pspicture}

\end{document}

在此处输入图片描述

答案4

只是为了好玩,直接从提供的数据中获取。L3 版本可能正在开发中 :)

\documentclass{standalone}
\usepackage{tikz,xstring,etoolbox,catchfile}
\usetikzlibrary{matrix}

%=== Remove these later, it creates a dummy data file
\usepackage{filecontents}
\begin{filecontents*}{testdata.txt}
101101010101011010101010110101010
100101010101001010101010010101010
010101110100101011101001010111010
111100101001111001010011110010100
011000110010110001100101100011001
111010101111110101011111101010111
101010101111010101011110101010111
101101010101011010101010110101010
100101010101001010101010010101010
010101110100101011101001010111010
111100101001111001010011110010100
011000110010110001100101100011001
111010101111110101011111101010111
101010101111010101011110101010111
\end{filecontents*}
%================================

%Replace your file name 
\CatchFileDef{\mydata}{testdata.txt}{}

\def\doit#1{%
\let\mymatrixcontent\empty%
\StrCount{#1}{ }[\myrownumber]%
\xdef\mormatrix{#1}%
    \foreach \m in {1,...,\myrownumber}{%
    \StrCut{\mormatrix}{ }\myextractedrow\myremainingmatrix%
    \xdef\mormatrix{\myremainingmatrix}%
    \StrLen{\myextractedrow}[\mycolnum]%
    \foreach \k in {1,...,\mycolnum}{%
         \StrChar{\myextractedrow}{\k}[\kk]%
             \begingroup\edef\x{\endgroup%
             \noexpand\gappto\noexpand\mymatrixcontent{\ifnum\kk>0|[fill=red]|\fi\noexpand\&}}\x%
    }\gappto\mymatrixcontent{\\}}%
\begin{tikzpicture}
\matrix[matrix of nodes,ampersand replacement=\&,inner sep=0pt,
    nodes={minimum size=4mm,outer sep=0pt}] {\mymatrixcontent};
\end{tikzpicture}%
\let\mymatrixcontent=\empty
}

\begin{document}
\doit{\mydata}
\end{document}

在此处输入图片描述

相关内容