
Me preguntaba cómo trazar una superficie singular como z=1/(x*y)^2
(la función en la que estoy trabajando es mucho más complicada). Lo que me gustaría lograr se muestra a continuación:
Wolfram Alpha (izquierda) hace un gran trabajo y Maple (derecha) tampoco está tan mal. Para mejorar la integración de LaTeX en mi documento (consistencia de fuente y tamaño), intenté usar pgfplots directamente, con el siguiente resultado:
\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}
Obviamente, el truncamiento en el límite superior del cuadro de la opción restrict z to domain
no es muy agradable. Al eliminar esta opción no se produce ningún truncamiento, lo cual tampoco es bueno. Hasta ahora, no encontré una manera de hacerlo correctamente. Definitivamente me pregunto cómo producirque trama tan hermosadel módulo de la función Gamma. ¿Quizás exista alguna forma adecuada de importar un gráfico de superficie 3D desde un software externo a LaTeX? ¿Alguna solución*?
*Estaba pensando en probar TikZ o Asymptote nativo, pero puede haber soluciones más simples. Usar software externo como Matlab para realizar tareas gráficas complejas es bastante común cuando se trabaja con pgfplots, pero nunca lo hice para gráficos 3D y me pregunto cómo podría funcionar algo así. Además, he pensado en importar datos de una tabla, pero probablemente tendré otros problemas. También intenté filtrar
\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}
con el mismo feo resultado.
Respuesta1
Un primer acercamientoes parametrizar la función o dibujarla con coordenadas polares. Esto puede ser un desafío arduo en el caso de funciones complejas como la que está trabajando.
Un segundo enfoquees utilizar la opción destacada *
de restrict z to domain*=0:1000
para recortar los valores grandes. Sin embargo, el inconveniente es que la superficie de truncamiento se dibuja:
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}
Un tercer enfoquebasado ensolución alternadada porChristian Feuersänger(autor de Pgfplots) del segundo es superponer la superficie de truncamiento con otro color de superficie. En teoría, esto se puede hacer implementando el trazado de contorno con contour gnuplot
en lugar de surf
. Desafortunadamente, esto no funciona como se esperaba.
MWE (Nombre del archivo.Texas):
\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}
Un cuarto enfoquees con gnuplot 5.4 y el comando set pm3d clip z
(esto no es compatible con versiones anteriores de gnuplot)
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";
Desafortunadamente, TikZ no puede leer archivos de tabla 3D GNUPLOT (generar con splot
), consulteManual de paquetes TikZ PGF 3.1.5, página 342, eso es,
\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}
da:Tabular output of this 3D plot style not implemented
Una solución alternativa es utilizar el gnuplottex
paquete con el terminal de salida TikZ.
MWE (aún no probado, ya que trabajo con TeX Live)
\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}
Un quinto enfoquecon PSTricks y\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}
Respuesta2
Respuesta3
SiguienteLa respuesta de John Bowman., Profundicé en la asíntota. Mientras aprendía a utilizarlo, quedé bastante sorprendido por sus posibilidades. Mi respuesta sigueesta publicación, que presenta un truco de asíntota llamado crop3D
que resuelve mi problema. Aunque es bastante "cara" (computacionalmente), me gusta el hecho de que esta técnica no requiere mucha instalación adicional y que puede aplicarse de forma casi ciega (por lo tanto, también podría usarse para obtener una buen truncamiento de la función Gamma, por ejemplo). Aquí está mi código.
\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}
y la salida correspondiente:
Muchas gracias a todos por vuestro esfuerzo y apoyo.
Respuesta4
Aquí hay una implementación del sagetex
método que comenté anteriormente para la compleja función Gamma.
\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}
El resultado en Cocalc se muestra a continuación:
Disminuir el tamaño del paso para obtener un diagrama más preciso genera problemas. El valor predeterminado bufsize=200000
es texmf.cnf
demasiado pequeño. Tendrías que modificar eso. En este momento, no sé cómo cambiar bufsize
en Cocalc.
El sitio Cocalc es gratuito, pero el rendimiento está sufriendo un poco en las cuentas gratuitas, como muestra el mensaje en la imagen. Si copia/pega el código y lo ejecuta, obtendrá ?? en el lugar de la imagen. Cambie step = .10
a step = .1
y se compilará correctamente. Por alguna razón, la primera compilación no funciona correctamente.