Abschneiden eines singulären 3D-Oberflächendiagramms mit großen Werten

Abschneiden eines singulären 3D-Oberflächendiagramms mit großen Werten

Ich habe mich gefragt, wie man eine einzelne Oberfläche wie diese zeichnen kann z=1/(x*y)^2(die Funktion, an der ich arbeite, ist viel komplizierter). Was ich erreichen möchte, ist unten dargestellt:

externe 3D-Diagramme

Wolfram Alpha (links) macht einen tollen Job und Maple (rechts) ist auch nicht schlecht. Um die LaTeX-Integration in meinem Dokument zu verbessern (Konsistenz von Schriftart und -größe), habe ich versucht, pgfplots direkt zu verwenden, mit folgendem Ergebnis:

\documentclass[]{article}
\usepackage{pgfplots}

\begin{document}
\begin{tikzpicture}
\begin{axis}[zmin=0,zmax=1000,restrict z to domain=0:1000]
    \addplot3[surf,samples=50,domain=-1:1,y domain=-1:1]{1/(x*y)^2};
\end{axis}
\end{tikzpicture}
\end{document}

pgfplots

Offensichtlich ist die Kürzung an der oberen Grenze der Box durch die Option restrict z to domainnicht sehr schön. Das Entfernen dieser Option führt zu keiner Kürzung, was auch nicht schön ist. Bis jetzt habe ich keinen Weg gefunden, dies richtig zu machen. Ich frage mich definitiv, wie manso eine schöne Handlungdes Moduls der Gammafunktion. Vielleicht gibt es eine geeignete Möglichkeit, ein 3D-Oberflächendiagramm aus externer Software in LaTeX zu importieren? Gibt es irgendeine Problemumgehung*?

*Ich habe darüber nachgedacht, natives TikZ oder Asymptote auszuprobieren, aber es gibt vielleicht einfachere Lösungen. Die Verwendung externer Software wie Matlab zur Durchführung komplexer grafischer Aufgaben ist bei der Arbeit mit pgfplots recht üblich, aber ich habe das nie für 3D-Diagramme getan und frage mich, wie so etwas funktionieren könnte. Außerdem habe ich darüber nachgedacht, Daten aus einer Tabelle zu importieren, aber ich werde wahrscheinlich auf andere Probleme stoßen. Ich habe auch versucht, zu filtern

\begin{axis}[zmin=0,zmax=1000,filter point/.code={%
        \pgfmathparse
        {\pgfkeysvalueof{/data point/z}>1000}%
        \ifpgfmathfloatcomparison
        \pgfkeyssetvalue{/data point/z}{nan}%
        \fi
    }]
    \addplot3[surf,unbounded coords=jump,samples=50,domain=-1:1,y domain=-1:1]{1/(x*y)^2};
\end{axis}

mit dem gleichen hässlichen Ergebnis.

Antwort1

Ein erster Ansatzbesteht darin, die Funktion zu parametrisieren oder sie mit Polarkoordinaten zu zeichnen. Dies kann bei komplexen Funktionen wie der, an der Sie arbeiten, eine große Herausforderung sein.

Ein zweiter Ansatzist die Verwendung der mit Sternchen markierten Option *, um restrict z to domain*=0:1000die großen Werte abzuschneiden. Der Nachteil besteht jedoch darin, dass die Abschneidefläche gezeichnet wird:

Bildbeschreibung hier eingeben

MWE:

\documentclass[]{article}
\usepackage{pgfplots}

\begin{document}
 \pgfplotsset{compat=1.17}
\begin{tikzpicture}
\begin{axis}[zmin=0,zmax=1000,restrict z to domain*=0:1000]
    \addplot3[surf,samples=85, samples y= 85,domain=-1:1,y domain=-1:1,opacity=0.5]{1/(x*y)^2};
\end{axis}
\end{tikzpicture}
\end{document}

Ein dritter Ansatzbasierend auf einemProblemumgehunggegeben durchChristian Feuersänger(Autor von Pgfplots) Die zweite Möglichkeit besteht darin, die Abschneidefläche mit einer anderen Oberflächenfarbe zu überlagern. Dies kann theoretisch erreicht werden, indem ein Konturdiagramm mit contour gnuplotanstelle von implementiert wird surf. Leider funktioniert dies nicht wie erwartet.

Bildbeschreibung hier eingeben

MWE (Dateiname.tex):

\documentclass[]{article}
\usepackage{pgfplots}
\usepgfplotslibrary{colormaps} 
\begin{document}
 \pgfplotsset{compat=1.8}
\begin{tikzpicture}
\begin{axis}[zmin=0,zmax=1000,colormap/autumn,]
   \addplot3[surf,samples=80, restrict z to domain*=0:1000,samples y= 80,domain=-1:1,y domain=-1:1, opacity=0.5]({x},{y},{1/(x*y)^2}); %{1/(x*y)^2};

% the contour plot:
 \addplot3[
contour gnuplot={levels={1000},labels=false,contour dir=z,},samples=80,domain=-1:1,y domain=-1:1,z filter/.code={\def\pgfmathresult{1000}},]
({x},{y},{1/(x*y)^2});


%filling the contour:
  \addplot3[
  /utils/exec={\pgfplotscolormapdefinemappedcolor{1000}},
  draw=none,
  fill=mapped color] 
  file {filename_contourtmp0.table};
\end{axis}
\end{tikzpicture}
\end{document}

Ein vierter Ansatzist mit gnuplot 5.4 und dem Befehl set pm3d clip z(dies wird von früheren gnuplot-Versionen nicht unterstützt)

Bildbeschreibung hier eingeben

MWE (Gnuplot 5.4):

set border 4095;
set bmargin 6;
set style fill transparent solid 0.50 border;
unset colorbox;
set view 56, 15, .75, 1.75;
set samples 40, 40;
set isosamples 40, 40;
set xyplane 0;
set grid x y z vertical;
set pm3d depthorder border linewidth 0.100;
set pm3d clip z;
set pm3d lighting primary 0.8 specular 0.3 spec2 0.3;
set xrange [-1:1];
set yrange [-1:1];
set zrange [0:1000];
set xtics 0.5 offset 0,-0.5;
set ytics 0.5 offset 0,-0.5;
set ztics 100;
f(x,y) = 1/(x*y)**2;
splot f(x,y) with pm3d fillcolor "red";

Leider kann TikZ keine 3D GNUPLOT Tabellendateien lesen (generieren mit splot), sieheTikZ PGF-Pakethandbuch 3.1.5, Seite 342, das ist,

\documentclass[]{article}
\usepackage{pgfplots}
\begin{document}
\pgfplotsset{compat=1.8}
\begin{tikzpicture}
    \begin{axis}
    \addplot3[raw gnuplot,surf] gnuplot[id=surf] { %
        set border 4095;
        set bmargin 6;
        set style fill transparent solid 0.50 border;
        unset colorbox;
        set view 56, 15, .75, 1.75;
        set samples 40, 40;
        set isosamples 40, 40;
        set xyplane 0;
        set grid x y z vertical;
        set pm3d depthorder border linewidth 0.100;
        set pm3d clip z;
        set pm3d lighting primary 0.8 specular 0.3 spec2 0.3;
        set xrange [-1:1];
        set yrange [-1:1];
        set zrange [0:1000];
        set xtics 0.5 offset 0,-0.5;
        set ytics 0.5 offset 0,-0.5;
        set ztics 100;
        f(x,y) = 1/(x*y)**2;
        splot f(x,y) with pm3d fillcolor "red";
    };
\end{axis}
\end{tikzpicture}
\end{document}

gibt:Tabular output of this 3D plot style not implemented

Eine Problemumgehung besteht darin, das gnuplottexPaket mit dem TikZ-Ausgabeterminal zu verwenden.

MWE (noch nicht getestet, da ich mit TeX Live arbeite)

\documentclass{article}
\usepackage{graphicx}
\usepackage{latexsym}
\usepackage{ifthen}
\usepackage{moreverb}
\usepackage{tikz}
\usepackage{gnuplot-lua-tikz}
\usepackage[miktex]{gnuplottex}
\begin{document}
    \begin{figure}%
            \centering%
            \begin{gnuplot}[terminal=tikz]
              set out "tex-gnuplottex-fig1.tex"
              set term lua tikz latex createstyle
              set border 4095;
              set bmargin 6;
              set style fill transparent solid 0.50 border;
              unset colorbox;
              set view 56, 15, .75, 1.75;
              set samples 40, 40;
              set isosamples 40, 40;
              set xyplane 0;
              set grid x y z vertical;
              set pm3d depthorder border linewidth 0.100;
              set pm3d clip z;
              set pm3d lighting primary 0.8 specular 0.3 spec2 0.3;
              set xrange [-1:1];
              set yrange [-1:1];
              set zrange [0:1000];
              set xtics 0.5 offset 0,-0.5;
              set ytics 0.5 offset 0,-0.5;
              set ztics 100;
              f(x,y) = 1/(x*y)**2;
              splot f(x,y) with pm3d fillcolor "red";
            \end{gnuplot}
        \caption{This is using the \texttt{tikz}-terminal}%
        \label{pic:tikz}%
    \end{figure}%
\end{document}

Ein fünfter Ansatzmit PSTricks und\psplotThreeD

Bildbeschreibung hier eingeben

MWE:

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-3dplot}
\begin{document}

\centering
\begin{pspicture}(-10,-4)(15,20)
    \psset{Beta=15}
    \psplotThreeD[plotstyle=line,linecolor=blue,drawStyle=yLines,
    yPlotpoints=100,xPlotpoints=100,linewidth=1pt](-5,5)(-5,5){%
    x y mul 2 neg exp
    dup 5 gt { pop 5 } if % truncation
    }
    \psplotThreeD[plotstyle=line,linecolor=cyan,drawStyle=xLines,
    yPlotpoints=100,xPlotpoints=100,linewidth=1pt](-5,5)(-5,5){%
    x y mul 2 neg exp
    dup 5 gt { pop 5 } if % truncation
    }
    \pstThreeDCoor[xMin=-1,xMax=5,yMin=-1,yMax=5,zMin=-1,zMax=6]
\end{pspicture}

\end{document}

Antwort2

Hier ist die AsymptoteCodezur Herstellung eines interaktiven 3DHandlungder Gammafunktion.

Antwort3

GefolgtJohn Bowmans Antworthabe ich mich mit Asymptote beschäftigt. Während ich lernte, wie man es benutzt, war ich ziemlich erstaunt über seine Möglichkeiten. Meine Antwort folgtdieser Beitrag, das einen Asymptote-Hack namens präsentiert, crop3Dder mein Problem löst. Obwohl es (rechnerisch) ziemlich „teuer“ ist, gefällt mir die Tatsache, dass diese Technik nicht viel zusätzliche Installation erfordert und dass sie fast blind angewendet werden kann (so könnte sie beispielsweise auch verwendet werden, um eine schöne Kürzung der Gamma-Funktion zu erhalten). Hier ist mein Code

\documentclass{article}
\usepackage{asymptote}

\begin{document}
    \begin{figure}[h!]
        \begin{asy}
            import crop3D;
            import graph3;
            unitsize(1cm);
            size3(5cm,5cm,3cm,IgnoreAspect);
            
            real f(pair z) {
                if ((z.x*z.y)^2 > 0.001)
                    return 1/(z.x*z.y)^2;
                else
                    return 1000;
            }
            
            currentprojection = orthographic(10,5,5000);
            currentlight = (1,-1,2);
            
            surface s = surface(f,(-1,-1),(1,1),nx=100,Spline);
            s = crop(s,(-1,-1,0),(1,1,500));
            
            draw(s,lightyellow,render(merge=true));
            
            xaxis3("$x$",Bounds,OutTicks(Step=1));
            yaxis3("$y$",Bounds,OutTicks(Step=1));
            zaxis3("$z$",Bounds,OutTicks(Step=500));
        \end{asy}
    \end{figure}
\end{document}

und die entsprechende Ausgabe:

Ausgabe

Vielen Dank an euch alle für euren Einsatz und eure Unterstützung.

Antwort4

Hier ist eine Implementierung der sagetexMethode, die ich oben für die komplexe Gammafunktion kommentiert habe

\documentclass[11pt,border={10pt 10pt 10pt 10pt}]{standalone}
\usepackage{pgfplots}
\usepackage{sagetex}
\pgfplotsset{compat=1.16}
\begin{document}
\begin{sagesilent}
var('x','y')
step = .10
x1 = -4.
x2 = 4.
y1 = -1.5
y2 = 1.5
MAX = 6
output = ""
output += r"\begin{tikzpicture}[scale=1.0]"
output += r"\begin{axis}[view={-15}{45},xmin=%s, xmax=%s, ymin=%s, ymax=%s]"%(x1,x2,y1,y2-step)
output += r"\addplot3[surf,mesh/rows=%d] coordinates {"%(((y2-step-y1)/step+1).round())
# rows is the number of y values
for y in srange(y1,y2,step):
    for x in srange(x1,x2,step):
        if (abs(CDF(x+I*y).gamma()))< MAX:
            output += r"(%f, %f, %f) "%(x,y,abs(CDF(x+I*y).gamma()))
        else:
            output += r"(%f, %f, %f) "%(x,y,MAX)
output += r"};"
output += r"\end{axis}"
output += r"\end{tikzpicture}"
\end{sagesilent}
\sagestr{output}
\end{document}

Die Ausgabe in Cocalc wird unten angezeigt: Bildbeschreibung hier eingeben

Die Verringerung der Schrittweite, um ein präziseres Diagramm zu erhalten, stößt auf Probleme. Der Standardwert bufsize=200000in texmf.cnfist zu klein. Das müsste man ändern. Im Moment weiß ich nicht, wie man das bufsizein Cocalc ändert.

Die Cocalc-Site ist kostenlos, aber die Leistung leidet bei den kostenlosen Konten etwas, wie die Meldung im Bild zeigt. Wenn Sie den Code kopieren/einfügen und ausführen, erhalten Sie anstelle des Bildes ??. Ändern Sie es step = .10in step = .1und es wird ordnungsgemäß kompiliert. Aus irgendeinem Grund funktioniert der erste Build nicht richtig.

verwandte Informationen