2019年05月02日更新

図式の書き方について

当サイトのPDFでは数多くの図式を描いていますが、TeXでどうやってこれらの図式を描いているのか、時々質問を受けるのでここにやり方を書いておきます。

まずTeXで図式を描くパッケージはいくつかあって、amscd、Xy-pic、TikZなどが知られています。多分検索してすぐ出てくるのはamscdで、これは簡単に使えるのですがあまり自由度が高くありません。四角い可換図式をちょっと描きたいくらいであればこれでもいいのですが当サイトで描きたいような図式を描くには向いていません。するとXy-picかTikZですが、当サイトではTikZを使っています。理由はXy-picよりもTikZの方が出力される図式がキレイ(に感じる)からです。あと多分、TikZの方が自由度が高いです(Xy-picよく知らないので実際どうかはわからない)。

さて、では実際TikZを使ってどうやって図式を描くのかを説明していきます。 (注: より詳しい説明をPDF「TikZの使い方」に書きました。 このページの説明は体系的ではなく、分かりにくいので出来ればPDFを読んでください。)

まずは \usepackage{tikz} でTikZを読み込みます。するとtikzpicture環境というのが使えるようになるので、この環境で図式を描いていきます。例えば普通の四角い図式の場合は以下のように書きます。(詳細は後述)

\begin{tikzpicture}[auto]
\node (a) at (0, 1.2) {$a$}; \node (x) at (1.2, 1.2) {$x$};
\node (b) at (0, 0) {$b$};   \node (y) at (1.2, 0) {$y$};
\draw[->] (a) to node {$\scriptstyle f$} (x);
\draw[->] (x) to node {$\scriptstyle p$} (y);
\draw[->] (a) to node[swap] {$\scriptstyle i$} (b);
\draw[->] (b) to node[swap] {$\scriptstyle g$} (y);
\end{tikzpicture}

これは次の図式を出力する命令です。

この命令をそのままコピペしてコンパイルすれば上記の図式が出る。となればよいのですが、そうはならない場合があります(私はここで一回つまづきました)。これはドライバの設定がどうとかあって、その辺りの設定がきちんとできていないと正常に出力されないのです。

ドライバのことはよく分からないので正確な説明はできないのですが……私の場合は \documentclass のオプションに dvipdfmx を付けることで正常に出力されるようになりました。(例: \documentclass[uplatex,a4j,12pt,dvipdfmx]{jsarticle}。dvipdfmxを使っているのであればこれで、そうでなければそれ用の設定をすれば出力される? よくわからない)

さて、上記の命令をコピペして図式が正常に出るようになれば、あとは命令の内容を理解するだけです。まず、

\node (a) at (0, 1.2) {$a$}; \node (x) at (1.2, 1.2) {$x$};
\node (b) at (0, 0) {$b$};   \node (y) at (1.2, 0) {$y$};

の部分が圏でいう対象を定義している部分になります。 例えば \node (a) at (0, 1.2) {$a$}; は、座標(0, 1.2)に $a$ を置く、という意味になります。(a) の部分はラベルで、このラベルを使って射を書くことができます。もちろんラベル名はもっと長い名前も付けられますし、また省略することもできます(例えば \node at (0, 1.2) {$a$}; となる)。次の

\draw[->] (a) to node {$\scriptstyle f$} (x);
\draw[->] (x) to node {$\scriptstyle p$} (y);
\draw[->] (a) to node[swap] {$\scriptstyle i$} (b);
\draw[->] (b) to node[swap] {$\scriptstyle g$} (y);

の部分が、射を定義する部分です。例えば \draw[->] (a) to node {$\scriptstyle f$} (x); はラベルaの対象からラベルbの対象に射を書き、射の名前を $\scriptstyle f$ とする、という意味になります。(射の名前が必要ない場合は省略して \draw[->] (a) to (x); と書くこともできます。)ちなみに通常は射の名前は矢印の進行方向に対して左側に付くので、逆にしたい場合は node[swap] とします。(今気づいたのですが、これは \begin{tikzpicture}[auto][auto] という設定をしているからですね。)

ここまで理解すれば、簡単な図式は大体書けますね。座標をいい感じに設定して対象を置き、これらを射で結ぶだけです。

もちろんこれだけでなく、色々とやりたいことがあると思います。例えば射をモノ射の形に変える、対象を四角で囲む、色を変える、射を点線にする、射を曲線にする、などなど……

こういうのは検索すると大体出てくるので、検索してください。あとは、TikZは分厚いマニュアルがあるのでそれを見るという方法もあります。

ただ折角なので一応、上記を実現するサンプルを以下に置いておくので参考にしてください。

\begin{tikzpicture}[auto]
\node (a) at (0, 1.2) {$a$}; \node (x) at (1.2, 1.2) {$x$};
\node (b) at (0, 0) {$b$};   \node (y) at (1.2, 0) {$y$};
\node (u) at (3, 0) {$u$};
\node[shape=rectangle, draw] (s) at (1.5, -1.2) {$s$}; 

\draw[->, draw=red] (a) to node {$\scriptstyle f$} (x);
\draw[<-] (x) to (y);
\draw[>->] (a) to node[swap] {$\scriptstyle i$} (b);
\draw[|->] (b) to node[swap] {$\scriptstyle g$} (y);

\draw[-, line width=5pt, draw=white] (a) to (u);
\draw[->] (a) to (u);
\draw[->, dashed] (y) to (u);

\draw[->] (x) to[bend left=30] node {$\scriptstyle k$} (u);

\draw[->] (b) to[bend right=40] (s);
\draw[->] (s) to node[swap, pos=0.7] {$\scriptstyle h$} (u);
\end{tikzpicture}

これで

が出力されます。

  • 射が斜めのときに、~ などをいい感じに沿わせたい時は node のオプションに slopedと書きます。

    \begin{tikzpicture}[auto]
    \node (a) at (0, 0) {$a$}; \node (x) at (2, 1) {$b$};
    \draw[->] (a) to node[sloped] {$\scriptstyle \sim$} (x);
    \end{tikzpicture}

  • 例えば、曲げた赤い矢印 \draw[->, bend left=30, draw=red] をよく使う場合、予め \tikzset{hoge/.style={->, bend left=30, draw=red}} と書いておくと、\draw[hoge] と書くだけで \draw[->, bend left=30, draw=red] と書くのと同じ状態になります。
  • 射を立体的に交差させたい場合は、次のように書くとできます。

    \begin{tikzpicture}[auto]
    \node (a) at (0, 0) {$a$};
    \node (b) at (2, 0) {$b$};
    \node (c) at (1, 1) {$c$};
    \node (d) at (1, -1) {$d$};
    \draw[->] (a) to (b);
    \draw[-, line width=6pt,draw=white] (c) to (d);
    \draw[->] (c) to (d);
    \end{tikzpicture}

  • コメント

    コメントはまだありません。

    コメントする

    感想、意見、質問など何でもどうぞ。
    ※書き込んだのに表示されない場合は、ページをリロードしてみてください。