Truncar un gráfico de superficie 3D singular con valores grandes

Truncar un gráfico de superficie 3D singular con valores grandes

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:

parcelas 3d externas

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}

diagramas de pgf

Obviamente, el truncamiento en el límite superior del cuadro de la opción restrict z to domainno 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:1000para recortar los valores grandes. Sin embargo, el inconveniente es que la superficie de truncamiento se dibuja:

ingrese la descripción de la imagen aquí

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 gnuploten lugar de surf. Desafortunadamente, esto no funciona como se esperaba.

ingrese la descripción de la imagen aquí

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)

ingrese la descripción de la imagen aquí

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 gnuplottexpaquete 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

ingrese la descripción de la imagen aquí

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

Aquí está la asíntotacódigopara producir un 3D interactivotramade la función Gamma.

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 crop3Dque 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:

producción

Muchas gracias a todos por vuestro esfuerzo y apoyo.

Respuesta4

Aquí hay una implementación del sagetexmé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: ingrese la descripción de la imagen aquí

Disminuir el tamaño del paso para obtener un diagrama más preciso genera problemas. El valor predeterminado bufsize=200000es texmf.cnfdemasiado pequeño. Tendrías que modificar eso. En este momento, no sé cómo cambiar bufsizeen 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 = .10a step = .1y se compilará correctamente. Por alguna razón, la primera compilación no funciona correctamente.

información relacionada