Рамы в стиле Тафте для трехмерных участков

Рамы в стиле Тафте для трехмерных участков

Этот вопрос является продолжениемэтот вопрос, что позволило мне решить двумерный случай.

Например, этот сюжет

синус

создается с помощью следующего кода:

\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}

Сходным образом

pdf

создано:

\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}

Теперь я хотел бы добиться того же стиля оси рамки диапазона в трехмерном графике. Моя лучшая попытка:

\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}

который дает

синусXtimessineY

Опция ticklabel shift={10pt}, делает именно то, что нужно для меток делений. На стр. 286 руководства pgfplots указано:

Смещает метки делений в направлении внешней нормали к оси на величину ...

Сравните две версии графика sin(x)sin(y) выше: метки делений на нижнем графике смещены от оси в нужное место.

К сожалению, нет tickmark shiftвозможности сместить отметки вдоль внешнего единичного вектора нормали таким же образом. Также нет axis shiftвозможности сместить ось.

В двумерном решении трюк состоял в том, чтобы использовать xshiftи yshiftпреобразование в x axis line styleдля простого смещения оси, а в xtick styleдля смещения делений.

Есть ли способ получить доступ к вектору нормали внешнего блока из tickmark shiftопции и использовать преобразование для перемещения осей и делений таким же образом, как и метки делений?

решение1

РЕДАКТИРОВАТЬ

Последние версии pgfplotsпоставляются с axis line shift, что позволяет нам упростить стиль следующим образом:

\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}

введите описание изображения здесь

Конец редактирования


Такого предопределенного стиля не существует.

Но вот одно определение в 5 строках:

введите описание изображения здесь

\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}

Команда \pgfplotspointouternormalvectorofticklabelaxis{x}является сокращением для \pgfplotspointouternormalvectorofaxis{\pgfplotsticklabelaxisspec{x}}. Боюсь, что документация по ней \pgfplotspointouternormalvectorofticklabelaxisотсутствует в справочном руководстве.

Обратите внимание, что этот сдвиг несовместим с линиями сетки (по конструкции!). Чтобы увидеть это, попробуйте добавить grid=major, и вы увидите, что описания немного смещены. Возможно, вам придется решить, хотите ли вы этого (или как это исправить).

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