使用 Tikz 实现小数分隔符和轴标签居中

使用 Tikz 实现小数分隔符和轴标签居中

以下代码figure使用 Tikz 创建而不使用pfgplots(我想在这里避免):

% compilation: pdflatex --jobname=Runge-f1 Runge.tex
\documentclass[12pt]{book}
\usepackage[utf8]{inputenc}
\usepackage{filecontents}
\usepackage{tikz}
\pgfrealjobname{Runge}

\begin{filecontents}{B6.dat}
-1  0
0   5
1   0
\end{filecontents}
\definecolor{rouge}{RGB}{233,55,77}

\def\xmin{-1.1}\def\xmax{1.1}\def\ymin{-.6}\def\ymax{5.6}

\begin{document}
\beginpgfgraphicnamed{Runge-f1}%
\footnotesize
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{tikzpicture}[>=latex,scale=1.4,x=4cm,y=1cm]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% background
\fill[rouge!10] (\xmin,\ymin) rectangle (\xmax,\ymax);
%%%% grid and labels
\begin{scope}
\clip (\xmin,\ymin) rectangle (\xmax,\ymax);
\foreach \x in {-1,-0.75,...,1} \draw[rouge!35] (\x,\ymin) -- (\x,\ymax);
\foreach \x in {-1,-0.75,...,1} \node[fill=rouge!10,inner sep=2pt,anchor=south,font=\tiny\color{rouge}] at (\x,-.5){$\mathsf\x$}; %%%%%% loop 1
\end{scope}
%%%% curve
\draw plot file{B6.dat};
%%%% external frame
\draw[line width=.6pt,rouge!50] (\xmin,\ymin) rectangle (\xmax,\ymax);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{tikzpicture}
\endpgfgraphicnamed%
\end{document}
  • 在循环 1 中如何用逗号作为小数点分隔符?
  • 在循环 1 中,是否可以$\x$通过忽略存在的负号来使标签相对于网格居中-

在此处输入图片描述

答案1

您可以使用siunitx。因此我定义了一个命令:

\usepackage{siunitx}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand{ \parsenumber } { m }
{
 \num[ output-decimal-marker = { , }]{\fp_eval:n { abs ( #1 ) }}
}
\ExplSyntaxOff

你的循环看起来像:

\foreach \x in {-1,-0.75,...,1} \node[fill=rouge!10,inner sep=2pt,anchor=south,font=\tiny\color{rouge}] at (\x,-.5){ \parsenumber{\x} }; %%%%%% loop 1

看起来减号应该不占用任何空间地显示。然后,您可以使用:

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{ \parsenumber } { m }
{
 \num[ output-decimal-marker = { , },bracket-negative-numbers,close-bracket={},open-bracket={\llap{$-$}}]{#1}
}
\ExplSyntaxOff

结果:

在此处输入图片描述

答案2

您还可以使用 PGF 解析您的号码。

\documentclass[tikz]{standalone}
\usepackage{filecontents}


\begin{filecontents}{B6.dat}
-1  0
0   5
1   0
\end{filecontents}
\definecolor{rouge}{RGB}{233,55,77}

\def\xmin{-1.1}\def\xmax{1.1}\def\ymin{-.6}\def\ymax{5.6}

\begin{document}

\footnotesize
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{tikzpicture}[>=latex,scale=1.4,x=4cm,y=1cm]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% background
\fill[rouge!10] (\xmin,\ymin) rectangle (\xmax,\ymax);
%%%% grid and labels
\begin{scope}
\clip (\xmin,\ymin) rectangle (\xmax,\ymax);
\foreach \x in {-1,-0.75,...,1}{ \draw[rouge!35] (\x,\ymin) -- (\x,\ymax);}
\foreach \x in {-1,-0.75,...,1}{
\pgfmathsetmacro{\myshift}{(\x < 0? -0.4 : 0)}
\node[fill=rouge!10,
      inner sep=2pt,
      anchor=base,
      font=\tiny\color{rouge},
      xshift=\myshift em
      ]  at (\x,-.5) {$\mathsf{\pgfmathprintnumber[use comma]{\x}}$}; %%%%%% loop 1
}
\end{scope}
%%%% curve
\draw plot file{B6.dat};
%%%% external frame
\draw[line width=.6pt,rouge!50] (\xmin,\ymin) rectangle (\xmax,\ymax);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{tikzpicture}

\end{document}

我只是猜测了减号的宽度,但你也可以测量它。

在此处输入图片描述

答案3

与打击乐的方法略有不同:

我们使用 PGF 数学的\pgfmathprintnumber

  • 选择权use comma
  • zero-width sign使用mathtools'\mathllap\robustify的选项etoolbox。您也可以改用 \llap(参见代码中的注释)。

需要调整两个特殊宏pgfmathprintnumber以适应此情况。(我在这里忽略了show pos强制使用加号的选项。)

一种相当非正统但安全的方法是使用\x\ifdim\x pt<0pt\hphantom{-}\fi,即检查是否\x小于0(仅当\x已经是评估的可扩展值时才有效)并-在数字后添加一个隐藏,从而将数字的无符号部分居中。

这两种解决方案的缺点是节点的边框与实际文本不相关。(但如果您既不使用draw西边也不使用右边的边框,这应该不是问题。)

我还将第二个循环中的节点包含在第一个循环中,这样就不必使用fill节点,这使得绘图独立于背景(可能只是一条线或一个阴影)。这通常也可以通过装饰markingsmark connection node选项来实现,尽管今天我失败了。

我还在text depth=+0pt节点选项中将节点文本框的深度设置为零,隐藏了深度,,-会导致节点的垂直对齐略有不同,因为我们有三种不同类型的输入:

  • (零)正整数(既不是,也不是-
  • 负整数(仅限-
  • 正浮点数和负浮点数(的深度,大于的深度-)。

另一个解决方案是使用base锚点来放置节点,而不是(默认)center节点。

代码

\documentclass[12pt,tikz,convert=false]{standalone}
\begin{filecontents}{B6.dat}
-1  0
0   5
1   0
\end{filecontents}
\usepackage{etoolbox,mathtools}
\robustify\mathllap
\makeatletter
\newif\ifpgfmathprintnumber@zerowidth@sign
\def\pgfmathprintnumber@zerowidth@#1{\mathllap{#1}}% or \llap{$#1$} without mathtools/etoolbox
\pgfqkeys{/pgf/number format}{zero-width sign/.is if=pgfmathprintnumber@zerowidth@sign,zero-width sign/.default=true}
\def\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@printsign#1{%
    \def\pgfmathfloat@loc@TMPb{#1}%
    \edef\pgf@tempa{\ifpgfmathprintnumber@zerowidth@sign\pgfmathprintnumber@zerowidth@{#1}\else#1\fi}%
    \ifx\pgfmathfloat@loc@TMPb\pgfmathfloatparsenumber@tok@MINUS
        \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgfmathresult\expandafter\expandafter\expandafter{\expandafter\pgfmathresult\pgf@tempa}%
        \let\pgfmathfloat@loc@TMPb=\pgfutil@empty
    \else
        \ifx\pgfmathfloat@loc@TMPb\pgfmathfloatparsenumber@tok@PLUS
            \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgfmathresult\expandafter\expandafter\expandafter{\expandafter\pgfmathresult\pgf@tempa}%
            \let\pgfmathfloat@loc@TMPb=\pgfutil@empty
        \else
            \ifpgfmathprintnumber@showpositive
                \expandafter\def\expandafter\pgfmathresult\expandafter{\pgfmathresult +}%
            \fi
        \fi
    \fi
    \ifnum\c@pgf@counta>0
        \def\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@NEXT{%
            \expandafter\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@printtrailingdigits\pgfmathfloat@loc@TMPb
        }%
    \else
        \def\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@NEXT{%
            \expandafter\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@counteverythird\pgfmathfloat@loc@TMPb
        }%
    \fi
    \pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@NEXT
}
\def\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@printall#1{%
    \def\pgfmathfloat@loc@TMPb{#1}%
    \let\pgfmathfloat@loc@TMPc=\pgfutil@empty
    \ifx\pgfmathfloat@loc@TMPb\pgfmathfloatparsenumber@tok@MINUS
        \ifpgfmathprintnumber@zerowidth@sign
            \let\pgfmathfloat@loc@TMPc\pgfmathprintnumber@zerowidth@
        \fi
    \else
        \ifx\pgfmathfloat@loc@TMPb\pgfmathfloatparsenumber@tok@PLUS
            \ifpgfmathprintnumber@zerowidth@sign
                \let\pgfmathfloat@loc@TMPc\pgfmathprintnumber@zerowidth@
            \fi
        \else
            \ifpgfmathprintnumber@showpositive
                \def\pgfmathfloat@loc@TMPc{+}%
            \fi
        \fi
    \fi
    \expandafter\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@printall@\pgfmathfloat@loc@TMPc#1%
}
\makeatother

\definecolor{rouge}{RGB}{233,55,77}
\def\xmin{-1.1}\def\xmax{1.1}\def\ymin{-.6}\def\ymax{5.6}
\begin{document}
\footnotesize
\begin{tikzpicture}[>=latex,scale=1.4,x=4cm,y=1cm]
%%%% background
\fill[rouge!10] (\xmin,\ymin) rectangle (\xmax,\ymax);
%%%% grid and labels
\begin{scope}
\clip (\xmin,\ymin) rectangle (\xmax,\ymax);
\foreach \x in {-1,-0.75,...,1}
  \path[rouge!35] 
    node[inner sep=2pt,anchor=south,font=\tiny\everymath{\color{rouge}\mathsf},text depth=+0pt] at (\x,-.5) {\pgfmathprintnumber[zero-width sign,use comma]{\x}}
      edge (\x,\ymin)
      edge (\x,\ymax);
\end{scope}
%%%% curve
\draw plot file{B6.dat};
%%%% external frame
\draw[line width=.6pt,rouge!50] (\xmin,\ymin) rectangle (\xmax,\ymax);
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

答案4

要解决您问题的第二部分:我将把第二个循环拆分成两个循环。在第一个循环中覆盖负值,您可以使用 yshift 3pt(这是负数占用的空间量)。

\foreach \x in {-1,-0.75,...,-0.25} \node[fill=rouge!10,inner  
   sep=2pt,anchor=south,font=\tiny\color{rouge}, xshift = -3pt] at (\x,-.5){$\mathsf\x$}; 
\foreach \x in {0,0.25,...,1} \node[fill=rouge!10,inner 
   sep=2pt,anchor=south,font=\tiny\color{rouge}] at (\x,-.5){$\mathsf\x$}; 

相关内容