Molduras em estilo Tufte para gráficos tridimensionais

Molduras em estilo Tufte para gráficos tridimensionais

Esta pergunta é uma continuaçãoessa questão, isso me permitiu resolver o caso bidimensional.

Por exemplo este enredo

seno

é criado pelo seguinte código:

\documentclass{minimal}
\usepackage{tikz}
\usepackage{pgfplots}
\def\axisdefaultwidth{360pt}
\pgfkeys{/pgfplots/x axis shift down/.style={
  x axis line style={yshift=-#1},
  xtick style={yshift=-#1},
  xticklabel shift={#1}}}
\pgfkeys{/pgfplots/y axis shift left/.style={
  y axis line style={xshift=-#1},
  ytick style={xshift=-#1},
  yticklabel shift={#1}}}

\pgfplotsset{
  every axis/.append style={thick},tick style={thick,black},
  range frame/.style={
    tick align=outside,
    scaled ticks=false,
    axis lines*=left,
    enlargelimits=false,
    x axis shift down=10pt,
    y axis shift left=10pt,
    line cap=round,
    clip=false,
    after end axis/.code={
       \draw (xticklabel* cs:0,10pt) -- ++(0,-\pgfkeysvalueof{/pgfplots/major tick length});
       \draw (xticklabel* cs:1,10pt) -- ++(0,-\pgfkeysvalueof{/pgfplots/major tick length});
       \draw (yticklabel* cs:0,10pt) -- ++(-\pgfkeysvalueof{/pgfplots/major tick length},0);
       \draw (yticklabel* cs:1,10pt) -- ++(-\pgfkeysvalueof{/pgfplots/major tick length},0);
    }
}

\begin{document}
\begin{tikzpicture}
  \begin{axis}[range frame,xtick={0,90,180,270,360}]
    \addplot[domain=0:360,samples=201] {sin(x)};
  \end{axis}
\end{tikzpicture}
\end{document}

De forma similar

pdf

é criado por:

\documentclass{minimal}
\usepackage{tikz}
\usepackage{pgfplots}
\usepgfplotslibrary{fillbetween}
\def\axisdefaultwidth{360pt}
\pgfkeys{/pgfplots/x axis shift down/.style={
  x axis line style={yshift=-#1},
  xtick style={yshift=-#1},
  xticklabel shift={#1}}}
\pgfkeys{/pgfplots/y axis shift left/.style={
  y axis line style={xshift=-#1},
  ytick style={xshift=-#1},
  yticklabel shift={#1}}}

\pgfplotsset{
  every axis/.append style={thick},tick style={thick,black},
  range frame/.style={
    tick align=outside,
    scaled ticks=false,
    axis lines*=left,
    enlargelimits=false,
    x axis shift down=10pt,
    y axis shift left=10pt,
    line cap=round,
    clip=false,
    after end axis/.code={
       \draw (xticklabel* cs:0,10pt) -- ++(0,-\pgfkeysvalueof{/pgfplots/major tick length});
       \draw (xticklabel* cs:1,10pt) -- ++(0,-\pgfkeysvalueof{/pgfplots/major tick length});
       \draw (yticklabel* cs:0,10pt) -- ++(-\pgfkeysvalueof{/pgfplots/major tick length},0);
       \draw (yticklabel* cs:1,10pt) -- ++(-\pgfkeysvalueof{/pgfplots/major tick length},0);
    }
  }
}

\begin{document}
\begin{tikzpicture}
  \begin{axis}[range frame,ytick={0},extra y ticks={0.398942},extra y tick labels={$\frac{1}{\sqrt{2π}}$},xtick=\empty,extra x ticks={-3,-2,-1,1,2,3},extra x tick labels={$-3σ$,$-2σ$,$-σ$,$σ$,$2σ$,$3σ$}]
    \addplot[domain=-5:5,samples=201,name path=A] {exp(-x^2/2)/sqrt(2*pi)};
    \path[name path=B] (axis cs:\pgfkeysvalueof{/pgfplots/xmin},0) -- (axis cs:\pgfkeysvalueof{/pgfplots/xmax},0);
    \addplot[black!30] fill between[of=A and B,soft clip={(axis cs:-3,0) rectangle (axis cs:3,1)}];
    \addplot[black!20] fill between[of=A and B,soft clip={(axis cs:-2,0) rectangle (axis cs:2,1)}];
    \addplot[black!10] fill between[of=A and B,soft clip={(axis cs:-1,0) rectangle (axis cs:1,1)}];
  \end{axis}
\end{tikzpicture}
\end{document}

Agora eu gostaria de obter o mesmo estilo de eixo do quadro em um gráfico tridimensional. Minha melhor tentativa é:

\documentclass{minimal}
\usepackage{tikz}
\usepackage{pgfplots}
\def\axisdefaultwidth{360pt}
\pgfplotsset{
  every axis/.append style={thick},tick style={thick,black},
  range3frame/.style={
    tick align=outside,
    scaled ticks=false,
    enlargelimits=false,
    ticklabel shift={10pt},
    axis lines*=left,
    line cap=round,
    clip=false
  }
}

\begin{document}
\begin{tikzpicture}
  \begin{axis}[view={55}{45}]
    \addplot3[mesh,samples=41,domain=0:360] {sin(x)*sin(y)};
  \end{axis}
\end{tikzpicture}
\begin{tikzpicture}
  \begin{axis}[range3frame,view={55}{45}]
    \addplot3[mesh,samples=41,domain=0:360] {sin(x)*sin(y)};
  \end{axis}
\end{tikzpicture}
\end{document}

que rende

senoXtimessineY

A opção ticklabel shift={10pt}faz exatamente a coisa certa para os rótulos das marcas de escala. pág. 286 do manual pgfplots afirma:

Desloca os rótulos de escala na direção da unidade normal externa do eixo em uma quantidade de ...

Compare as duas versões do gráfico sin(x)sin(y) acima, os rótulos das marcas de escala no gráfico inferior se afastaram do eixo para a direita.

Infelizmente não há tickmark shiftopção de deslocar as marcas de escala ao longo do vetor normal da unidade externa da mesma maneira. E também nenhuma axis shiftopção para compensar o eixo.

Na solução bidimensional o truque era usar xshiftuma yshifttransformação para x axis line stylesimplesmente deslocar o eixo e para xtick styledeslocar as marcas de escala.

Existe uma maneira de acessar o vetor normal da unidade externa a partir da tickmark shiftopção e usar uma transformação para mover o eixo e as marcas da mesma maneira que os rótulos das marcas?

Responder1

EDITAR

Versões recentes de pgfplotscome with axis line shift, o que nos permite simplificar o estilo da seguinte forma:

\documentclass{standalone}
\usepackage{pgfplots}
\def\axisdefaultwidth{360pt}

\pgfplotsset{
  every axis/.append style={thick},tick style={thick,black},
  %
  range3frame/.style={
    tick align=outside,
    scaled ticks=false,
    enlargelimits=false,
    axis lines*=left,
    line cap=round,
    clip=false,
    axis line shift=10pt,
  }
}

\begin{document}
\begin{tikzpicture}
  \begin{axis}[range3frame,view={55}{45}]
    \addplot3[mesh,samples=41,domain=0:360] {sin(x)*sin(y)};
  \end{axis}
\end{tikzpicture}
\end{document}

insira a descrição da imagem aqui

Fim da edição


Não existe esse estilo predefinido.

Mas aqui está um definido em 5 linhas:

insira a descrição da imagem aqui

\documentclass{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\def\axisdefaultwidth{360pt}

\pgfplotsset{
  every axis/.append style={thick},tick style={thick,black},
  %
  % #1 = x, y, or z
  % #2 = the shift value
  /tikz/normal shift/.code 2 args={%
    \pgftransformshift{%
        \pgfpointscale{#2}{\pgfplotspointouternormalvectorofticklabelaxis{#1}}%
    }%
  },%
  %
  range3frame/.style={
    tick align=outside,
    scaled ticks=false,
    enlargelimits=false,
    ticklabel shift={10pt},
    axis lines*=left,
    line cap=round,
    clip=false,
    xtick style={normal shift={x}{10pt}},
    ytick style={normal shift={y}{10pt}},
    ztick style={normal shift={z}{10pt}},
    x axis line style={normal shift={x}{10pt}},
    y axis line style={normal shift={y}{10pt}},
    z axis line style={normal shift={z}{10pt}},
  }
}

\begin{document}
\begin{tikzpicture}
  \begin{axis}[range3frame,view={55}{45}]
    \addplot3[mesh,samples=41,domain=0:360] {sin(x)*sin(y)};
  \end{axis}
\end{tikzpicture}
\end{document}

O comando \pgfplotspointouternormalvectorofticklabelaxis{x}é um atalho para \pgfplotspointouternormalvectorofaxis{\pgfplotsticklabelaxisspec{x}}. Receio que a documentação \pgfplotspointouternormalvectorofticklabelaxisesteja faltando no manual de referência.

Observe que esta mudança é incompatível com as linhas da grade (por construção!). Para ver isso, tente adicionar grid=majore você verá que as descrições estão um pouco erradas. Talvez você precise decidir se é isso que deseja (ou como repará-lo).

informação relacionada