实际上是两个问题......(在此征求很多意见)
是否有一份大多数人都同意的权威指南,是快速了解如何在 tikz 世界中制作图片的最佳去处,以及
特别是,如何使用它(假设它不是不言而喻的)来制作像下面这样的图像?(假设 tikz 是除了在 LaTeX 中插入 eps 图像之外的最佳方法)
答案1
正如杰克在他的评论中提到的那样,
PGF/TikZ manual
是 PGF/TikZ 的权威参考,其中包含一些非常温和的教程,可帮助您入门。还有一个Minimal Introduction to TikZ
这可能会有所帮助(我从未读过)。另一个有价值的例子来源是TeXample.net
。最后但并非最不重要的一点是,该网站包含大量从简单到非常复杂的示例。构造所需形状的可能性有很多;我选择定义一些命令
\MySquare
,\MyCircle
每个命令有五个参数;第一个参数给出正方形边长(分别是圆的直径),其他四个参数可用于填充象限。该\MyShape
命令有九个参数;第一个控制大小,其他八个用于填充颜色。
在这三种情况下,想法都是相同的;首先,对区域进行阴影处理,然后绘制形状和分界线。
代码:
\documentclass[12pt]{article}
\usepackage{tikz}
\newcommand\FillSquare[5]{%
\fill[#2] (0,0) rectangle +(0.5*#1,0.5*#1);
\fill[#3] (0.5*#1,0cm) rectangle +(0.5*#1,0.5*#1);
\fill[#4] (0,0.5*#1) rectangle +(0.5*#1,0.5*#1);
\fill[#5] (0.5*#1,0.5*#1) rectangle +(0.5*#1,0.5*#1);
}
\newcommand\MySquare[5]{%
\FillSquare{#1}{#2}{#3}{#4}{#5}
\draw (0,0) rectangle (#1,#1);
\draw (0,0.5*#1) -- +(#1,0);
\draw (0.5*#1,0) -- +(0,#1);
}
\newcommand\MyCircle[5]{%
\fill[#4] (0,0) arc[radius=0.5*#1,start angle=180,end angle=90] -- +(0,-0.5*#1) --cycle;
\fill[#5] (#1,0) arc[radius=0.5*#1,start angle=0,end angle=90] -- +(0,-0.5*#1) --cycle;
\fill[#3] (#1,0) arc[radius=0.5*#1,start angle=0,end angle=-90] -- +(0,0.5*#1) -- cycle;
\fill[#2] (0.5*#1,-0.5*#1) arc[radius=0.5*#1,start angle=-90,end angle=-180] -- +(0.5*#1,0) -- cycle;
\draw (0.5*#1,0) circle [radius=0.5*#1];
\draw (0,0) -- +(#1,0);
\draw (0.5*#1,-0.5*#1) -- +(0,#1);
}
\newcommand\MyShape[9]{%
\fill[#2] (0,0) arc[radius=0.5*#1,start angle=270,end angle=180] -- +(0.5*#1,0) --cycle;
\fill[#5] (-0.5*#1,0.5*#1) arc[radius=0.5*#1,start angle=180,end angle=90] -- +(0,-0.5*#1) --cycle;
\fill[#6] (1.5*#1,0.5*#1) arc[radius=0.5*#1,start angle=0,end angle=90] -- +(0,-0.5*#1) --cycle;
\fill[#9] (1.5*#1,0.5*#1) arc[radius=0.5*#1,start angle=0,end angle=-90] -- +(0,0.5*#1) -- cycle;
\FillSquare{#1}{#3}{#4}{#7}{#8}
\draw (#1,0) -- +(-#1,0)
arc[radius=0.5*#1,start angle=270,end angle=90] -- +(#1,0)
arc[radius=0.5*#1,start angle=90,end angle=-90] -- cycle;
\draw (-0.5*#1,0.5*#1) -- +(2*#1,0);
\draw (#1,0) -- +(0,#1);
\draw (0.5*#1,0) -- +(0,#1);
\draw (0,0) -- +(0,#1);
}
\begin{document}
\begin{tikzpicture}
\MySquare{4cm}{gray!30}{blue!30}{green!30}{red!30}
\begin{scope}[xshift=5.2cm,yshift=1cm]
\MyCircle{2cm}{orange}{gray!30}{red!30}{cyan}
\end{scope}
\begin{scope}[xshift=2.2cm,yshift=-4cm]
\MyShape{3cm}{gray!30}{blue!30}{green!30}{red!30}{olive!60}{brown!30}{yellow!30}{cyan!50}
\end{scope}
\end{tikzpicture}
\end{document}
如果必须在区域上添加标签,也许采用不同的方法更好:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,calc}
\newcommand\DrawSquare[3][]{%
\node[inner sep=0pt,outer sep=0pt,draw,rectangle,minimum size=#2,#1] (#3) {};
}
\newcommand\FillSquare[3]{%
\ifnum#2=1\relax
\fill[#3] ( $ (#1.north west) + (0.5\pgflinewidth,-0.5\pgflinewidth) $ ) rectangle (#1.center);
\else
\ifnum#2=2\relax
\fill[#3] (#1.center) rectangle ( $ (#1.north east) + (-0.5\pgflinewidth,-0.5\pgflinewidth) $ );
\else
\ifnum#2=3\relax
\fill[#3] ( $ (#1.south west) + (0.5\pgflinewidth,0.5\pgflinewidth) $ ) rectangle (#1.center);
\else
\ifnum#2=4\relax
\fill[#3] (#1.center) rectangle ( $ (#1.south east) + (-0.5\pgflinewidth,0.5\pgflinewidth) $ );
\fi\fi\fi\fi%
}
\newcommand\LabelRegion[3]{%
\ifnum#2=1\relax
\node at ( $ (#1.north west)!0.5!(#1.center) $ ) {#3};
\else
\ifnum#2=2\relax
\node at ( $ (#1.north east)!0.5!(#1.center) $ ) {#3};
\else
\ifnum#2=3\relax
\node at ( $ (#1.south west)!0.5!(#1.center) $ ) {#3};
\else
\ifnum#2=4\relax
\node at ( $ (#1.south east)!0.5!(#1.center) $ ) {#3};
\fi\fi\fi\fi%
}
\newcommand\DrawLines[1]{%
\draw (#1.north) -- (#1.south);
\draw (#1.west) -- (#1.east);
}
\begin{document}
\begin{tikzpicture}
\DrawSquare{3cm}{A}
\FillSquare{A}{1}{red!40}
\FillSquare{A}{2}{blue!40}
\FillSquare{A}{3}{green!40}
\FillSquare{A}{4}{yellow!40}
\DrawLines{A}
\LabelRegion{A}{1}{I}
\LabelRegion{A}{2}{II}
\LabelRegion{A}{3}{III}
\LabelRegion{A}{4}{IV}
\DrawSquare[right=of A]{2cm}{B}
\FillSquare{B}{1}{gray!40}
\FillSquare{B}{2}{orange!40}
\FillSquare{B}{3}{cyan!40}
\FillSquare{B}{4}{magenta!40}
\DrawLines{B}
\LabelRegion{B}{1}{a}
\LabelRegion{B}{2}{b}
\LabelRegion{B}{3}{c}
\LabelRegion{B}{4}{d}
\end{tikzpicture}
\end{document}
命令:
\DrawSquare{<length>}{<name>}
绘制一个边长等于的正方形,<length>
并为其指定名称<name>
;它有一个可选参数,用于将选项传递给用于\node
绘制正方形的。
\FillSquare{<name>}{<number>}{<color>}
<name>
使用第三个参数指定的颜色,用name 填充正方形的四个象限之一。<number>
是一个从 1 到 4 的整数,控制哪个区域将被着色。
<name>
可以使用与用于命名正方形相关的锚点来分配附加标签。
\DrawLines{<name>}
为名为 的节点绘制两条垂直线<name>
。
最后,
\LabelRegion{<name>}{<number>}{<text>}
<text>
位于 区域中心的位置<number>
,形状名为<name>
。
使用一些\foreach
循环可以使代码进一步简化:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,calc}
\newcommand\DrawSquare[3][]{%
\node[inner sep=0pt,outer sep=0pt,draw,rectangle,minimum size=#2,#1] (#3) {};
}
\newcommand\FillSquare[3]{%
\ifnum#2=1\relax
\fill[#3] ( $ (#1.north west) + (0.5\pgflinewidth,-0.5\pgflinewidth) $ ) rectangle (#1.center);
\else
\ifnum#2=2\relax
\fill[#3] (#1.center) rectangle ( $ (#1.north east) + (-0.5\pgflinewidth,-0.5\pgflinewidth) $ );
\else
\ifnum#2=3\relax
\fill[#3] ( $ (#1.south west) + (0.5\pgflinewidth,0.5\pgflinewidth) $ ) rectangle (#1.center);
\else
\ifnum#2=4\relax
\fill[#3] (#1.center) rectangle ( $ (#1.south east) + (-0.5\pgflinewidth,0.5\pgflinewidth) $ );
\fi\fi\fi\fi%
}
\newcommand\LabelRegion[3]{%
\ifnum#2=1\relax
\node at ( $ (#1.north west)!0.5!(#1.center) $ ) {#3};
\else
\ifnum#2=2\relax
\node at ( $ (#1.north east)!0.5!(#1.center) $ ) {#3};
\else
\ifnum#2=3\relax
\node at ( $ (#1.south west)!0.5!(#1.center) $ ) {#3};
\else
\ifnum#2=4\relax
\node at ( $ (#1.south east)!0.5!(#1.center) $ ) {#3};
\fi\fi\fi\fi%
}
\newcommand\DrawLines[1]{%
\draw (#1.north) -- (#1.south);
\draw (#1.west) -- (#1.east);
}
\newcommand\ColorRegions[2]{%
\foreach \rcolor [count=\i] in {#2}
{\FillSquare{#1}{\i}{\rcolor}}
}
\newcommand\PlaceLabels[2]{%
\foreach \rlabel [count=\i] in {#2}
{\LabelRegion{#1}{\i}{\rlabel}}
}
\begin{document}
\begin{tikzpicture}
\DrawSquare{3cm}{A}
\ColorRegions{A}{red!40,blue!40,green!40,yellow!40}
\DrawLines{A}
\PlaceLabels{A}{I,II,III,IV}
\DrawSquare[right=of A]{2cm}{B}
\ColorRegions{B}{gray!40,orange!40,cyan!40,magenta!40}
\DrawLines{B}
\PlaceLabels{B}{a,b,c,d}
\end{tikzpicture}
\end{document}
答案2
这是一个可以应用于每条路径(包括节点的路径)的解决方案。
这包括一个键:(divide
和一些辅助键)。
它的语法是列表的列表:
[divide={{gray!30:I,blue!30:II},{green!30:III,red!30:[green]IV}}]
意味着第一行是
{gray!30:I,blue!30:II}
第二行是
{green!30:III,red!30:[green]IV}.
结果如下所示。
代码还检查每一行、每一列和每个单元格的各种其他键。
这同样适用于放置在节中的节点(在您对此评论另一个答案之前我并不知道这一点)。仅使用跨越整个节的节点可能效果会更好。
通过使用低级 PGF 命令可以改进辅助坐标的计算。
代码
\documentclass[tikz,convert=false]{standalone}
\usepackage{etoolbox}
\usetikzlibrary{calc,shapes.misc}
\makeatletter
\def\qrr@ppbb{path picture bounding box}
\tikzset{
divide/.style={%
/utils/exec=%
\let\qrr@pathpicture\pgfutil@empty
\pgfutil@tempcnta\z@ % rows
\pgfutil@tempcntb\z@,% cols
/tikz/@divide rows/.list={#1},
path picture/.expand once=\qrr@pathpicture
},
@divide rows/.style={%
/utils/exec=\pgfutil@tempcntb\z@,
@divide cols/.list={#1},
/utils/exec=\advance\pgfutil@tempcnta\@ne
},
@divide cols/.code=
\let\pgf@tempb\pgfutil@empty
\let\pgf@tempc\pgfutil@empty
\pgfutil@in@{:}{#1}%
\ifpgfutil@in@
\pgfkeysalso{@divide cols split={#1}}%
\else
\def\pgf@tempa{#1}%
\fi
\eappto\qrr@pathpicture{%
\noexpand\path
($(\[email protected] west)!\the\pgfutil@tempcntb/\noexpand\the\pgfutil@tempcntb!(\[email protected] east)$)
coordinate (qrr@pp@tl)
($(\[email protected] west)!\number\numexpr\pgfutil@tempcntb+\@ne\relax/\noexpand\the\pgfutil@tempcntb!(\[email protected] east)$)
coordinate (qrr@pp@tr)
($(\[email protected] west)!\the\pgfutil@tempcnta/\noexpand\the\pgfutil@tempcnta!(\[email protected] west)$)
coordinate (qrr@pp@lt)
($(\[email protected] west)!\number\numexpr\pgfutil@tempcnta+\@ne\relax/\noexpand\the\pgfutil@tempcnta!(\[email protected] west)$)
coordinate (qrr@pp@bl);
\noexpand\path[
every divide/.try,
every divide \the\pgfutil@tempcntb\space row/.try,
every divide \the\pgfutil@tempcnta\space column/.try,
every divide \the\pgfutil@tempcntb-\the\pgfutil@tempcntb\space cell/.try,
\pgf@tempa,
every divide later/.try,
every divide \the\pgfutil@tempcntb\space row later/.try,
every divide \the\pgfutil@tempcnta\space column later/.try,
every divide \the\pgfutil@tempcntb-\the\pgfutil@tempcntb\space cell later/.try,
midway
] (qrr@pp@tl |- qrr@pp@lt)
coordinate (cell-\the\pgfutil@tempcntb-\the\pgfutil@tempcnta-tl)
rectangle (qrr@pp@tr |- qrr@pp@bl)
coordinate (cell-\the\pgfutil@tempcntb-\the\pgfutil@tempcnta-br)
\ifx\pgf@tempc\pgfutil@empty\else
node[
every divide node/.try,
every divide \the\pgfutil@tempcntb\space row node/.try,
every divide \the\pgfutil@tempcnta\space column node/.try,
every divide \the\pgfutil@tempcntb-\the\pgfutil@tempcntb\space cell node/.try,
\expandafter\unexpanded\expandafter{\pgf@tempb}] {\expandafter\unexpanded\expandafter{\pgf@tempc}}
\fi
;
}%
\advance\pgfutil@tempcntb\@ne,
@divide cols split/.code args={#1:#2}{
\def\pgf@tempa{#1}%
\pgfutil@ifnextchar[\qrr@divide@splitopt{\qrr@divide@splitopt[]}#2\@qrr@divide@splitopt
}
}
\def\qrr@divide@splitopt[#1]#2\@qrr@divide@splitopt{\def\pgf@tempb{#1}\def\pgf@tempc{#2}}
\makeatother
\tikzset{every divide node/.style={midway,text=black}}
\begin{document}
\tikz[every divide/.style={fill}] \draw (0,0) rectangle (2,3) [divide={{gray!30:I,blue!30:II},{green!30:III,red!30:IV}}];
\tikz[every divide/.style={fill},every divide later/.style={draw=black}] \draw (1,2) circle [x radius=2, y radius=3] [divide={{gray!30,blue!30},{green!30,red!30}}];
\tikz[every divide/.style={fill,sharp corners}] \draw[rounded corners=1cm] (0,0) rectangle (2,3) [divide={{gray!30,blue!30},{green!30,red!30}}];
\tikz[every divide/.style={fill,sharp corners}] \node[draw,minimum size=3cm, minimum height=1.5cm, rounded corners=.5cm,divide={{gray!30,blue!30,yellow},{green!30,red!30,blue}}] {};
\begin{tikzpicture}
\node[draw,rounded rectangle,minimum size=4cm,minimum height=2cm,
divide={{draw,draw=gray!75!black,{fill=gray,draw=gray!75!black},{draw,fill=gray}},{draw,,draw=gray!75!black,draw}}
] (n) {};
\draw (cell-1-0-tl) -- (cell-1-0-tl |- cell-1-0-br);
\end{tikzpicture}
\end{document}
输出