стили sn ребер и хороших пустых узлов в лесу приводят к делению на ноль; что происходит?

стили sn ребер и хороших пустых узлов в лесу приводят к делению на ноль; что происходит?

Theforestруководствоопределяет два стиля: sn edgesи 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ошибка. Я отследил проблему вплоть до \pgfintersectionofpathsбиблиотеки pgf. intersectionsСледующий код воспроизводит точную ошибку без forest.

\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, который вычисляет пересечение двух линий, применяя некоторое преобразование координат к некоторой точке. Математические подробности двух "some" в предыдущем предложении не важны, за исключением того факта, что последний шаг в вычислении PGF соответствующей матрицы преобразования — это инверсия некоторой другой матрицы, путем вызова \pgftransforminvert. Это , \pgftransforminvertкоторый терпит неудачу, поскольку матрица, которую он пытается инвертировать, почти сингулярна. Руководство PGF (стр. 641) предупреждает, что это произойдет:

Эта команда выдаст ошибку, если определитель матрицы слишком мал, то есть если матрица близка к вырожденной.

Но почему матрица почти сингулярна? Потому что отрезки, которые мы пытаемся пересечь, почти параллельны. В этот момент мне показалось, что источником проблемы была численная точность TeX. Однако...

Перед вычислением пересечения линий путем вызова пытается определить, пересекаются ли линии: это делается в -like . Поэтому я считаю \pgfpointintersectionoflines, что проблема в том, что утверждает, что линии пересекаются, но дает сбой во время вычисления пересечения. (Код содержит замечание "16384 может быть ненадёжным выбором.", где 16384 - константа, используемая в каком-то внутреннем процессе нормализации. Может ли это быть источником проблемы?)\pgfintersectionofpaths\if\pgfiflinesintersect\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 пересечение, другой вариант, где прямые (точно) параллельны, дает 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

Так что если вы правильно выберете шрифт, вы сможете избежать ошибки. Лично я все равно предпочел бы иметь объяснение того, как ее избежать, независимо от выбора шрифта.

Связанный контент