7

I have been trying to get this surface drawn using pgfplot, but I can't make it look like the picture I'm trying to make the code for.

\documentclass{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
    
    \begin{axis}[view = {70}{-40},
        xmax = 4,
        xmin = -4,
        ymax = 4, 
        ymin = -4, 
        restrict z to domain = -2:5]
        
        \addplot3 [
        domain=-3:3,
        domain y = -3:3,
        surf] {x^2 + y^2};
        
    \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

I also really want to draw some other surfaces together with my surface, but I do not have any clue how to do that. (See the pictures) enter image description here

I really hope you can point me in the right direction.

3
  • I heard that 'geogebra' can convert plotted function into tikzpicture or something like that, have You tried that? Oct 18, 2021 at 10:10
  • 1
    The graphs where two plots are crossing each other is doable in PGFPlots(TikZ)(with no z-buffer between plots), but is takes a lot of manual work to split the plots into areas where one or the other is on top. -use Asymptote - see answer by @Black Mild. Oct 18, 2021 at 12:03
  • @Jakob: Maybe you should help the helpers by providing more information such as the equations for parabolic cylinders. Personally I do not want to guess that ^^
    – Black Mild
    Oct 18, 2021 at 14:09

3 Answers 3

9

It does not make sense to use a surf plot for a completely flat area - just use \fill like this:

\documentclass[border=1 cm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
view={45}{20},
xmin=-4, xmax=4,
ymin=-4, ymax=4, 
zmin=-2, zmax=5,
axis lines=middle,
axis on top,
]
\fill[red!80!black] plot[domain=-sqrt(2.5):sqrt(2.5),samples=100] (\x,\x,{2*(\x)^2}) --cycle;
\fill[red!80!pink] (0,0,5) circle[radius=sqrt(5)];
\end{axis}
\end{tikzpicture}
\end{document}

Red parabola in 3D axis

If you want it shaded with a grid or other things, you can use a surf plot like this:

\documentclass[border=1 cm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
colormap/hot2,
view={45}{20},
xmin=-4, xmax=4,
ymin=-4, ymax=4, 
zmin=-2, zmax=5,
restrict z to domain=-2:6,
axis lines=middle,
axis on top,
]
\addplot3[
surf,
samples=51,
] {x^2 + y^2};
\fill[white] (0,0,5) +(-2cm,0cm) rectangle +(2cm,1cm);
\draw[fill=red!80!pink] (0,0,5) circle[radius=sqrt(5)];
\end{axis}
\end{tikzpicture}
\end{document}

Shaded black/red/yellow parabola

0
16

The first figure with Asymptote. Other figures can be drawn in a similar way.

enter image description here

import graph3;
currentprojection=orthographic(2,1.5,.5,zoom=.95);
unitsize(1cm);
//currentprojection=obliqueX(40);
size(8cm);
real a=4.5; // below z=a
triple f(pair M) {
real x = sqrt(a)*(M.x)*cos(M.y);
real y = sqrt(a)*(M.x)*sin(M.y);
return (x,y,x^2+y^2);
}
real rmax = 1, rmin =0;
real phimax =2*pi, phimin =0;
surface s=surface(f, (rmin,phimin), (rmax,phimax), Spline);
//draw(s, surfacepen=pink,meshpen=brown+thick());
draw(s,surfacepen=yellow+opacity(.7));

real b=2.5;
real x(real t) {return sqrt(b)*cos(t);}
real y(real t) {return sqrt(b)*sin(t);}
real z(real t) {return b;}
path3 g=graph(x,y,z,phimin,phimax,operator..);
draw(g,red+1pt);

draw(shift(-3,-3,b)*scale(6,6,0)*unitplane,blue+opacity(.5));

draw(Label("$x$",EndPoint),-5*X--5*X,Arrow3());
draw(Label("$y$",EndPoint),-5*Y--5*Y,Arrow3());
draw(Label("$z$",EndPoint),-Z--6*Z,Arrow3());

The second picture: we can play with opacity values, remove the red box. I choose the parabolic cylinder z=1+2y^2.

enter image description here

// http://asymptote.ualberta.ca/
unitsize(1cm);
size(8cm);
import graph3;
currentprojection=orthographic(2,1.4,.6,zoom=.95);
//currentprojection=obliqueX(40);

// the yellow paraboloid z=f(x,y)= x^2+y^2
real a=2.25; // below z=a^2
// to take domain is a disk (instead of a rectangle)
triple f(pair M) {
real x = a*(M.x)*cos(M.y);
real y = a*(M.x)*sin(M.y);
return (x,y,x^2+y^2);
}
real rmax=1, rmin=0;
real phimax=2*pi, phimin=0;
surface sf=surface(f, (rmin,phimin), (rmax,phimax), Spline);
//draw(sf, surfacepen=pink,meshpen=brown+thick());
draw(sf,surfacepen=yellow+opacity(1));

triple h(pair M) {
if (1+2M.y^2>a^2) return (M.x,M.y,a^2);
else return (M.x,M.y,1+2M.y^2);
}
real xmax=4, xmin=-4;
real ymax=1.5, ymin=-1.5;
surface sh=surface(h, (xmin,ymin), (xmax,ymax), Spline);
//draw(sh, surfacepen=pink,meshpen=brown+thick());
draw(sh,surfacepen=blue+opacity(.8));

triple A=(xmin,ymin,0), B=(xmax,ymax,a^2);
draw(box(A,B),red+opacity(.5));

// the red circle x^2+y^2=b^2 is the intersection of
// the blue plane z=b^2 and the paraboloid
real b=1.6;
real x(real t) {return b*cos(t);}
real y(real t) {return b*sin(t);}
real z(real t) {return b^2;}
path3 g=graph(x,y,z,phimin,phimax,operator..);
//draw(g,red+1pt);

//draw(shift(-3,-3,b^2)*scale(6,6,0)*unitplane,blue+opacity(1));

draw(Label("$x$",EndPoint),-5*X--5*X,Arrow3());
draw(Label("$y$",EndPoint),-5*Y--5*Y,Arrow3());
draw(Label("$z$",EndPoint),-Z--7*Z,Arrow3());
3
  • 1
    This is quite beautiful. Oct 19, 2021 at 19:10
  • I updated the 2nd picture.
    – Black Mild
    Oct 20, 2021 at 19:15
  • @CaptainGiraffe beautiful is as beautiful does!
    – Black Mild
    Oct 21, 2021 at 15:10
6

I offer a TikZ solution. I think that for this figure it's easier to draw in 2d, so I did it this way.

I'm not posting the maths, because it will be tedious without MathJax or something similar. But the key here is to find the envelope of the family of ellipses (circles in 3d) that are obtained cutting the paraboloid by horizontal planes.

Making the drawing in this way all the calculations are exact (as far as TikZ goes) and all the curves are TikZ paths, I'm not using plot (see the update 1 below).

The code:

\documentclass[tikz,border=2mm]{standalone}

\tikzset
{%
  axes/.style={thick,-latex},
  paraboloid front/.style={right color=red!80,left color=white,fill opacity=0.6},
  paraboloid back/.style={left color=red!80,fill opacity=0.6},
  plane/.style={blue,fill=blue!50,fill opacity=0.8},
}

\begin{document}
\begin{tikzpicture}[line cap=round,line join=round]
% axes x,y
\draw[axes]  (30:4)  -- (210:4) node [left]  {$x$};
\draw[axes]  (150:4) -- (330:4) node [right] {$y$};
\draw[thick] (0,0)   -- (0,2.25);
% paraboloid, bottom, back
\draw[paraboloid back] ({0.25*sqrt(51)},2) parabola bend (0,-0.125) ({-0.25*sqrt(51)},2)
  arc ({180+atan(1/sqrt(17))}:{-atan(1/sqrt(17))}:{0.75*sqrt(6)} and {0.75*sqrt(2)});
% paraboloid, bottom, front
\draw[paraboloid front] ({0.25*sqrt(51)},2) parabola bend (0,-0.125) ({-0.25*sqrt(51)},2)
  arc ({180+atan(1/sqrt(17))}:{360-atan(1/sqrt(17))}:{0.75*sqrt(6)} and {0.75*sqrt(2)});
% horizontal plane
\draw[plane] (210:3) ++ (0,2.25) ++ (330:3.5) --++ (30:6) --++ (150:7) --++ (210:6) -- cycle;
% paraboloid, top, back
\draw[paraboloid back] ({0.25*sqrt(93)},3.75) parabola bend (0,-0.125) ({0.25*sqrt(51)},2)
   arc ({-atan(1/sqrt(17))}:{180+atan(1/sqrt(17))}:{0.75*sqrt(6)} and {0.75*sqrt(2)})
   parabola bend (0,-0.125) ({-0.25*sqrt(93)},3.75)
   arc ({180+atan(1/sqrt(31))}:{-atan(1/sqrt(31))}:{sqrt(6)} and {sqrt(2)});
% axis z
\draw[axes] (0,2.25) -- (0,6) node [above] {$z$};
% paraboloid, top, front
\draw[paraboloid front] ({0.25*sqrt(93)},3.75) parabola bend (0,-0.125) ({0.25*sqrt(51)},2)
   arc ({-atan(1/sqrt(17))}:{-180+atan(1/sqrt(17))}:{0.75*sqrt(6)} and {0.75*sqrt(2)})
   parabola bend (0,-0.125) ({-0.25*sqrt(93)},3.75)
   arc ({180+atan(1/sqrt(31))}:{360-atan(1/sqrt(31))}:{sqrt(6)} and {sqrt(2)});
\end{tikzpicture}
\end{document}

Update 1: I didn't it see at first, but the above code doesn't get the visibility right. This is because the parabola bend path draws the parabola to the vertex despite the last point specified is before this vertex. So I don't think parabola is the right way to do it after all. I could do a clip, but it will not be easy to find the appropriate path. Perhaps spath3 library will do the trick, I'll take a look at it in the future (see update 2 below).

Meanwhile, the same drawing with plots:

\documentclass[tikz,border=2mm]{standalone}

\tikzset
{%
  axes/.style={thick,-latex},
  paraboloid front/.style={right color=red!80,left color=white,fill opacity=0.6},
  paraboloid back/.style={left color=red!80,fill opacity=0.6},
  plane/.style={blue,fill=blue!50,fill opacity=0.8},
}

\newcommand{\myparabola}[2]{-- plot [domain={#1}:{#2},samples=40] (\x,2/3*\x*\x-0.125)}

\begin{document}
\begin{tikzpicture}[line cap=round,line join=round]
% dimensions
\pgfmathsetmacro\angTC{atan(1/sqrt(31))} % angles, top circle
\pgfmathsetmacro\angBC{atan(1/sqrt(17))} % angles, bottom circle
\pgfmathsetmacro\TTx  {0.25*sqrt(93)}    % tangent point x, top circle
\pgfmathsetmacro\TBx  {0.25*sqrt(51)}    % tangent point x, bottom circle
% axes x,y
\draw[axes]  (30:4)  -- (210:4) node [left]  {$x$};
\draw[axes]  (150:4) -- (330:4) node [right] {$y$};
\draw[thick] (0,0)   -- (0,2.25);
% paraboloid, bottom, back
\draw[paraboloid back] (-\TBx,2)
  arc (180+\angBC:-\angBC:{0.75*sqrt(6)} and {0.75*sqrt(2)}) \myparabola{\TBx}{-\TBx};
% paraboloid, bottom, front
\draw[paraboloid front] (-\TBx,2)
  arc (180+\angBC:360-\angBC:{0.75*sqrt(6)} and {0.75*sqrt(2)}) \myparabola{\TBx}{-\TBx};
% horizontal plane
\draw[plane] (210:3) ++ (0,2.25) ++ (330:3.5) --++ (30:6) --++ (150:7) --++ (210:6) -- cycle;
% paraboloid, top, back
\draw[paraboloid back] (\TBx,2)
  arc (-\angBC:180+\angBC:{0.75*sqrt(6)} and {0.75*sqrt(2)}) \myparabola{-\TBx}{-\TTx}
  arc (180+\angTC:-\angTC:{sqrt(6)} and {sqrt(2)}) \myparabola{\TTx}{\TBx};
% axis z
\draw[axes] (0,2.25) -- (0,6) node [above] {$z$};
% paraboloid, top, front
\draw[paraboloid front] (\TBx,2)
  arc (-\angBC:-180+\angBC:{0.75*sqrt(6)} and {0.75*sqrt(2)}) \myparabola{-\TBx}{-\TTx}
  arc (180+\angTC:360-\angBC:{sqrt(6)} and {sqrt(2)}) \myparabola{\TTx}{\TBx};
\end{tikzpicture}
\end{document}

And the drawing (with the right visibility):

enter image description here

Update 2: This is my first attempt at Andrew Stacey's spath3 library. I'm don't know if I know what I'm doing, so use it at your own risk!! (It needs TL2021, I don't know about other LaTeX distros).

I'm following Andrew's excellent answer here (the second one) step by step. In fact the comments about spath3 are all his (I changed a word or two). And , of course, the errors are all mine.

The new code:

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{intersections,spath3}

\tikzset
{%
  axes/.style={thick,-latex},
  paraboloid front/.style={right color=red!80,left color=white,fill opacity=0.6},
  paraboloid back/.style={left color=red!80,fill opacity=0.6},
  plane/.style={blue,fill=blue!50,fill opacity=0.8},
}

\begin{document}
\begin{tikzpicture}[line cap=round,line join=round]
% creating the paths: parabola, two ellipses and two lines (for cutting)
\path[spath/save=P]  ({-0.25*sqrt(93)},3.75) parabola bend (0,-0.125) ({0.25*sqrt(93)},3.75);
\path[spath/save=EB] (0,2.25) ellipse ({0.75*sqrt(6)} and {0.75*sqrt(2)}); % ellipse, bottom
\path[spath/save=ET] (0,4)    ellipse ({sqrt(6)} and {sqrt(2)});           % ellipse, top
\path[spath/save=LB] (-3,2)    -- (3,2);                                   % line,    bottom
\path[spath/save=LT] (-3,3.75) -- (3,3.75);                                % line,    top
% spath3 operations
\tikzset
{% Ellipses have an "empty" component at the start which
 % moves from the centre to the rim; it can be irritating
 % when trying to count components later so this removes
 % any empty components
   spath/remove empty components={EB},
   spath/remove empty components={ET},
 % Now split each path where it intersects with the lines
   spath/split at intersections={P}{LB},
   spath/split at intersections={EB}{LB},
   spath/split at intersections={ET}{LT},
 % Each path is now a collection of components; to work
 % with them individually we split them into a list of
 % separate paths which is stored in a macro
   spath/get components of={P}\Pcpts,
   spath/get components of={EB}\Bcpts,
   spath/get components of={ET}\Tcpts,
}
% axes x,y
\draw[axes]  (30:4)  -- (210:4) node [left]  {$x$};
\draw[axes]  (150:4) -- (330:4) node [right] {$y$};
\draw[thick] (0,0)   -- (0,2.25);
% paraboloid, bottom, back
\draw[paraboloid back,
      spath/use=\getComponentOf\Pcpts{2},
      spath/use={\getComponentOf\Bcpts{2},weld},
];
% paraboloid, bottom, front
\draw[paraboloid front,
      spath/use=\getComponentOf\Pcpts{2},
      spath/use={\getComponentOf\Bcpts{1},reverse,weld}
];
% horizontal plane
\draw[plane] (210:3) ++ (0,2.25) ++ (330:3.5) --++ (30:6) --++ (150:7) --++ (210:6) -- cycle;
% paraboloid, top, back
\draw[paraboloid back,
      spath/use=\getComponentOf\Pcpts{1},
      spath/use={\getComponentOf\Bcpts{2},reverse,weld},
      spath/use={\getComponentOf\Pcpts{3},weld},
      spath/use={\getComponentOf\Tcpts{2},weld}
];
% axis z
\draw[axes] (0,2.25) -- (0,6) node [above] {$z$};
% paraboloid, top, front
\draw[paraboloid front,
      spath/use=\getComponentOf\Pcpts{1},
      spath/use={\getComponentOf\Bcpts{1},weld},
      spath/use={\getComponentOf\Pcpts{3},weld},
      spath/use={\getComponentOf\Tcpts{1},reverse,weld}
];
\end{tikzpicture}
\end{document}

The output is the same as above.

3
  • You are so patient with the numbers in your code!
    – Black Mild
    Oct 21, 2021 at 15:12
  • 1
    @BlackMild, yes I know. This way of do it's more a maths problem that anything, but it's the first time I thought of drawing a surface as an envelope of curves, and I enjoyed the challenge!! Oct 21, 2021 at 19:00
  • envelope is a nice idea for sure!
    – Black Mild
    Oct 21, 2021 at 20:26

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.