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
Так что если вы правильно выберете шрифт, вы сможете избежать ошибки. Лично я все равно предпочел бы иметь объяснение того, как ее избежать, независимо от выбора шрифта.