您是否知道是否有任何可用的 LaTeX 包来创建这样的图表?
(来源)
答案1
我认为,只要稍微花点功夫,我就能消除图表右侧和底部的杂散规则点。但它们可能不会打扰你。
编辑:既然答案被接受了,我想我应该稍微扩展一下解释。我的目标是既让输出看起来符合 OP 要求的风格,又让用户的输入尽可能简单。
我选择stackengine
做重活,因为这个问题需要该软件包的许多不同功能。我通过将两个\rule
s 堆叠在一起来创建单元网格。我通过\stackinset
在单元网格顶部添加彩色项目符号来创建彩色点。我通过将内容堆叠在顶部 90 度旋转的名称标签下来创建最终网格。
综上所述,输入模式非常高效。网格本身的输入量远少于上角的“必须、应该、可能”标签。例如,实际网格是使用
\Shortstack{%
\hname{entry}\R\B\G\X\\
\hname{lobby}\G\B\X\R\\
\hname{reception}\X\R\B\G\\
\hname{administration}\R\R\B\G%
}%
其中\X
表示一个空网格单元,\R
、\B
和\G
宏分别表示红色、蓝色和绿色项目符号。以下是解决方案:
\documentclass{article}
\usepackage{fixltx2e}
\usepackage[usestackEOL]{stackengine}[2013-09-25]
\usepackage{xcolor, graphicx}
\newsavebox{\Rbox}\newsavebox{\Bbox}\newsavebox{\Gbox}\newsavebox{\Xbox}
\def\thk{.5pt} % RULE THICKNESS
\def\gsize{.4cm} % GRID SIZE
\def\hnamesize{1.8cm} % WIDTH OF HORIZONTAL-NAME BLOCK
\def\grid{\stackinset{c}{}{c}{}{\rule{\thk}{\gsize}}{\rule{\gsize}{\thk}}}
\sbox\Rbox{\stackinset{c}{.2pt}{c}{-.8pt}{\scalebox{2}{\color{red}$\bullet$}}{\grid}}
\sbox\Bbox{\stackinset{c}{.2pt}{c}{-.8pt}{\scalebox{1.75}{\color{blue}$\bullet$}}{\grid}}
\sbox\Gbox{\stackinset{c}{.2pt}{c}{-.8pt}{\scalebox{1.5}{\color{green}$\bullet$}}{\grid}}
\sbox\Xbox{\grid}
\def\R{\usebox{\Rbox}}\def\B{\usebox{\Bbox}}
\def\G{\usebox{\Gbox}}\def\X{\usebox{\Xbox}}
\newcommand*\hname[2][P]{\makebox[\hnamesize][l]{\tiny\sffamily%
\raisebox{-.3\ht\strutbox}{\uppercase{#2}}%
\if x#1\else\rule{\hnamesize-\widthof{\uppercase{#2}}}{\thk}\fi}}
\newcommand*\vname[1]{%
\makebox[\gsize]{\rotatebox{90}{\tiny\sffamily\uppercase{#1}}}%
}
\setstackgap{S}{0pt}
\def\stackalignment{l}
\begin{document}
\stackinset{l}{-2.5ex}{t}{}{%
\renewcommand\arraystretch{0.7}
\begin{tabular}{c@{}l}
\abovebaseline[-2pt]{\scalebox{2}{\color{red}$\bullet$}} &
\color{red}\footnotesize\sffamily MUST\\
\abovebaseline[-2pt]{\scalebox{1.75}{\color{blue}$\bullet$}} &
\color{blue}\scriptsize\sffamily SHOULD\\
\abovebaseline[-2pt]{\scalebox{1.5}{\color{green}$\bullet$}} &
\color{green}\tiny\sffamily MAYBE\\
\end{tabular}
}{%
\stackunder{%
\hname[x]{}\vname{entry}\vname{lobby}\vname{reception}\vname{administration}
}{%
\Shortstack{%
\hname{entry}\R\B\G\X\\
\hname{lobby}\G\B\X\R\\
\hname{reception}\X\R\B\G\\
\hname{administration}\R\R\B\G%
}%
}%
}
\end{document}
答案2
看起来像一份工作pgf图使用带有符号坐标和网格的散点图。以下是我目前想到的:
\documentclass{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
legend style={
legend pos=outer north east,
},
xticklabel pos=right,
y dir =reverse,
symbolic x coords = {Entry,Lobby,Reception,Administration,Security,Lounge},
symbolic y coords = {Entry,Lobby,Reception,Administration,Security,Lounge},
x tick label style={rotate=90},
grid=major,
width=5cm,
height=5cm
]
ytick = data,
\addplot[only marks,red,mark size = 5pt] coordinates {
(Lobby,Entry)
(Reception,Entry)
};
\addlegendentry{Must}
\addplot[only marks,blue] coordinates {
(Reception,Administration)
(Administration,Reception)
};
\addlegendentry{Should}
\addplot[only marks,green] coordinates {
(Entry,Entry)
(Lobby,Reception)
};
\addlegendentry{Maybe}
\end{axis}
\end{tikzpicture}
\end{document}
答案3
这MWE
使用Asymptote
。假设矩阵是对称的。使用两种命令来填充矩阵的列:两者都使用第一个参数作为标记索引(smlId
,midId
或bigId
),第二个参数作为column
数字,但第一个使用 s 列表row
来标记,而另一个使用形式为 的对列表(<first row>, <count>)
。
例如, 用小标记m.markCol(smlId,5,7,18);
标记行7
和18
列,用大标记标记从 开始的行的顺序 和从 开始的行的顺序。5
m.markCol(bigId,1,(2,5),(8,2));
5
2
2
8
1
% mx.tex :
\documentclass{article}
\usepackage[inline]{asymptote}
\usepackage{lmodern}
\begin{document}
\begin{figure}
\begin{asy}
settings.outformat="pdf";
unitsize(1bp);
import fontsize;
defaultpen(fontsize(8pt));
pen textPen=rgb(0.4,0.3,0.3);
pen linePen=heavycyan+1bp;
real smlCircR=3;
real midCircR=4;
real bigCircR=5;
guide[] circMark={
scale(smlCircR)*unitcircle,
scale(midCircR)*unitcircle,
scale(bigCircR)*unitcircle,
};
pen[] circMarkPen={
rgb(0,0.996,0.329)+fontsize(8pt)
,rgb(0,0.702,1)+fontsize(10pt)
,red+fontsize(12pt)
};
string[] name={
"ENTRY",
"LOBBY",
"RECEPTION",
"ADMINISTRATION",
"SECURITY",
"LOUNGE",
"RESTROOMS",
"EMPLOYEE LOUNGE",
"GIFT SHOP",
"CAF\'E",
"CLASSROOMS",
"REC. STUDIO",
"WORKSHOP",
"RECITAL HALL",
"GRAND THEATRE",
"DRESSING ROOM",
"REHEARSEL",
"MUSICIAN LOUNGE",
"MECH. ROOM",
"CONTROL ROOM",
"STORAGE",
};
real dr=12;
real dc=dr;
real r,c;
int n=name.length;
c=0;
Label L;
real maxw=0;
real w;
pair mx;
for(int i=0;i<n;++i){
r=dr*(n-i);
L=Label("\sffamily "+name[i],(0,0),E);
mx=max(object(L).g);
if(mx.x>maxw)maxw=mx.x;
}
real xshift=maxw+bigCircR;
real yshift=2bigCircR;
for(int i=0;i<n;++i){
r=dr*(n-i);
c=dc*i;
draw((0,(i+1)*dr)--(xshift+(n-1)*dc,(i+1)*dr),linePen);
draw((xshift+i*dc,yshift+n*dr)--(xshift+i*dc,dr),linePen);
}
layer();
c=0;
for(int i=0;i<n;++i){
r=dr*(n-i);
L=Label("\sffamily "+name[i],(0,0));
label(L,(c,r),E,textPen,UnFill(2));
}
r=n*dr;
for(int i=0;i<n;++i){
c=xshift+dc*i;
L=rotate(90)*Label("\sffamily "+name[i],(0,0));
label(L,(c,r+yshift),N,textPen);
}
struct Mask{
int[][] mask;
void markCol(int circId, int col ... int[] seq){
for(int i=0;i<seq.length;++i){
mask[seq[i]][col]=circId;
}
}
void markCol(int circId, int col ... pair[] seq){ // mark sequences
for(int i=0;i<seq.length;++i){
for(int j=0;j<seq[i].y;++j){
mask[(int)seq[i].x+j][col]=circId;
}
}
}
void drawMarks(){
int id;
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
id=mask[i][j];
if(id>0 && id<4){
fill(shift(xshift+j*dc,(n-i)*dr)*circMark[id-1],circMarkPen[id-1]);
fill(shift(xshift+i*dc,(n-j)*dr)*circMark[id-1],circMarkPen[id-1]);
}
}
}
}
void operator init(int n){
mask=array(n,array(n,0));
}
}
int smlId=1;
int midId=2;
int bigId=3;
Mask m=Mask(n);
m.markCol(smlId,2,7);
m.markCol(smlId,3,5);
m.markCol(smlId,5,7,18);
m.markCol(smlId,6,8);
m.markCol(smlId,7,9);
m.markCol(smlId,8,n-2);
m.markCol(smlId,9,n-2);
m.markCol(smlId,10,(n-7,3));
m.markCol(midId,0,n-9,n-10);
m.markCol(midId,1,7,13,14);
m.markCol(midId,2,3,5,6,8,9);
m.markCol(midId,4,5,8);
m.markCol(bigId,0,(1,6),(8,2));
m.markCol(bigId,1,(2,5),(8,2));
m.markCol(bigId,2,4,n-1);
m.markCol(bigId,3,4,6);
m.markCol(bigId,5,9,14);
m.markCol(bigId,6,(9,3),(13,3));
m.markCol(bigId,9,14);
m.markCol(bigId,10,(11,3));
m.markCol(bigId,11,16);
m.markCol(bigId,13,16,17,n-1);
m.markCol(bigId,14,(15,6));
m.markCol(bigId,16,n-4);
m.markCol(bigId,17,n-1);
m.markCol(bigId,18,n-1);
m.drawMarks();
fill(shift((bigCircR,(n+5)*dr))*circMark[bigId-1],circMarkPen[bigId-1]);
fill(shift((bigCircR,(n+4)*dr))*circMark[midId-1],circMarkPen[midId-1]);
fill(shift((bigCircR,(n+3)*dr))*circMark[smlId-1],circMarkPen[smlId-1]);
label("\sffamily MUST", (2bigCircR,(n+5)*dr),E,circMarkPen[bigId-1]);
label("\sffamily SHOULD",(2bigCircR,(n+4)*dr),E,circMarkPen[midId-1]);
label("\sffamily MAYBE", (2bigCircR,(n+3)*dr),E,circMarkPen[smlId-1]);
\end{asy}
\end{figure}
\end{document}
% Prosess it with
%
% pdflatex mx.tex
% asy mx-*.asy
% pdflatex mx.tex