PGFplots 使用“wave”绘制显式颜色

PGFplots 使用“wave”绘制显式颜色

我正在尝试绘制复平面中平方根的分支/黎曼曲面(例如维基百科)。为了对平方根的虚部进行编码,我尝试使用颜色wave输入格式为颜色提供具体的值。

我使用极坐标 (x cos(y), x sin(y)),平方根的实部应该是 sqrt(x) cos(y/2),而颜色的虚部是 sqrt(x) sin(y/2)。

考虑以下代码:

\documentclass{article}
\usepackage{pgfplots}

\begin{document}
\begin{tikzpicture}
    \begin{axis}
        \addplot3 [
            surf,
            domain=0:4,
            domain y=-pi:3*pi,
            mesh/color input=explicit mathparse,
            point meta={symbolic={wave=363+(2+sqrt(x)*sin(deg(y/2)))/4*(814-363)}}
        ]
            (x,y,0); % This works just fine
            % ({x*cos(deg(y))}, {x*sin(deg(y))}, {sqrt(x)*cos(deg(y/2))}); % This breaks!
    \end{axis}
\end{tikzpicture}

\end{document}

绘制水平面不会产生任何问题。但使用实际绘图时,我收到以下错误消息:

Package pgfplots Error: Sorry, the color component value nan (no. 0) is out of range. The allowed range is 0 <= value <= 1. The error occured near `point meta 'wave=363+(2+sqrt(x)*sin(deg(y/2)))/4*(814-363)' of coord no 6 (2Y9.99975739e-1],2Y3.141592654e0],0Y0.0e0])'.

这也发生在其他坐标上。

编辑:我把它归结为第一个论点,这cos(deg(y))似乎是问题所在。

编辑:它看起来应该是这样的:

平方根的分支。

此图片取自维基百科注意颜色分布。例如,黄色、绿色和青色出现了两次,而蓝色和红色只出现了一次。更准确地说,两个黄色部分并不是精确地位于另一个之上,而是沿着实线反射。

编辑:只是写下我写的评论:更不用说这个代码,它与官方文档,第 151 页,经过一些修改后失败。

\documentclass{article}
\usepackage{pgfplots}

\begin{document}
\begin{tikzpicture}
    \begin{axis}
        \addplot3 [
            surf,
            domain=0:1,
            domain y=0:1,
            mesh/color input=explicit mathparse,
            point meta={symbolic={wave=363+x*(814-363)}}
        ]
            (x,y,0); % This works just fine
            % (y,x,0); % This breaks!
    \end{axis}
\end{tikzpicture}

\end{document}

答案1

我不熟悉如何定义颜色图,但你的绘图问题可以通过使用精确的引擎来计算点来解决。总是有选择(Asymptote、lua 等)。我推荐智者有几个原因。首先,它是一个 CAS(计算机代数系统),因此它是提供精确计算的最高级别的数学软件。其次,作为 CAS,您可以使用其他程序无法访问的内置功能(导数、矩阵、图论、微分方程等)。第三,您可以使用 Python,这允许您绕过 LaTeX 编程。第四,SAGE 单元服务器(或 Sagemath 应用程序)可以帮助您轻松地从平板电脑上进行修改。以下是使用sagetexjet颜色图的解决方案:

\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\usepackage{sagetex}
\pgfplotsset{compat=1.15} 
\begin{document}
\begin{sagesilent}
var('x,y')
xcoords = [i for i in srange(0,4,.2)]
ycoords = [i for i in srange(-3.14,9.52,.2)]

output = ""
output += r"\begin{tikzpicture}[scale=1.0]"
output += r"\begin{axis}[view={-10}{-40},xmin=%d, xmax=%d, ymin=%d, ymax=%d]"%(-4,4,-4,4)
output += r"\addplot3[colormap/jet,surf,opacity=0.5,mesh/rows=%d] coordinates {"%(len(ycoords))
# the length of ycoords is the number of y values
for y in ycoords:
    for x in xcoords:
        output += r"(%f, %f, %f) "%(x*cos(y),x*sin(y),sqrt(x)*cos(y/2))

output += r"};"
output += r"\end{axis}"
output += r"\end{tikzpicture}"
\end{sagesilent}
\sagestr{output}
\end{document}

Cocalc 中的结果是:

在此处输入图片描述

我已经设置了opacity=0.5,您可能想试验一下该值。

该行在xcoords = [i for i in srange(0,4,.2)]Python 中创建了我的 x 值列表,范围从 0、.2、.4 到 3.8,y 值由 SAGE 创建,这提供了我们期望的精度。sagetex在 Python 的帮助下,需要 3 个步骤才能将我的代码创建为字符串。将for-loop坐标放入字符串中,最终使用 将其放入文档中\sagestr{output}

SAGE 不是 LaTeX 发行版的一部分。最简单的试用方法是获取免费的Cocalc 账户。您也可以将 SAGE 下载到您的计算机并使其与您的 LaTeX 发行版配合使用,但这是一个更长且更困难的过程。搜索此网站以获取有关如何sagetex使用该软件包的更多示例。

编辑:我认为你的方法的问题在于这x不是我们想要的。我们认为x是非负的,因为你将其定义为介于 0 和 4 之间,但根据绘图程序, x的值是。我注意到,如果我使用 sqrt(abs(x)),程序运行良好: xx*cos(y)在此处输入图片描述

如果我删除绝对值那么它根本无法编译:

在此处输入图片描述

请注意错误消息告诉我该值需要介于 0 和 1 之间。当我检查我的数据文件时,它显示许多为负的 x 值:

在此处输入图片描述

在我看来,这wave=363+(2+sqrt(x)*sin(deg(y/2)))/4*(814-363)是在计算 x 值的平方根:{x*cos(deg(y))}而不是x您定义的 0 到 4 之间的值。由于{x*cos(deg(y))}是负数,平方根给出的是一个虚数,不在 [0,1] 内。我不知道在这种情况下如何使wave颜色图工作。

答案2

这不是一个令人满意的答案,因为这不会解决这个错误,但是我今天用渐近线弄脏了我的手,我很高兴(虽然渐近线并不总是能很好地将 3d 图形渲染为矢量图形)。

\documentclass[convert]{standalone}

\usepackage{asymptote}

\begin{document}

\begin{asy}
    settings.prc = false;
    settings.render = 0;
    unitsize(1cm);
    fontsize(11pt);
    size(5cm);

    import graph3;
    import palette;

    currentprojection=orthographic(-0.8,-1.1,0.8);
    int angles = 60;
    int radii = 15;

    triple f(pair z) { // using polar coordinates
        return (z.x * cos(z.y), z.x * sin(z.y), sqrt(z.x) * cos(z.y/2));
    }

    triple c(pair z) { // using polar coordinates
        return (z.x * cos(z.y), z.x * sin(z.y), sqrt(z.x) * sin(z.y/2));
    }

    surface s = surface(f, (0,-pi), (1,3pi), nu=radii, nv=angles, Spline);
    pen[][] p = palette(surface(c, (0,-pi), (1,3pi), nu=radii, nv=angles).map(zpart), Wheel());
    draw(s, mean(p), meshpen=black+linewidth(0.2pt));

    xaxis3(Bounds(Min, Min), -1, 1, OutTicks(2,2));
    yaxis3(Bounds(Min, Min), -1, 1, OutTicks(2,2));
    zaxis3(Bounds(Min, Max), -1, 1, OutTicks(2,2));
\end{asy}

\end{document}

在此处输入图片描述

相关内容