29

I want to produce smooth surface plots with smooth grid lines using TikZ/pgfplots. Usually, this can be achieved using e.g. [samples=100], but this also draws 100 grid lines. I basically want that

  1. the surface and the grid lines are computed using many help points (samples) to make it smooth
  2. but only a fraction of the grid lines shall be drawn.

I've browsed the documentation, but couldn't find anything helpful in that direction. All the surface plot examples which I found showed edgy grid lines giving the surface a faceted look instead of the smooth pictures I want to achieve.

Here's a minimal working example for two different sample values:

\documentclass{article}
\usepackage{tikz, pgfplots}

\begin{document}

\begin{tikzpicture}
   \begin{axis}[samples=10]
      \addplot3[surf, domain=-2:2] {x^2-y^2};
   \end{axis}
\end{tikzpicture}

\begin{tikzpicture}
   \begin{axis}[samples=100]
      \addplot3[surf, domain=-2:2] {x^2-y^2};
   \end{axis}
\end{tikzpicture}

\end{document}

Output from MWE

In the first picture, the lines are too edgy, in the second picture all the many lines are drawn. How can I achieve a smooth looking surface with only a few, but smooth, grid lines?

7
  • 6
    You can get the surf and mesh independently with \addplot3[surf, shader=interp,domain=-2:2] {x^2-y^2}; \addplot3[mesh,samples=20,draw=black,domain=-2:2] {x^2-y^2};. and increase the mesh sample size until you are happy with it. Use it without the [samples=100] option in the axis environment.
    – percusse
    Jan 2, 2012 at 22:07
  • 3
    @percusse throw in a screenshot, and your comment is an answer :)
    – cmhughes
    Jan 2, 2012 at 22:12
  • @cmhughes Since I am still a novice on pgfplots I don't know if that is the way to go. If Kristin thinks it is useful, I would make it an answer but thanks for the pat on the shoulder, though :)
    – percusse
    Jan 2, 2012 at 22:46
  • @percusse Thanks, separating surface and grid lines using mesh is a good beginning. However, for the mesh, I want to draw, say, only 5 or 10 lines per dimension, but they shall look smooth nevertheless. I could say: forget about the surface coloring, just give me a few nicely curved grid lines to describe the surface. Is there any way to achieve this?
    – Kristin
    Jan 2, 2012 at 22:54
  • That's why I didn't make it an answer and I don't know a quick fix yet. Maybe @ChristianFeuersänger or someone else drop by and share their view.
    – percusse
    Jan 2, 2012 at 23:04

2 Answers 2

25

The answer of pgfplots for "mesh plots with smooth boundary" is its patchplots library, combined with one of the higher-order patch types. Take, for example, patch type=biquadratic : its boundaries are second order polynomials. This allows to provide a coarse-grained grid combined with smoothness.

The cost for such a format is to provide patches in a nontrival sequence: coordinates

0 1 2 3 4 5 6 7 8 

are interpreted as the following points on a (single) rectangle:

3  6  2
7  8  5
0  4  1

the next 9 points make up the next rectangle and so forth. Here, points 0,1,2,3 make up the corners whereas points 4,5,6,7 are used to define the boundary parables. Point 8 is only relevant if you have shader=interp; I think it is unused for mesh plots. If you combine the approach with shader=faceted interp, you get smooth fill colors + mesh lines.

Examples and images can be found in Section 5.6 Patchplots Library.

Of course, the cost is to manually arrange your input coordinate sequence in the format shown above - one set of 9 arranged points for every patch. To simplify this, you can also provide a single list of coordinates, and a connectivity table which tells pgfplots that patch 0 consists of vertices with indices #42 #5# #7 #3 #30 #12 ... (see the patch table option of pgfplots).

The alternatives are (as percusse already mentioned) to combine two plots: one which only fills the surface and one which provides the mesh. However, this has a severe limitation: pgfplots only considers image depths inside of one single plot (compare the discussion and the alternative solution described in Section "5.6.4 Drawing Grids" in the patch plots library.

pgfplots has no option to "draw only each Nth mesh line".

EDIT

I have just realized that your example function is a biquadratic function! As such, you only need one patch to capture its boundary without any loss in precision - and the effort to put input coordinates into the requested sequence is limited to only 9 points. That can be done by means of \addplot table[z expr=<expression>].

Only the color interpolation is of first order (because pdf only supports bilinear interpolation). Consequently, you can get the effect for your example function using shader=faceted interp combined with patch refines - and just one patch as input:

enter image description here

\documentclass{article}

\usepackage{pgfplots}
\usepgfplotslibrary{patchplots}

\pgfplotsset{compat=1.3}

\begin{document}
\thispagestyle{empty}

\begin{tikzpicture}
    \begin{axis}
    \addplot3[patch,patch refines=3,shader=faceted interp,patch type=biquadratic] 
        table[z expr=x^2-y^2]
    {
        x y
        -2 -2
        2 -2
        2 2
        -2 2
        0 -2
        2 0
        0 2
        -2 0
        0 0
    };
    \end{axis}
\end{tikzpicture}
\end{document}

Here is it with patch refines=2:

enter image description here

4
  • Cool, thanks a lot! I didn't come across the patch library so far. It looks quite complicated, but the results are promising!
    – Kristin
    Jan 4, 2012 at 22:48
  • I fear that it has, indeed, a quite complicated input format. Its intended audience is people importing high order geometries from numerical programs or from CAD programs. But it should be applicable anyway. Jan 5, 2012 at 18:14
  • Note that I have just realized that your example function actually is a biquadratic function -- and can be represented by just one patch. See my edited answer. Feb 27, 2012 at 21:30
  • Thanks, that's a helpful addition! And makes things a little less complicated.
    – Kristin
    Feb 28, 2012 at 20:59
7

You can disable the grids with the "shader=inter" as suggested by @percusse . Then set the grids to whatever you want. Here is an example where the grids are each 1 (unit) distance for x and y.

\documentclass[12pt]{article}
\usepackage{amsmath}
\usepackage{enumerate}
\usepackage{tikz}
\usepackage{xcolor}
\usepackage{tikz-3dplot}
\usepackage{hyperref}
\usepackage{ifthen}
\usepackage{pgfplots}
\pgfplotsset{compat=1.11}

\begin{document}
\begin{tikzpicture}
   \begin{axis}[samples=60]
      \addplot3[surf, domain=-2:2, shader=interp] {x^2-y^2};
      \foreach \xx in {-2.0,-1.0,...,2.0}
      {
        \addplot3+[domain=-2:2, line width=0.1mm, mark=none, color=black, samples y=0]
         ({\xx}, {x}, {\xx*\xx-x^2});
      }

      % y=constant grids lines
      \foreach \yy in {-2.0,-1.0,...,2.0}
      {
         \addplot3[domain=-2:2, line width=0.1mm, mark=none, color=black, samples y=0]
         ({x}, {\yy}, {x^2-\yy*\yy});
      }


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

and here the figure:

Grids separated one unit on each direction

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .