フォレスト内の sn エッジと適切な空ノード スタイルにより、ゼロ除算が発生します。何が起こっているのでしょうか。

フォレスト内の sn エッジと適切な空ノード スタイルにより、ゼロ除算が発生します。何が起こっているのでしょうか。

forestマニュアルsn edgesは と の2 つのスタイルを定義します。nice empty nodesこれらは次のように定義されます。

sn edges/.style={for tree={parent anchor=south, child anchor=north}}

そして

nice empty nodes/.style={for tree={calign=fixed edge angles},delay={where content={}{shape=coordinate,for parent={for children={anchor=north}}}{}} }

それぞれ。

これらの両方のスタイルを次のツリーで使用すると、次のエラーが発生します。

! Package PGF Math Error: You asked me to calculate `1/0.0', but I cannot divid
e any number by zero.

See the PGF Math package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.51 \end{forest}

何が起こっているのか知っている人はいませんか? どうすればこれを修正できますか?

ムウェ

\documentclass{article}

\usepackage{forest}
\forestset{
sn edges/.style={for tree={parent anchor=south, child anchor=north}},
nice empty nodes/.style={for tree={calign=fixed edge angles},delay={where content={}{shape=coordinate,for parent={for children={anchor=north}}}{}}}
}

\begin{document}

\begin{forest} nice empty nodes, sn edges
    [TP
        [{the ball} ]
        [
            [T ]
            [PrP
                [{$<$the ball$>$} ]
                [
                    [Pr ]
                    [VoiP
                        [{$<$the ball$>$} ]
                        [
                            [Voi ]
                            [AffP
                                [{to Mary} ]
                                [
                                    [Aff ]
                                    [ThP
                                        [{$<$the ball$>$} ]
                                        [
                                            [Th ]
                                            [AgP
                                                [{by John} ]
                                                [
                                                    [Ag ]
                                                    [$\surd$throw ]
                                                ]
                                            ]
                                        ]
                                    ]
                                ]
                            ]
                        ]
                    ]
                ]
            ]
        ]
    ]
\end{forest}

\end{document}

アップデート

興味深いことに、リーフの下のすべてが削除されてもエラーなしでコンパイルされますAff。つまり、次のコードはコンパイルされます。

\begin{forest} nice empty nodes, sn edges
    [TP
        [{the ball} ]
        [
            [T ]
            [PrP
                [{$<$the ball$>$} ]
                [
                    [Pr ]
                    [VoiP
                        [{$<$the ball$>$} ]
                        [
                            [Voi ]
                            [AffP
                                [{to Mary} ]
                                [
                                    [Aff ]
                                ]
                            ]
                        ]
                    ]
                ]
            ]
        ]
    ]
\end{forest}

答え1

まず、注意点: スタイルがなくてもエラーが発生しますsn edges

forestこれは ではなく、バグだと思います。のライブラリpgfに問題がないか調べました。次のコードは なしで正確なエラーを再現します。\pgfintersectionofpathspgfintersectionsforest

\pgfintersectionofpaths{%
  \pgfpathmoveto{\pgfpoint{0.0pt}{-3.53297pt}}
  \pgfpathlineto{\pgfpoint{19.54204pt}{-31.44316pt}}%
}{%
  \pgfpathmoveto{\pgfpoint{34.6372pt}{-53.00208pt}}%
  \pgfpathlineto{\pgfpoint{19.54204pt}{-31.44316pt}}}

この問題をさらに詳しく調べてみました。\pgfintersectionofpathsは を呼び出し \pgfpointintersectionoflines、これはある点に何らかの座標変換を適用して 2 本の直線の交点を計算します。前の文の 2 つの「何らかの」の数学的詳細は重要ではありませんが、PGF の関連する変換行列の計算の最終ステップは を呼び出すことによって他の何らかの行列を反転することであるという事実は重要です\pgftransforminvert\pgftransforminvert反転しようとしている行列がほぼ特異であるため、 は失敗します。PGF マニュアル (p. 641) では、これが起こると警告しています。

このコマンドは、行列の行列式が小さすぎる場合、つまり行列がほぼ特異である場合にエラーを生成します。

しかし、なぜ行列はほぼ特異なのでしょうか? 交差しようとしている線分がほぼ平行だからです。この時点では、問題の原因は TeX の数値精度にあるように思えました。しかし...

を呼び出して直線の交差を計算する前に\pgfpointintersectionoflines\pgfintersectionofpathsは直線が交差するかどうかを検出しようとします。これは の\ifように で実行されます。したがって、 は直線が交差していると主張しているものの、交差の計算中に失敗するという点\pgfiflinesintersectが問題であると考えられます。( のコードには、「16384 は堅牢な選択ではない可能性があります。」というコメントが含まれています。ここで、16384 は内部の正規化プロセスで使用される定数です。これが問題の原因でしょうか?)\pgfiflinesintersect\pgfpointintersectionoflines\pgf@iflinesintersect

の動作を\pgfintersectionofpathsさらに調査したところ、実際には一貫性がないことがわかりました。 の次の呼び出しは\pgfintersectionofpaths同じ結果 (1 つの交差点、原点) を生成することが予想されます。

\pgfintersectionofpaths
  {\pgfpathmoveto{\pgfpoint{0pt}{0pt}}\pgfpathlineto{\pgfpoint{1pt}{0pt}}}
  {\pgfpathmoveto{\pgfpoint{0pt}{0pt}}\pgfpathlineto{\pgfpoint{0pt}{1pt}}}
\pgfintersectionsolutions

\pgfintersectionofpaths
  {\pgfpathmoveto{\pgfpoint{0pt}{0pt}}\pgfpathlineto{\pgfpoint{1pt}{0pt}}}
  {\pgfpathmoveto{\pgfpoint{0pt}{0pt}}\pgfpathlineto{\pgfpoint{-1pt}{0pt}}}
\pgfintersectionsolutions

しかし、これは当てはまりません。線が垂直な最初の例では、交点は 1 つ生成されますが、線が (正確に) 平行なもう 1 つの例では、交点は 0 つ生成されます。

これを修正したいのですが、この問題は私にとっては複雑すぎるように思われます。いずれにせよ、これは議論する価値があり、作者にpgf通知する必要があると思います。

答え2

なぜそうなるのかはわかりませんが、このエラーは使用されているフォントに関連しているようです。

次の構成を使用して MWE をコンパイルすると、エラーを再現できます。

  • フォント指定なし(Computer/Latin Modern)、pdfLaTeX または XeLaTeX でコンパイル
  • \usepackage{palatino}pdfLaTeXまたはXeLaTeXでコンパイルされた
  • \usepackage{libertine}pdfLaTeXまたはXeLaTeXでコンパイルされた
  • \usepackage{fontspec} \setmainfont{Linux Libertine O}XeLaTeXでコンパイル
  • \usepackage{fontspec} \setmainfont{Doulos SIL}XeLaTeXでコンパイル
  • \usepackage{fontspec} \setmainfont{TeX Gyre Pagella}XeLaTeXでコンパイル

しかし、これらの構成では、エラーなしでコンパイルされます。

  • \usepackage{times}pdfLaTeXまたはXeLaTeXでコンパイルされた
  • \usepackage{kpfonts}pdfLaTeXまたはXeLaTeXでコンパイルされた
  • \usepackage{fontspec} \setmainfont{Charis SIL}XeLaTeXでコンパイル
  • \usepackage{fontspec} \setmainfont{Cambria}XeLaTeXでコンパイル
  • \usepackage{fontspec} \setmainfont{Brill}XeLaTeXでコンパイル
  • \usepackage{fontspec} \setmainfont{Times New Roman}XeLaTeXでコンパイル

この場合、別のエラーが発生しました (\end{forest}行の寸法が大きすぎます)。

  • \usepackage{fontspec} \setmainfont{TeX Gyre Termes}XeLaTeXでコンパイル

したがって、フォントを正しく選択すれば、エラーを回避できます。ただし、個人的には、フォントの選択に関係なく、エラーを回避する方法についての説明があるとありがたいと思います。

関連情報