Plotting surface and curve in 3D and a curve in xy-plane, all in the same plot

Question:

To illustrate an optimization problem, I want all of this in the same 3D plot:

  • A surface.
  • A curve in the xy-plane.
  • A curve/path on the surface which marks out the points on the surface that lies directly above the curve in the xy-plane.

This is my code so far:

import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator
import numpy as np
from mpl_toolkits import mplot3d

fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
X = np.linspace(-5,5,100)
Y = X
X, Y = np.meshgrid(X, Y)
Z = 50 - X**2 - Y**2

#Plotting curve on the surface
ax = plt.axes(projection='3d')

yline = np.linspace(-5,5,100)
xline = -np.sqrt(4/(2+yline**2)) #the x-values of the curve in the xy-plane
zline = 50 - xline**2 - yline**2 

ax.plot3D(xline, yline, zline, "black")

surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm)
ax.set_zlim(0, 50)

#Plotting curve in xy-plane
a = 5
g = 1 - 2*X - X*Y**2
plt.contour(X,Y,g, [a], offset=0)

plt.show()

Here is the plot from two different angles:
from eye height
bird perspective

Some problems:

  • First of all, it seems like the axes have been numbered twice. Is that because I make a meshgrid, and later on use ax.plot3D? That I use two different ways of plotting something, and as a consequence make the 3D space twice?
  • The path on the surface appears weakly. Is there a way to make the path more visible?
  • From the picture in bird perspective, we see that the path does not lie directly above the curve in the xy-plane. What would be easier, was if Python had a built-in function who could project the curve in the xy-plane directly onto the surface. Am I missing something here? Does anyone know of such a function?

These questions might be dummy questions, but answers and tips are highly appreciated!

Asked By: abstract_je

||

Answers:

  1. The code creates two axes objects (both assigned to the ax variable) in the same figure. This is not needed and results in double ticks marks.

  2. To make the path on the surface more visible, plot it with a higher zorder.

  3. The curve on the surface does not overlap with the curve on the xy plane because these are different curves. To plot the projection of the surface curve on the xy plane, set all z-coordinates of the curve to 0.

Below is the code with these changes.

import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator
import numpy as np
from mpl_toolkits import mplot3d

fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
X = np.linspace(-5, 5, 100)
Y = X
X, Y = np.meshgrid(X, Y)
Z = 50 - X**2 - Y**2

yline = np.linspace(-5, 5, 100)
xline = -np.sqrt(4 / (2 + yline**2))
zline = 50 - xline**2 - yline**2
ax.plot3D(xline, yline, zline, "b", zorder=10)

surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm, alpha=0.7)
ax.set_zlim(0, 50)

#Plotting curve in xy-plane
ax.plot3D(xline, yline, 0, "k")

plt.show()
Answered By: bb1
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.