Hatena::ブログ(Diary)

マクロツイーター このページをアンテナに追加 RSSフィード Twitter

2013-03-02

TikZ は dvipdfmx をどこまでサポートするか? (2)

前回の記事で dvipdfm での PGF(TikZ)の機能制限として挙げた項目の中に

図画間結合(inter-picture connections)は pdfTeX の最近の版でのみサポートされる。

というものがある。今回の記事ではこの機能および現状の dvipdfmx でのサポート状況について解説する。併せて pTeX 系エンジンでこの機能を使う方法について説明する。

図画間結合とは何か

TikZ では、「ノードに名前を付けて後でその位置を参照する」という機能がある。例えば、以下の例では、5 つのノードP0P4 の名前を付けて、その後で、ノード同士を結ぶ折れ線を「名前を参照して」描いている。

\begin{tikzpicture}
% 5個のノードを名前付きで描く
\node[rectangle,draw] at (  0:1cm) (P0) {0};
\node[rectangle,draw] at ( 72:1cm) (P1) {1};
\node[rectangle,draw] at (144:1cm) (P2) {2};
\node[rectangle,draw] at (216:1cm) (P3) {3};
\node[rectangle,draw] at (288:1cm) (P4) {4};
% ノード同士を結ぶ折れ線を描く
\draw (P0)--(P2)--(P4)--(P1)--(P3)--(P0);
\end{tikzpicture}
f:id:zrbabbler:20130302215203p:image

通常は、ある tikzpicture 環境*1内で定義された「名前」はその環境の中でしか参照できない。「図画間結合」というのは、このように通常ではできない「自身以外の tikzpicture 環境にあるノードの参照」を可能にするための機能である。次のように tikzpicture 環境のオプションに「remember picture」を入れるとこの機能が有効になり、その環境内で定義したノードの位置を、同様に remember picture を付けた*2別の tikzpicture 環境の中で(通常のノード座標系書式、例えば NodeA.south 等により)参照可能になる。

\begin{tikzpicutre}[remember picture]
  \node[circle,draw](P1) at (0,0) {};
  \coordinate(P2) at (3,2); % coordinate もノードの一種
\end{tikzpicture}
\begin{tikzpicutre}[remember picture,overlay] % overlay に注意
  % 前の tikzpicture 中のノード P1, P2 を参照している
  \draw[->,thick] (P1.east)--(P2);
    % ※無論この例では別環境にする意味はない
\end{tikzpicture}

上の例の 2 つ目の tikzpicture のオプション overlay は「この図の外見のサイズをゼロにする」オプションである。「自身の外の」ノードの位置に何かを描画するという場合、当然その部分が「自身の描画領域(bounding box)」に含まれないように注意を払う必要がある。*3(なお、図画間結合を使う場合は、当然ながら、参照元と参照先の tikzpicture 環境は同じページに出力されている必要がある。)

図画間結合を用いた例

先に示した例では図画間結合を使う意味が全くないので、もう少し実用的な例を挙げておく。

\documentclass{article}
\usepackage[a6paper,scale=.8]{geometry}
\usepackage{amsmath}
\usepackage[svgnames]{xcolor} % Green等のSVG色名を使う
\usepackage{tikz}
%% \Anch{<名前>}{<色>}{<テキスト>}
% 指定のテキストを指定の色の四角枠で囲み, 指定の名前をもつTikZの
% ノードとして出力する. 図には remeber picture 属性を付けている
% ので外部から参照可能である.
\newcommand*{\Anch}[3]{%
  \tikz[remember picture,baseline=(#1.base)]
    \node[draw,rectangle,#2] (#1) {\normalcolor #3};
}
\begin{document}
For example consider
\begin{align}
% 数式環境中にノードを配置する
6x\>\Anch{T1}{Green}{$-\>7$} &= \Anch{T2}{Blue}{$4x$} + 8\sqrt2 + 9.
\intertext{By transposing terms we have}
6x\>\Anch{T3}{Blue}{$-\>4x$} &= 8\sqrt2 + 9\>\Anch{T4}{Green}{$+\>7$},
\intertext{and thus}
2x &= 8\sqrt2 + 16,
% ノード間を結ぶ矢印を別のTikZ環境で描く
\begin{tikzpicture}[remember picture,overlay]
\draw[->,Green] (T1.south)--(T4.north);
\draw[->,Blue]  (T2.south)--(T3.north);
\end{tikzpicture}
\end{align}
and they lived happily ever after.
\end{document}
f:id:zrbabbler:20130302215202p:image

この例の場合、数式を align で配置することが前提となるので、ノードの描画と矢印を単一の TikZ 環境に含めることはできない。*4

「図画間結合」は TeX エンジンに依存する

さて、容易に予想されるように、「図画間結合」の実現には本来の TeX にはない「拡張機能」が使われているので、この機能は「ドライバ依存」となっている。ただし他の「ドライバ依存」と少し事情が異なる。ここで使われている「拡張機能」は「TeX組版内容内での任意の位置に対するページ内絶対位置を取得する」というものであるが、これは「DVI ドライバ」の拡張機能ではなく「TeX 組版エンジン」の拡張機能なのである。だからこの機能が使えるかどうかは「どの DVI ドライバPDF に変換するか」ではなく「どの TeX エンジンを用いて文書を組版するか」に依存することになる。*5冒頭で紹介した TikZ のマニュアルの機能制限の説明で

pdfTeX の最近の版でのみサポートされる。

となっているのもこの事情に拠る。(なお、欧文 LaTeXlatex コマンド)の実行にはかなり以前から pdfTeX エンジンが使われるようになっている。)DVI ドライバの違いは関係がないので、dvips のドライバの機能制限も全く同じになっている。従って、「dvipdfmx」でも状況は変わらないということが解るであろう。もし、この「ページ内絶対位置の取得」という拡張機能が本当に pdfTeX でしかサポートされてないとすると、和文組版のために pTeX 系(pTeX/upTeX)のエンジンを用いる場合には「図画間結合」は原理的に使用不可能ということになってしまう。

pTeX 系で「図画間結合」を使う可能性

しかし実状は異なる。「ページ内絶対位置の取得」の機能の現状のサポート状況は次の通りである。

  • この機能を初めて実装したのが pdfTeX である。それを継承する LuaTeX でも提供される。
  • XeTeX は pdfTeX 互換ではないが、この機能は提供されている。
  • pTeX 系エンジンについては、e-TeX 拡張版の e-pTeX / e-upTeX であればこの機能が提供されている。

従って、pTeX(upTeX でも同様*6)で「ページ内絶対位置の取得」の機能(を利用した LaTeX パッケージ)を使いたい場合、もし e-pTeX が利用可能であればそれを利用すればよいことになる。TeX Live 2011 以降では pLaTeXplatex コマンド)のエンジンは e-pTeX に置き換えられている。それより少し古い頃の W32TeX*7では eplatex というコマンドで e-pTeX エンジンで動く pLaTeX が利用できる。

pxpgfmark パッケージ

これまでの話から考えると e-pTeX エンジンであれば普通に dvipdfmx のドライバを使って TikZ の「図画間結合」が利用できそうである。ところが残念ながらドライバの実装の都合*8でそうなっていない。これは容易に修正できるので、パッケージを作成した。

次のように、TikZ パッケージ*9より後にこのパッケージを読み込むと、e-pTeX エンジンで「図画間結合」が有効になる。

\documentclass[dvipdfmx]{jsarticle}
\usepackage[a6paper,scale=.8]{geometry}
\usepackage{amsmath}
\usepackage[svgnames]{xcolor}
\usepackage{tikz}
\usepackage{pxpgfmark} % remember picture を可能にする
%% \Anch{<名前>}{<色>}{<テキスト>}
\newcommand*{\Anch}[3]{%
  \tikz[remember picture,baseline=(#1.base)]
    \node[draw,rectangle,#2] (#1) {\normalcolor #3};
}
\begin{document}
例えば次の例では:
\begin{align}
6x\>\Anch{T1}{Green}{$-\>7$} &= \Anch{T2}{Blue}{$4x$} + 8\sqrt2 + 9
\intertext{移項すると:}
6x\>\Anch{T3}{Blue}{$-\>4x$} &= 8\sqrt2 + 9\>\Anch{T4}{Green}{$+\>7$}
\intertext{ゆえに:}
2x &= 8\sqrt2 + 16
\begin{tikzpicture}[remember picture,overlay]
\draw[->,Green] (T1.south)--(T4.north);
\draw[->,Blue]  (T2.south)--(T3.north);
\end{tikzpicture}
\end{align}
めでたしめでたし。
\end{document}
f:id:zrbabbler:20130302215201p:image

*1:または \tikz 命令。以下同様。

*2:両方の環境で remember picture が必要な理由は、記録された参照元と参照先の「ページ内絶対座標」から参照先の「相対座標」に変換する必要があるため。

*3:これを忘れると「コンパイルする度に領域が拡大する」という妙な現象が起こる。なお、tikzpicture に overlay を付けるとその図全体が大きさを持たないことになるので、これが不適当なら、\useasboundingbox 命令を使うなり、「外に描く」部分を overlay 付きの scope 環境に入れる等の別の方策が必要になる。

*4:ちなみにこの例では、全ての TikZ 環境は align 環境の中入れているため必ず同一ページに出力されることが保証されている。

*5:ただし、pdfTeX のように「組版」の部分と「DVI ドライバ」の部分が一体になっているエンジンではこの区別が解りにくいのも確かである。

*6:これ以下の説明で「p」を「up」に置き換えたものも成立する。

*7:および美文書第 5 版の DVD からインストールした TeX システム。

*8:直接エンジンが pdfTeX であるかを検査して、そうである場合にのみ機能を有効化している。

*9:または PGF パッケージ。Beamer クラスは内部で PGF を読み込んでいるので、この場合はプリアンブルのどこで読み込んでもよい。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/zrbabbler/20130302/1362228901