3

I'm using the pgfplots package in an attempt to draw the function s(p0) = sign(Re p0) sign(Im p0), where p0 is a complex number. What I have so far is

\documentclass[svgnames]{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=1.7}

\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        ticks=none,
        xlabel=$\mathrm{Re}(p_0)$,
        ylabel=$\mathrm{Im}(p_0)$,
        zlabel=$s(p_0)$]

    \addplot3[surf,domain=-1:1,color=DarkBlue!20]{x/abs(x)*y/abs(y)};
    \addplot3[mesh,domain=-1:1,color=black,samples=10]{0};% complex plane

    \end{axis}
\end{tikzpicture}
\end{document}

which produces this rather ugly plot.

enter image description here

What I would like to have is something akin to this:

enter image description here

So my question is, how can I

  1. remove those annoying "cliffs",
  2. add low-opacity color to the complex plane, i.e. the mesh at z = 0
  3. add proper depth perception,
  4. add numbers but no markers sparingly to the axes, i.e. just -1, 0, and 1, and
  5. apply nicer colors not only to the mesh but the actual surface of the plot.
5
  1. remove those annoying "cliffs"

Pgfplots allows to exclude parts of surfaces using two different ways: either by assigning "unbounded coords" (like z=nan) for specific data points or by using "unbounded color data" (point meta=nan).

Below, I chose to use "unbounded color data" and added a suitable color data by means of point meta={abs(x) < 1e-3 || abs(y) < 1e-3 ? nan : z} . This means that the colordata is a scalar value which is nan for x ~ 0 and y ~0 and is the z value otherwise. This means that the axis in the middle becomes invisible (i.e. the adjacent surface segments are omitted).

Details: see section "4.5.14 Interrupted Plots" in the manual.

  1. "add low-opacity color to the complex plane"

I added opacity=0.7 to its option list. Any kind of tikz drawing option can be added, and this is how opacity is configured. Please refer to the manual of tikz for a complete list of graphics state options (pgfmanual.pdf)

  1. "add proper depth perception"

This something that pgfplots simply cannot do at the time of this writing. In order to combine multiple overlapping surfaces, you have two choices: resort to another 3d visualization tool or reorder the surface segments manually.

Since this question is about pgfplots, I followed the second approach. In my case, this results in two surfaces for the jump plot: one above and one below the complex plane. To this end, I simply modified the already existing filter for point meta by adding z>0 or z<0, respectively. See below.

  1. "Add numbers but no markers"

I used xtick distance combined and tickwidth below

  1. "apply nicer colors"

What does "nicer" mean? Personally, I like it if the mesh color is "close" to the surface color; something that pgfplots does by default. Consequently, I simply reverted your color override to the default. The default is to map the scalar color data into a colormap. Details about this can be found in the pgfplots manual or may be subject of a follow-up question.

I chose colors for the complex plane explicitly as its colormap mapping is hard to control (it has no min/max). You can, of course, easily generalize it to the other two segments.

\documentclass{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=1.7}

\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        xlabel=$\mathrm{Re}(p_0)$,
        ylabel=$\mathrm{Im}(p_0)$,
        zlabel=$s(p_0)$,
        xtick distance=1,
        ytick distance=1,
        ztick distance=1,
        tickwidth=0pt,
    ]

    \addplot3[
        surf,domain=-1:1,%color=DarkBlue!20,
        point meta={abs(x) < 1e-3 || abs(y) < 1e-3 || z > 0 ? nan : z},
    ] {x/abs(x)*y/abs(y)};

    \addplot3[
        %mesh,
        surf,
        domain=-1:1,
        opacity=0.7,
        blue!50!white,faceted color={blue},
        %color=black,
        samples=10,
    ]{0};% complex plane

    \addplot3[
        surf,domain=-1:1,%color=DarkBlue!20,
        point meta={abs(x) < 1e-3 || abs(y) < 1e-3 || z < 0 ? nan : z},
    ] {x/abs(x)*y/abs(y)};
    \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

0
0

Coming back to this problem after some time, I think the simplest solution is probably to just specify coordinates rather than plot the actual function. This approach improves both compile time and file size.

enter image description here

\documentclass{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        xlabel=$\Re(p_0)$,
        ylabel=$\Im(p_0)$,
        zlabel=$s(p_0)$,
        domain=-1:1,
        surf,shader=flat,
        xtick distance=1,
        ytick distance=1,
        ztick distance=1,
        tickwidth=0pt
    ]

    \addplot3[blue!20] coordinates {
        (-1,1,-1) (0,1,-1)

        (-1,0,-1) (0,0,-1)
    };

    \addplot3[blue!20] coordinates {
        (1,-1,-1) (0,-1,-1)

        (1,0,-1) (0,0,-1)
    };

    % Zero plane
    \addplot3[
        gray,opacity=0.1,
        samples=2,
    ]{0};

    \addplot3[orange!80] coordinates {      
        (0,0,1) (1,0,1)

        (0,1,1) (1,1,1)
    };

    \addplot3[orange!80] coordinates {      
        (0,0,1) (-1,0,1)

        (0,-1,1) (-1,-1,1)
    };

    \end{axis}
\end{tikzpicture}
\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.