matplotlib-fill_between-in-3D icon indicating copy to clipboard operation
matplotlib-fill_between-in-3D copied to clipboard

Example of a way of bringing the Python 3 matplotlib.pyplot.fill_between function to 3D plots.

Matplotlib's fill_between in 3D

License: MIT Last Commit

The purpose of this repository is to show an example of a way of bringing the Python 3 matplotlib.pyplot.fill_between function to 3D plots.

The main fill_between_3d function can be found in the FillBetween3d.py file of this repository.

You can see the images of this README file displayed together at the image gallery.

Table of contents

  • Examples of use
    • Example 1
    • Example 2
    • Example 3

Examples of use:

The needed imports for these three examples will be

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection

Example 1

This example shows how to plot three lines with fill_between_3d applied to them in three different equidistant layers. The code is the following:

# x axis 1D space.
x = np.linspace(-10,10,100)

# Define the three functions to plot.
f1 = np.sin(0.25*x)**2 * np.exp(-0.1*(x+0.7)**2) 
f2 = np.sin( 0.5*x)**2 * np.exp(-0.1*(x+0.7)**2)
f3 = np.sin(     x)**2 * np.exp(-0.1*(x+0.7)**2)

# Sets of [x, y, 0] lines (with constant y) for defining the bases of the polygons.
set01 = [x, -7*np.ones(len(x)), np.zeros(len(x))]
set02 = [x,  0*np.ones(len(x)), np.zeros(len(x))]
set03 = [x,  7*np.ones(len(x)), np.zeros(len(x))]

# Sets of the form [x, y, fi] (with constant y) representing each function 3D line.
set1  = [x, -7*np.ones(len(x)), f1]
set2  = [x,  0*np.ones(len(x)), f2]
set3  = [x,  7*np.ones(len(x)), f3]

# Plotting part. Figure and axes creation.
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d', xlim=(-10,10), ylim=(-10,10))

# Plot the f1 line and its fill_between_3d.
ax.plot(*set1, lw=2, zorder=20, c="C0")
fill_between_3d(ax, *set01, *set1, mode = 1, c="C0")

# Plot the f2 line and its fill_between_3d.
ax.plot(*set2, lw=2, zorder=15, c="C1")
fill_between_3d(ax, *set02, *set2, mode = 1, c="C1")

# Plot the f3 line and its fill_between_3d.
ax.plot(*set3, lw=2, zorder=10, c="C2")
fill_between_3d(ax, *set03, *set3, mode = 1, c="C2")

# Correct the z limit of the plot.
ax.set_zlim((0,np.max([f1,f2,f3])))

# Show the plot.
plt.show()

The result is


mode = 1

mode = 2

Example 2

This second and simpler example shows how the fill_between_3d function fills the area between two arbitrary lines laying in the 3d space.

x = np.linspace(-1,1,100)
y = np.linspace(-1,1,100)

set1 = [x, np.cos(2*np.pi*y), np.sin(2*np.pi*y)]     # x, y, z coordinates of the first line (x1, y1, z1)
set2 = [x, 2*np.cos(2*np.pi*y), 2*np.sin(2*np.pi*y)] # x, y, z coordinates of the second line (x2, y2, z2)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

ax.plot(*set1, lw=4)
ax.plot(*set2, lw=4)
fill_between_3d(ax, *set1, *set2, mode = 1)

plt.show()

Example 3

This function can also be used to fill the area between two lines like the matplotlib's fill_between function does in 2D plots but with 3D lines.

x = np.linspace(-2,2,100)
y = np.linspace(-2,2,100)

set1 = [x, np.zeros(len(x)), np.exp(-(x-0.5)**2)]
set2 = [x, np.zeros(len(x)), 0.5*np.exp(-(x)**2)]

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

ax.plot(*set1, lw=4)
ax.plot(*set2, lw=4)
fill_between_3d(ax, *set1, *set2, mode = 1)

plt.show()

Adding

X, Y = np.meshgrid(x, y)
Z = 0.5*np.exp(-(X**2+Y**2))

ax.plot_surface(X, Y, Z, color='darkorange', alpha=0.8)

to the code of this example results in: