Усечение сингулярного трехмерного графика поверхности с большими значениями

Усечение сингулярного трехмерного графика поверхности с большими значениями

Мне было интересно, как построить сингулярную поверхность, например z=1/(x*y)^2(функция, над которой я работаю, гораздо сложнее). То, чего я хотел бы добиться, показано ниже:

внешние 3D-графики

Wolfram Alpha (слева) отлично справляется, да и Maple (справа) тоже неплох. Чтобы улучшить интеграцию LaTeX в мой документ (согласованность шрифта и размера), я попробовал напрямую использовать pgfplots, и вот что получилось:

\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

Очевидно, что усечение на верхней границе поля из опции restrict z to domainне очень хорошо. Удаление этой опции не приводит к усечению вообще, что тоже нехорошо. До сих пор я не нашел способа сделать это правильно. Мне определенно интересно, как создатьтакой красивый сюжетмодуля гамма-функции. Может быть, есть какой-то правильный способ импортировать 3D-график поверхности из внешнего ПО в LaTeX? Есть ли обходной путь*?

*Я думал попробовать собственный TikZ или Asymptote, но могут быть и более простые решения. Использование внешнего программного обеспечения, такого как Matlab, для выполнения сложных графических задач довольно распространено при работе с pgfplots, но я никогда не делал этого для 3D-графиков, и мне интересно, как это может работать. Также я думал об импорте данных из таблицы, но, вероятно, столкнусь с другими проблемами. Я также пробовал фильтровать

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

с тем же ужасным результатом.

решение1

Первый подходпараметризовать функцию или нарисовать ее в полярных координатах. Это может быть трудной задачей в случае сложных функций, таких как та, над которой вы работаете.

Второй подходиспользовать звездный вариант *для restrict z to domain*=0:1000обрезки больших значений. Тем не менее, недостаток в том, что поверхность усечения рисуется:

введите описание изображения здесь

МВЭ:

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

Третий подходоснованный наобходной путьпредоставленоКристиан Фойерзенгер(автор Pgfplots) второй — наложить на поверхность усечения другой цвет поверхности. Теоретически это можно сделать, реализовав контурный график с contour gnuplotвместо surf. К сожалению, это не работает так, как ожидалось.

введите описание изображения здесь

МВЭ (имя файла.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}

Четвертый подходесть в gnuplot 5.4 и команде set pm3d clip z(не поддерживается более ранними версиями 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";

К сожалению, TikZ не может читать файлы таблиц 3D GNUPLOT (сгенерированные с помощью splot), см.Руководство по пакетам TikZ PGF 3.1.5, стр. 342, то есть,

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

дает:Tabular output of this 3D plot style not implemented

Обходной путь — использование gnuplottexпакета с выходным терминалом TikZ.

MWE (еще не тестировал, так как работаю с 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}

Пятый подходс PSTricks и\psplotThreeD

введите описание изображения здесь

МВЭ:

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

решение2

Вот асимптотакоддля создания интерактивного 3DсюжетГамма-функции.

решение3

СледующийОтвет Джона Боумена, я углубился в Asymptote. Изучая, как им пользоваться, я был весьма поражен его возможностями. Мой ответ следуетэта почта, который представляет собой хак Asymptote, crop3Dкоторый решает мою проблему. Несмотря на то, что он довольно «дорогой» (в вычислительном отношении), мне нравится тот факт, что эта техника не требует большого количества дополнительных установок и что ее можно применять практически вслепую (таким образом, ее также можно использовать для получения хорошего усечения гамма-функции, например). Вот мой код

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

и соответствующий вывод:

выход

Большое спасибо всем вам за ваши усилия и поддержку.

решение4

Вот реализация sagetexметода, который я прокомментировал выше, для комплексной гамма-функции.

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

Вывод в Cocalc показан ниже: введите описание изображения здесь

Уменьшение размера шага для получения более точной диаграммы наталкивается на проблемы. Значение по умолчанию bufsize=200000слишком texmf.cnfмало. Вам придется его изменить. На данный момент я не знаю, как изменить значение bufsizeв Cocalc.

Сайт Cocalc бесплатный, но производительность немного падает, как и для бесплатных аккаунтов, как показывает сообщение на картинке. Если вы скопируете/вставите код и запустите его, вы получите ?? на месте картинки. Измените step = .10на step = .1, и он скомпилируется правильно. По какой-то причине первая сборка работает неправильно.

Связанный контент