Я хочу использовать TikZ/pgf для создания следующей 3D-графики, которая состоит из:
- график функции f(x, y) = xy/(x^2 + y^2) при (x, y) != (0,0) и f(0,0)=0;
- пересечение плоскости y = x с поверхностью, то есть линия с уравнением y = x, z = 1/2, но с пропущенной точкой (0, 0, 1/2);
- происхождение; и
- по крайней мере, положительная часть осей x, y и z.
Этот график был создан с помощью Mathematica и использует точку обзора (2,85216, 1,62152, 0,828166) в сферических координатах (r,θ, φ) (где углы указаны в радианах, а не в градусах).
Моя pgfplots
попытка использует приведенный ниже код и создает график, показанный после него.
Вопрос: Как мне изменить pgfplots
код так, чтобы он максимально напоминал графику Mathematica, чтобы он:
по сути использует ту же точку зрения (и, следовательно, ту же ориентацию осей);
не учитывает контурные правила на поверхности;
имеет излом на оси z на линии y = x, z = 1/2;
использует более убедительную точку в начале координат; и
позволяет избежать «неровностей» на поверхности вблизи оси z.
По пункту 5. Я пытался увеличить samples
значение, но это приводит к TeX capacity exceeded
ошибке!
Мой pgfplot
вывод:
Мой код:
\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
% Define a grayscale colormap
\pgfplotsset{
colormap={grayscale}{[1pt] rgb255(0pt)=(0,0,0); rgb255(1000pt)=(255,255,255)}
}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
view={75.833}{35.3489},
axis lines=center,
xlabel={$x$}, ylabel={$y$}, zlabel={$z$},
ticks=none,
domain=-1:1, y domain=-1:1,
samples=50, % need to avoid "jaggies"
z buffer=sort,
clip=false,
xmin=-1, xmax=1, ymin=-1, ymax=1, zmin=-1, zmax=1.5,
colormap name=grayscale,
xlabel style={anchor=north west}, ylabel style={anchor=north west},
zlabel style={anchor=south},
]
% Surface plot
\addplot3[surf, shader=faceted interp, opacity=0.7]
{x != 0 || y != 0 ? (x*y)/(x^2 + y^2) : 0};
% Point at the origin
\addplot3[mark=*, mark size=1,mark options={color=black}] coordinates {(0, 0, 0)};
% Curve of intersection of plane and surface
\addplot3[samples=20, samples y=0, thick, color=black]
({x}, {x}, {1/2});
\end{axis}
\end{tikzpicture}
\end{document}
решение1
Обновлять
Я модифицировал код в соответствии с многочисленными комментариями @murray. Существует два способа представления поверхности: либо с использованием полярных координат для области определения, либо с использованием нормальных координат. Первый способ идеально справляется с сингулярностью в начале координат, поскольку учитывает ее. Последний придерживается начального определения функции, но испытывает трудности с ее поведением около (0, 0).
В последнем случае основные изменения по сравнению с первоначальным ответом заключаются в следующем:
- поверхность разделена на две части (у<0иу>0соответственно)
- Границы добавлены для лучшего понимания поверхности.
- Оси рисуются отдельно (как сегменты TikZ).
Порядок расположения различных графических элементов имеет значение.
Замечание
Ниже представлено изображение, полученное с помощью matplotlib
вычислений на основе сетки 10000x10000. Поверхность никогда не может быть сглажена вокруг начала координат с последней точки зрения.
Новый код для чертежа с использованием полярных координат для домена
\documentclass[11pt, margin=10pt]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{math}
\pgfplotsset{compat=1.17}
\begin{document}
\pgfplotsset{
colormap={cmpgray}{rgb255=(221,221,221) rgb255=(54,54,54)}
}
\xdefinecolor{axisRGB}{RGB}{128, 30, 0} % {128, 128, 145}
\begin{tikzpicture}
\begin{axis}[
data cs=polar,
axis lines=none, % grid=major,
view={110}{22},
z buffer=sort,
clip=false]
% negative Ox axis
\draw[axisRGB, thin] (0, 0, 0) -- (-1.8, 0, 0);
\draw[axisRGB, thin, ->] (0, 0, .02) -- (0, 0, .8)
node[right, text=black, scale=.7] {$z$};
\addplot3[
surf,
shader=interp,
domain=0:360, domain y=.02:1.4,
samples=50, samples y=20,
opacity=0.95]
{.5*sin(2*x)};
% negative Oy axis
\draw[axisRGB, thin] (0, 0, 0) -- (0, -1.8, 0);
% negative Oz axis
\draw[axisRGB, thin] (0, 0, -.025) -- (0, 0, -.8);
% point at the origin
\fill[opacity=.7] (0, 0, 0) circle (1.2pt);
\draw[axisRGB, thin, ->] (0, .02, 0, 0) -- (0, 1.8, 0)
node[below, text=black, scale=.7] {$y$};
\draw[axisRGB, thin, ->] (.02, 0, 0) -- (1.8, 0, 0)
node[below, text=black, scale=.7] {$x$};
% Intersection curve of surface and plane z=1/2
\draw[thin] (-1, -1, 1/2) -- (1, 1, 1/2);
\end{axis}
\end{tikzpicture}
\end{document}
Новый код для второго розыгрыша
\documentclass[11pt, margin=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.17}
\begin{document}
\pgfplotsset{
colormap={cmpgray}{rgb255=(221,221,221) rgb255=(54,54,54)}
}
\xdefinecolor{axisRGB}{RGB}{128, 128, 145}
\begin{tikzpicture}
\begin{axis}[
view={115}{19},
axis lines=none, % center,
xlabel={$x$}, ylabel={$y$}, zlabel={$z$},
ticks=none,
z buffer=sort,
clip=false,
xmin=-1.3, xmax=1.3,
ymin=-1.3, ymax=1.3,
zmin=-1, zmax=1.3,
xlabel style={anchor=north west, scale=.8},
ylabel style={anchor=north west, scale=.8},
zlabel style={anchor=south, scale=.8},
]
% Surface y<0
\addplot3[
surf,
domain=-1:1,
y domain=-1:-.005,
samples=55,
colormap name=cmpgray,
shader=interp, % flat, faceted interp,
opacity=0.75]
{x*y/(x^2 + y^2)};
% Surface y<0 's border
\addplot3[%
draw=black, ultra thin,
domain=-1:1,
samples y=0]
(x, -1, {-x/(x*x +1)});
\addplot3[%
draw=black, ultra thin,
domain=-1:1,
samples y=0]
(-1, x, {-x/(x*x +1)});
% negative Ox and Oy axes
\draw[axisRGB, thin] (0, 0, 0) -- (0, -1.4, 0);
\draw[axisRGB, thin] (0, 0, 0) -- (-1.4, 0, 0);
% Point at the origin
\fill (0, 0, 0) circle (1.2pt);
% positive Oz axis
\draw[axisRGB, thin, ->] (0, 0, .02) -- (0, 0, 1.3)
node[right, text=black, scale=.7] {$z$};
% Surface y>0
\addplot3[
surf,
domain=-1:1,
y domain=.005:1,
samples=55,
colormap name=cmpgray,
shader=interp, % flat, faceted interp,
opacity=0.75]
{x*y/(x*x + y*y)};
% positive Oy axis
\draw[axisRGB, thin, ->] (0, .02, 0, 0) -- (0, 1.4, 0)
node[below, text=black, scale=.7] {$y$};
% negative Oz axis
\draw[axisRGB, thin] (0, 0, -.025) -- (0, 0, -1.3);
% Intersection curve of surface and plane z=1/2
\draw[thin] (-1, -1, 1/2) -- (1, 1, 1/2);
% Surface y>0 's border
\addplot3[%
draw=black, very thin,
domain=-1:1,
samples y=0]
(x, 1, {x/(x*x +1)});
\addplot3[%
draw=black, very thin,
domain=-1:1,
samples y=0]
(1, x, {x/(x*x +1)});
% positive Ox axis
\draw[axisRGB, thin, ->] (.02, 0, 0) -- (1.5, 0, 0)
node[below, text=black, scale=.7] {$x$};
\end{axis}
\end{tikzpicture}
\end{document}
Старый ответ
Что-то вроде этого; я только изменил точку зрения, длину осей координат и шейдер.
Код
\documentclass[11pt, margin=10pt]{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{colorbrewer}
\pgfplotsset{compat=1.17}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
view={115}{15},
axis lines=center,
xlabel={$x$}, ylabel={$y$}, zlabel={$z$},
ticks=none,
domain=-1:1, y domain=-1:1,
samples=50, % need to avoid "jaggies"
z buffer=sort,
clip=false,
xmin=-1.3, xmax=1.3,
ymin=-1.3, ymax=1.3,
zmin=-1, zmax=1.3,
xlabel style={anchor=north west, scale=.8},
ylabel style={anchor=north west, scale=.8},
zlabel style={anchor=south, scale=.8},
]
% Surface plot
\addplot3[
surf,
colormap/Blues, % cool,
% shader=faceted interp,
opacity=0.3]
{x != 0 || y != 0 ? (x*y)/(x^2 + y^2) : 0};
% Point at the origin
\addplot3[mark=*, mark size=1,mark options={color=black}]
coordinates {(0, 0, 0)};
% Curve of intersection of plane and surface
\addplot3[samples=20, samples y=0, thick, color=black]
({x}, {x}, {1/2});
\end{axis}
\end{tikzpicture}
\end{document}