我正在建立一个蒂克兹逐行绘制图表。每行由一系列 blob 组成,行末通过发出 来表示\newrow
。
以下是我迄今为止编写的代码:
\documentclass{article}
\usepackage{tikz}
\usepackage{keycommand}
\begin{document}
\newcounter{HeightCounter}
\setcounter{HeightCounter}{0}
\newkeycommand{\blob}[left=0,right=0,minheight=0,color={}]{%
\fill[\commandkey{color}] (\commandkey{left},\theHeightCounter)
rectangle (\commandkey{right},\theHeightCounter+\commandkey{minheight});
}
\newcommand{\newrow}{...}
\begin{center}
\begin{tikzpicture}[x=1mm,y=-1mm]
\blob[color=blue, left=0, right=20, minheight=6]
\blob[color=blue, left=25, right=45, minheight=8]
\blob[color=blue, left=50, right=60, minheight=7]
%\newrow
\addtocounter{HeightCounter}{8}
\blob[color=green, left=0, right=20, minheight=4]
\blob[color=green, left=25, right=35, minheight=2]
\blob[color=green, left=40, right=60, minheight=5]
%\newrow
\addtocounter{HeightCounter}{5}
\blob[color=red, left=0, right=35, minheight=4]
\blob[color=red, left=40, right=60, minheight=2]
%\newrow
\end{tikzpicture}
\end{center}
\end{document}
该代码生成的结果是:
我会喜欢:
- 每一行中的斑点都延伸到相同的高度,例如H,定义
minheight
为该行中的最大值。 - 然后该命令将
\newrow
计数器推进HeightCounter
H。
这是我想要的输出(看看每个斑点如何向下拉伸以填充其各自行的高度):
以下是我想说的喜欢输入(请注意,该\newrow
命令没有参数;它应该自动计算前一行的高度):
\begin{center}
\begin{tikzpicture}[x=1mm,y=-1mm]
\blob[color=blue, left=0, right=20, minheight=6]
\blob[color=blue, left=25, right=45, minheight=8]
\blob[color=blue, left=50, right=60, minheight=7]
\newrow
\blob[color=green, left=0, right=20, minheight=4]
\blob[color=green, left=25, right=35, minheight=2]
\blob[color=green, left=40, right=60, minheight=5]
\newrow
\blob[color=red, left=0, right=35, minheight=4]
\blob[color=red, left=40, right=60, minheight=2]
\newrow
\end{tikzpicture}
\end{center}
我正在以编程方式生成大量此类图表,因此对我来说,由 LaTeX 而不是人类用户完成高度计算非常重要。
使用普通编程语言进行编程的方式如下:
- 依次处理每个 blob,存储每个 blob 相应的
color
和left
数据right
,并累积字段的最大值minheight
。 - 达到后
\newrow
,将该行中的所有斑点绘制到所需的高度,然后前进HeightCounter
适当的量。
我认为该算法可能与 LaTeX 绘制表格的方式非常相似,因此也许这个问题会有一个非常自然的 LaTeX 解决方案。
答案1
这是一个使用关键过滤的想法。
另一种方法是使用手动停用某些密钥<key>/.code=
,但我想家庭似乎更合适……
代码
\documentclass[tikz,convert=false]{standalone}
\providecommand{\blobset}[1]{}% (for my editor)
\providecommand{\blob}[1][]{} %
\providecommand{\newrow}{} %
\makeatletter
\def\blobset{\pgfqkeys{/blob}}
\pgfkeys{
/utils/list to family family/.code=\edef\qrr@utils@listtofamily{#1},
/utils/list to family/.style={
#1/.belongs to family/.expanded=\qrr@utils@listtofamily,
}
}
\tikzset{blob/.code=\blobset{#1}}
\blobset{
every blob picture/.style={/tikz/x=1mm,/tikz/y=-1mm},
% % setup
% or keys:
color/.style={/tikz/fill=#1},
color/.default=black,
left/.initial=0,
right/.style={width={#1-(\pgfkeysvalueof{/blob/left})}},
width/.initial=10,
minheight/.code=\pgfmathsetmacro\blob@height{max(\blob@height,#1)},
% our families:
@blob@draw/.is family,
@blob@save/.is family,
% which key belongs to which family?
/utils/list to family family=/blob/@blob@draw,
/utils/list to family/.list={color, left, right, width},
minheight/.belongs to family=/blob/@blob@save
}
\newenvironment{blobpicture}[1][]{%
\blobset{#1}%
\let\newrow\blob@newrow
\let\blob\blob@
\tikzpicture[/blob/every blob picture/.try]}{\endtikzpicture}% only LaTeX!
\def\blob@reset{\let\blob@stored\pgfutil@empty\def\blob@height{0}}
\blob@reset
\def\blob@{\pgfutil@ifnextchar[\blob@save{\blob@save[]}}
\def\blob@save[#1]{%
\blobset{@blob@save/.activate family}%
\pgfkeysfiltered{/blob/.cd,#1}%
\expandafter\def\expandafter\blob@stored\expandafter{\blob@stored\blob@draw{#1}}%
}
\def\blob@draw#1{\path[every blob path/.try, blob={@blob@save/.deactivate family,#1}] ({\pgfkeysvalueof{/blob/left}},0) rectangle ++ ({\pgfkeysvalueof{/blob/width}},{\blob@height});}
\def\blob@newrow{
\blob@stored
\tikzset{shift={(0,\blob@height)}}%
\blob@reset}
\makeatother
\begin{document}
\begin{blobpicture}
\blob[color=blue, left=0, right=20, minheight=6]
\blob[color=blue, left=25, right=45, minheight=8]
\blob[color=blue, left=50, right=60, minheight=7]
\newrow
\blob[color=green, left=0, right=20, minheight=4]
\blob[color=green, left=25, right=35, minheight=2]
\blob[color=green, left=40, right=60, minheight=5]
\newrow
\blob[color=red, left=0, right=35, minheight=4]
\blob[color=red, left=40, right=60, minheight=2]
\newrow
\end{blobpicture}
\end{document}