So ändern Sie das 3D-Oberflächendiagramm von pgfplots, damit es besser aussieht

So ändern Sie das 3D-Oberflächendiagramm von pgfplots, damit es besser aussieht

Ich möchte mit TikZ/pgf folgende 3D-Grafik erstellen, die aus Folgendem besteht:

  • eine Darstellung der Funktion f(x, y) = xy/(x^2 + y^2), wobei (x, y) != (0,0) und f(0,0)=0;
  • der Schnittpunkt der Ebene y = x mit der Oberfläche, d. h. die Linie mit der Gleichung y = x, z = 1/2, wobei jedoch der Punkt (0, 0, 1/2) weggelassen wurde;
  • der Ursprung; und
  • zumindest der positive Teil der x-, y- und z-Achse.

Mathematica-Plot

Diese Grafik wurde mit Mathematica erstellt und verwendet einen Blickwinkel (2,85216, 1,62152, 0,828166) in (r, θ, φ) Kugelkoordinaten (wobei die Winkel in Radiant und nicht in Grad angegeben sind).

Mein pgfplotsVersuch verwendet den untenstehenden Code und erzeugt die danach angezeigte Grafik.

Frage: Wie kann ich den pgfplotsCode so ändern, dass er der Mathematica-Grafik sehr ähnlich ist, sodass er:

  1. verwendet im Wesentlichen den gleichen Blickwinkel (und damit die gleiche Achsenausrichtung);

  2. lässt Konturlinien auf der Oberfläche weg;

  3. hat den Bruch an der z-Achse auf der Linie y = x, z = 1/2;

  4. verwendet einen überzeugenderen Punkt am Ursprung; und

  5. vermeidet die „Zacken“ in der Oberfläche in der Nähe der Z-Achse.

Zu 5.: Ich habe versucht, den samplesWert zu erhöhen, dabei tritt jedoch ein TeX capacity exceededFehler auf!

Meine pgfplotAusgabe:

pgfplot

Mein Code:

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

Antwort1

Aktualisieren

Bildbeschreibung hier eingeben

aktualisieren

Ich habe den Code gemäß den zahlreichen Kommentaren von @murray geändert. Es gibt zwei Möglichkeiten, die Oberfläche darzustellen: entweder die Verwendung von Polarkoordinaten als Definitionsbereich oder die Verwendung von Normalkoordinaten. Ersteres geht ideal mit der Singularität am Ursprung um, da es diese respektiert. Letzteres hält sich an die ursprüngliche Definition der Funktion, hat aber Probleme mit ihrem Verhalten um (0, 0).

Im letzteren Fall sind die wichtigsten Änderungen gegenüber der ursprünglichen Antwort die folgenden:

  • Die Oberfläche ist zweigeteilt (y<0Undy>0jeweils)
  • Ränder werden zum besseren Verständnis der Oberfläche hinzugefügt
  • Achsen werden separat gezeichnet (als TikZ-Segmente).

Dabei kommt es auf die Reihenfolge der einzelnen grafischen Elemente an.

Anmerkung Unten sehen Sie ein Bild, das matplotlibmit Berechnungen auf der Grundlage eines 10000x10000-Rasters erstellt wurde. Aus letzterer Sicht kann die Oberfläche um den Ursprung herum nie geglättet werden.

Bildbeschreibung hier eingeben

Neuer Code für die Zeichnung mit Polarkoordinaten für die Domäne

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

Neuer Code für die zweite Ziehung

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

Alte Antwort

Bildbeschreibung hier eingeben

Ungefähr so; ich habe lediglich den Blickwinkel, die Länge der Koordinatenachsen und den Shader geändert.

Der Code

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

verwandte Informationen