问:pNiceMatrix/bNiceMatrix 中的基线没有完全对齐

问:pNiceMatrix/bNiceMatrix 中的基线没有完全对齐

是否有可能完美地对齐基线p/bNiceMatrix?(当你有一个大矩阵时,错位是相当明显的......)

平均能量损失

\documentclass{article}

\usepackage{nicematrix}

\begin{document}
    
\begin{equation}
    \rlap{\rule{57mm}{0.11pt}}0 = \begin{NiceMatrix}[baseline=2]
        0 & 1 \\
        0 & 1 \\
        0 & 1 \\
    \end{NiceMatrix}\quad
    0 = \begin{pNiceMatrix}[baseline=2]
        0 & 2 \\
        0 & 2 \\
        0 & 2 \\
    \end{pNiceMatrix}\quad
    0 = \begin{bNiceMatrix}[baseline=2]
        0 & 3 \\
        0 & 3 \\
        0 & 3 \\
    \end{bNiceMatrix}
\end{equation}
    
\end{document}

结果

在此处输入图片描述


感谢大家的回复。

更新:@Ruixi Zhang 建议的补丁解决了错位问题。

更新 2 (2021-11-26):该补丁似乎有副作用。

测试代码

\usepackage{booktabs}
\usepackage{nicematrix}
...
\begin{table}[h]
    \caption{A table}
    \centering
    \begin{NiceTabular}{ll}[cell-space-limits=3pt]
        \toprule
        a & b \\
        \midrule
        \Block{}{new\\line} & c \\
        \bottomrule
    \end{NiceTabular}
\end{table}

副作用

答案1

(2021/11/23)的6.4版本nicematrix解决了该bug nicematrix

这是一个 MWE。

最终,我没有使用 Ruixi Zhang 的 LaTeX 补丁(参见其他答案),因为当在矩阵中的某个地方使用{array}该命令时似乎会产生后果。\Block\\

\documentclass{article}
\usepackage{nicematrix}

    \begin{document}

\begin{equation}
    \rlap{\rule{57mm}{0.11pt}}0 = \begin{NiceMatrix}[baseline=2]
        0 & 1 \\
        0 & 1 \\
        0 & 1 \\
    \end{NiceMatrix}\quad
    0 = \begin{pNiceMatrix}[baseline=2]
        0 & 2 \\
        0 & 2 \\
        0 & 2 \\
    \end{pNiceMatrix}\quad
    0 = \begin{bNiceMatrix}[baseline=2]
        0 & 3 \\
        0 & 3 \\
        0 & 3 \\
    \end{bNiceMatrix}
\end{equation}
    
\end{document}

与往常一样nicematrix,您需要进行多次编译。

上述代码的输出

答案2

这是一个“双重”错误。第一部分在 LaTeX 内核本身中,第二部分在软件包中nicematrix

  1. 该错误的第一部分存在于底层array环境中(自 LaTeX2.09 以来就一直存在)。我两年前就向 LaTeX 团队报告了这个问题(https://github.com/latex3/latex2e/issues/147)。任何修复将要破坏了向后兼容性,因此修复不太可能在内核中实现。

    问题在于,每行array都有一个“支柱”。该支柱的高度与深度之比为 7:3。但它的高度应为<half baseline> + <math axis>,深度应为<half baseline> - <math axis>。在大多数情况下,差异非常小,但仍然明显到足以导致错位。

    例如,在 Computer Modern Math 中设置了基线间隔10pt的文章12pt应具有 8.5pt 的支柱高度和 3.5pt 的支柱深度。但是 LaTeX 将支柱高度设置为约 8.4pt,将支柱深度设置为约 3.6pt,从而导致微小的 0.1/2=0.05pt 错位。

  2. 该错误的第二部分是在环境中NiceArrayWithDelims。即使我们修复了内核支柱行为,仍然存在 0.4pt 的错位。问题似乎出在 中。似乎缺少 的\vcenter{ \skip_vertical:N -\l_tmpa_dim ... \skip_vertical:N -\l_tmpb_dim }偏移量。\arrayrulewidth

    没有简单的方法来修补 LaTeX3 环境,所以我将直接复制NiceArrayWithDelims下面的整个定义。只替换了两行代码。因此,此修复程序是不是需要认真对待。它只是暂时的解决办法。

完整代码:

\documentclass{article}

\usepackage{nicematrix}

% Fix the LaTeX kernel part of the bug
\usepackage{etoolbox}
\makeatletter
\AtBeginDocument{%
  % nicematrix loads array.sty
  \patchcmd\@array
    {\arraystretch \@tempdima}
    {\dimexpr\arraystretch\baselineskip/2
      +\arraystretch\extrarowheight
      +\fontdimen22\textfont\tw@\relax}
    {\typeout{Fixed array strut height for array.sty}}
    {\typeout{Couldn't patch \string\@array}}%
  \patchcmd\@array
    {\arraystretch \dp \strutbox}
    {\dimexpr\arraystretch\baselineskip
      -\arraystretch\baselineskip/2
      -\fontdimen22\textfont\tw@\relax}
    {\typeout{Fixed array strut depth for array.sty}}
    {\typeout{Couldn't patch \string\@array}}%
  \let\@@array\@array
}
\makeatother

% `Fix' the package bug.
% Only two lines are replaced!!!
% Not to be taken as a serious fix!!!
\makeatletter
\ExplSyntaxOn
\RenewDocumentEnvironment { NiceArrayWithDelims }
  { m m O { } m ! O { } t \CodeBefore }
  {
    \bool_if:NT \c__nicematrix_revtex_bool \__nicematrix_patch_for_revtex:
    \__nicematrix_provide_pgfsyspdfmark:
    \bool_if:NT \c__nicematrix_footnote_bool \savenotes
    \bgroup
    \tl_gset:Nn \g__nicematrix_left_delim_tl { #1 }
    \tl_gset:Nn \g__nicematrix_right_delim_tl { #2 }
    \tl_gset:Nn \g__nicematrix_preamble_tl { #4 }
    \int_gzero:N \g__nicematrix_block_box_int
    \dim_zero:N \g__nicematrix_width_last_col_dim
    \dim_zero:N \g__nicematrix_width_first_col_dim
    \bool_gset_false:N \g__nicematrix_row_of_col_done_bool
    \str_if_empty:NT \g__nicematrix_name_env_str
      { \str_gset:Nn \g__nicematrix_name_env_str { NiceArrayWithDelims } }
    \__nicematrix_adapt_S_column:
    \bool_if:NTF \l__nicematrix_NiceTabular_bool
      \mode_leave_vertical:
      \__nicematrix_test_if_math_mode:
    \bool_if:NT \l__nicematrix_in_env_bool { \__nicematrix_fatal:n { Yet~in~env } }
    \bool_set_true:N \l__nicematrix_in_env_bool
      \cs_gset_eq:NN \__nicematrix_old_CT@arc@ \CT@arc@
    \cs_if_exist:NT \tikz@library@external@loaded
      {
        \tikzexternaldisable
        \cs_if_exist:NT \ifstandalone
          { \tikzset { external / optimize = false } }
      }
    \int_gincr:N \g__nicematrix_env_int
    \bool_if:NF \l__nicematrix_block_auto_columns_width_bool
      { \dim_gzero_new:N \g__nicematrix_max_cell_width_dim }
    \seq_gclear:N \g__nicematrix_blocks_seq
    \seq_gclear:N \g__nicematrix_pos_of_blocks_seq
    \seq_gclear:N \g__nicematrix_pos_of_stroken_blocks_seq
    \seq_gclear:N \g__nicematrix_pos_of_xdots_seq
    \tl_gclear_new:N \g__nicematrix_code_before_tl
    \tl_gclear:N \g__nicematrix_row_style_tl
    \bool_gset_false:N \g__nicematrix_aux_found_bool
    \tl_if_exist:cT { c__nicematrix _ \int_use:N \g__nicematrix_env_int _ tl }
      {
        \bool_gset_true:N \g__nicematrix_aux_found_bool
        \use:c { c__nicematrix _ \int_use:N \g__nicematrix_env_int _ tl }
      }
     \tl_gclear:N \g__nicematrix_aux_tl
    \tl_if_empty:NF \g__nicematrix_code_before_tl
      {
        \bool_set_true:N \l__nicematrix_code_before_bool
        \tl_put_right:NV \l__nicematrix_code_before_tl \g__nicematrix_code_before_tl
      }
    \bool_if:NTF \l__nicematrix_NiceArray_bool
      { \keys_set:nn { NiceMatrix / NiceArray } }
      { \keys_set:nn { NiceMatrix / pNiceArray } }
    { #3 , #5 }
    \tl_if_empty:NF \l__nicematrix_rules_color_tl
      { \exp_after:wN \__nicematrix_set_CT@arc@: \l__nicematrix_rules_color_tl \q_stop }
    \IfBooleanTF { #6 } \__nicematrix_pre_array_i:w \__nicematrix_pre_array:
  }
  {
    \bool_if:NTF \l__nicematrix_light_syntax_bool
      { \use:c { end __nicematrix-light-syntax } }
      { \use:c { end __nicematrix-normal-syntax } }
    \c_math_toggle_token
    \skip_horizontal:N \l__nicematrix_right_margin_dim
    \skip_horizontal:N \l__nicematrix_extra_right_margin_dim
    \hbox_set_end:
    \bool_if:NT \l__nicematrix_width_used_bool
      {
        \int_compare:nNnT \g__nicematrix_total_X_weight_int = 0
          { \__nicematrix_error:n { width~without~X~columns } }
      }
    \int_compare:nNnT \g__nicematrix_total_X_weight_int > 0
      {
        \tl_gput_right:Nx \g__nicematrix_aux_tl
          {
            \bool_set_true:N \l__nicematrix_X_columns_aux_bool
            \dim_set:Nn \l__nicematrix_X_columns_dim
              {
                \dim_compare:nNnTF
                  {
                    \dim_abs:n
                      { \l__nicematrix_width_dim - \box_wd:N \l__nicematrix_the_array_box }
                  }
                  <
                  { 0.001 pt }
                  { \dim_use:N \l__nicematrix_X_columns_dim }
                  {
                    \dim_eval:n
                      {
                        ( \l__nicematrix_width_dim - \box_wd:N \l__nicematrix_the_array_box )
                        / \int_use:N \g__nicematrix_total_X_weight_int
                        + \l__nicematrix_X_columns_dim
                      }
                  }
              }
          }
      }
    \int_compare:nNnT \l__nicematrix_last_row_int > { -2 }
      {
        \bool_if:NF \l__nicematrix_last_row_without_value_bool
          {
            \int_compare:nNnF \l__nicematrix_last_row_int = \c@iRow
              {
                \__nicematrix_error:n { Wrong~last~row }
                \int_gset_eq:NN \l__nicematrix_last_row_int \c@iRow
              }
          }
      }
    \int_gset_eq:NN \c@jCol \g__nicematrix_col_total_int
    \bool_if:nTF \g__nicematrix_last_col_found_bool
      { \int_gdecr:N \c@jCol }
      {
        \int_compare:nNnT \l__nicematrix_last_col_int > { -1 }
          { \__nicematrix_error:n { last~col~not~used } }
      }
    \int_gset_eq:NN \g__nicematrix_row_total_int \c@iRow
    \int_compare:nNnT \l__nicematrix_last_row_int > { -1 } { \int_gdecr:N \c@iRow }
    \int_compare:nNnT \l__nicematrix_first_col_int = 0
      {
        \skip_horizontal:N \col@sep
        \skip_horizontal:N \g__nicematrix_width_first_col_dim
      }
    \bool_if:NTF \l__nicematrix_NiceArray_bool
      {
        \str_case:VnF \l__nicematrix_baseline_tl
          {
            b \__nicematrix_use_arraybox_with_notes_b:
            c \__nicematrix_use_arraybox_with_notes_c:
          }
          \__nicematrix_use_arraybox_with_notes:
      }
      {
        \int_compare:nNnTF \l__nicematrix_first_row_int = 0
          {
            \dim_set_eq:NN \l_tmpa_dim \g__nicematrix_dp_row_zero_dim
            \dim_add:Nn \l_tmpa_dim \g__nicematrix_ht_row_zero_dim
          }
          { \dim_zero:N \l_tmpa_dim }
        \int_compare:nNnTF \l__nicematrix_last_row_int > { -2 }
          {
            \dim_set_eq:NN \l_tmpb_dim \g__nicematrix_ht_last_row_dim
            \dim_add:Nn \l_tmpb_dim \g__nicematrix_dp_last_row_dim
          }
          { \dim_zero:N \l_tmpb_dim }
        \hbox_set:Nn \l_tmpa_box
          {
            \c_math_toggle_token
            \tl_if_empty:NF \l__nicematrix_delimiters_color_tl
              { \color { \l__nicematrix_delimiters_color_tl } }
            \exp_after:wN \left \g__nicematrix_left_delim_tl
            \vcenter
              {
%                \skip_vertical:N -\l_tmpa_dim
                \skip_vertical:n { -\l_tmpa_dim - \arrayrulewidth }
                \hbox
                  {
                    \bool_if:NTF \l__nicematrix_NiceTabular_bool
                      { \skip_horizontal:N -\tabcolsep }
                      { \skip_horizontal:N -\arraycolsep }
                    \__nicematrix_use_arraybox_with_notes_c:
                    \bool_if:NTF \l__nicematrix_NiceTabular_bool
                      { \skip_horizontal:N -\tabcolsep }
                      { \skip_horizontal:N -\arraycolsep }
                  }
%                \skip_vertical:N -\l_tmpb_dim
                \skip_vertical:n { -\l_tmpb_dim + \arrayrulewidth }
              }
            \tl_if_empty:NF \l__nicematrix_delimiters_color_tl
              { \color { \l__nicematrix_delimiters_color_tl } }
            \exp_after:wN \right \g__nicematrix_right_delim_tl
            \c_math_toggle_token
          }
        \bool_if:NTF \l__nicematrix_delimiters_max_width_bool
          {
            \__nicematrix_put_box_in_flow_bis:nn
              \g__nicematrix_left_delim_tl \g__nicematrix_right_delim_tl
          }
          \__nicematrix_put_box_in_flow:
      }
    \bool_if:NT \g__nicematrix_last_col_found_bool
      {
        \skip_horizontal:N \g__nicematrix_width_last_col_dim
        \skip_horizontal:N \col@sep
      }
    \bool_if:NF \l__nicematrix_Matrix_bool
      {
        \int_compare:nNnT \c@jCol < \g__nicematrix_static_num_of_col_int
          { \__nicematrix_error:n { columns~not~used } }
      }
    \group_begin:
    \globaldefs = 1
    \__nicematrix_msg_redirect_name:nn { columns~not~used } { error }
    \group_end:
    \__nicematrix_after_array:
    \egroup
    \iow_now:Nn \@mainaux { \ExplSyntaxOn }
    \iow_now:Nn \@mainaux { \char_set_catcode_space:n { 32 }  }
    \iow_now:Nx \@mainaux
      {
        \tl_gset:cn { c__nicematrix_ \int_use:N \g__nicematrix_env_int _ tl }
          { \exp_not:V \g__nicematrix_aux_tl }
      }
    \iow_now:Nn \@mainaux { \ExplSyntaxOff }
    \bool_if:NT \c__nicematrix_footnote_bool \endsavenotes
  }
\ExplSyntaxOff
\makeatother

\begin{document}
    
\begin{equation}
    \rlap{\rule{57mm}{0.11pt}}0 = \begin{NiceMatrix}[baseline=2]
        0 & 1 \\
        \rlap{\color{red}\rule{5.7mm}{0.11pt}}0 & 1 \\
        0 & 1 \\
    \end{NiceMatrix}\quad
    0 = \begin{pNiceMatrix}[baseline=2]
        0 & 2 \\
        \rlap{\color{red}\rule{5.7mm}{0.11pt}}0 & 2 \\
        0 & 2 \\
    \end{pNiceMatrix}\quad
    0 = \begin{bNiceMatrix}[baseline=2]
        0 & 3 \\
        \rlap{\color{red}\rule{5.7mm}{0.11pt}}0 & 3 \\
        0 & 3 \\
    \end{bNiceMatrix}
\end{equation}
    
\end{document}

里面的代码\AtBeginDocument{...}是从我自己的补丁文件中提取出来的(https://github.com/RuixiZhang42/font-pairing-guide/blob/master/mtpro2-patch.tex),截至撰写本文时为 852–866 行。它仅涵盖array.sty。更彻底的修复作为从 850 行到 911 行的代码提供。

答案3

这不是一个真正的答案,而只是\patchcmd修补 LaTeX3 环境(结束)的一种可能方法NiceArrayWithDelims,以便缩短“完整代码”示例中的相应部分@RuixiZhang 的回答

\makeatletter
\ExplSyntaxOn
% patch \cs{environment NiceArrayWidthDelims end aux }
\char_set_catcode_space:n {32} % restore catcode of space char

\expandafter\patchcmd
  \csname environment~ NiceArrayWithDelims~ end~ aux~ \endcsname
  {\skip_vertical:N -\l_tmpa_dim}
  {\skip_vertical:n {-\l_tmpa_dim -\arrayrulewidth }}
  {}{\fail}

\expandafter\patchcmd
  \csname environment~ NiceArrayWithDelims~ end~ aux~ \endcsname
  {\skip_vertical:N -\l_tmpb_dim }
  {\skip_vertical:n {-\l_tmpb_dim +\arrayrulewidth }}
  {}{\fail}
\ExplSyntaxOff
\makeatother

相关内容