
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:
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}
Offensichtlich ist die Kürzung an der oberen Grenze der Box durch die Option restrict z to domain
nicht 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:1000
die großen Werte abzuschneiden. Der Nachteil besteht jedoch darin, dass die Abschneidefläche gezeichnet wird:
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 gnuplot
anstelle von implementiert wird surf
. Leider funktioniert dies nicht wie erwartet.
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)
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 gnuplottex
Paket 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
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
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, crop3D
der 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:
Vielen Dank an euch alle für euren Einsatz und eure Unterstützung.
Antwort4
Hier ist eine Implementierung der sagetex
Methode, 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:
Die Verringerung der Schrittweite, um ein präziseres Diagramm zu erhalten, stößt auf Probleme. Der Standardwert bufsize=200000
in texmf.cnf
ist zu klein. Das müsste man ändern. Im Moment weiß ich nicht, wie man das bufsize
in 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 = .10
in step = .1
und es wird ordnungsgemäß kompiliert. Aus irgendeinem Grund funktioniert der erste Build nicht richtig.