Skip to content

Instantly share code, notes, and snippets.

@franktoffel
Last active October 2, 2023 07:05
Show Gist options
  • Save franktoffel/f79d84319f043c1d3c897f3732489460 to your computer and use it in GitHub Desktop.
Save franktoffel/f79d84319f043c1d3c897f3732489460 to your computer and use it in GitHub Desktop.
How to plot a 3D heart for San Valentin with Python (matplotlib)
'''
=================================
3D heart shape in matplotlib
=================================
Demonstrates how to plot a 3D function in cartesian coordinates.
Uses the marching cubes algorithm in scikit-image to obtain a isosurface.
Example contributed by CAChemE.org
Adapted from: http://www.walkingrandomly.com/?p=2326
'''
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
import numpy as np
from skimage import measure
# Set up mesh
n = 100
x = np.linspace(-3,3,n)
y = np.linspace(-3,3,n)
z = np.linspace(-3,3,n)
X, Y, Z = np.meshgrid(x, y, z)
# Create cardioid function
def f_heart(x,y,z):
F = 320 * ((-x**2 * z**3 -9*y**2 * z**3/80) +
(x**2 + 9*y**2/4 + z**2-1)**3)
return F
# Obtain value to at every point in mesh
vol = f_heart(X,Y,Z)
# Extract a 2D surface mesh from a 3D volume (F=0)
verts, faces, normals, values = measure.marching_cubes_lewiner(vol, 0, spacing=(0.1, 0.1, 0.1))
# Create a 3D figure
fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(111, projection='3d')
# Plot the surface
ax.plot_trisurf(verts[:, 0], verts[:,1], faces, verts[:, 2],
cmap='Spectral', lw=1)
# Change the angle of view and title
ax.view_init(15, -15)
# ax.set_title(u"Made with ❤ (and Python)", fontsize=15) # if you have Python 3
ax.set_title("Made with <3 (and Python)", fontsize=15)
# Show me some love ^^
plt.show()
@tfeng7
Copy link

tfeng7 commented Jun 1, 2018

hi, kapooramit, this works for me.
verts, faces ,_ ,_ = measure.marching_cubes_lewiner(vol, 0, spacing=(0.1, 0.1, 0.1))

@kiram-4376
Copy link

bad good
that code didn't work I've attached a photo to prove it.

@franktoffel
Copy link
Author

Make sure you have matplotlib (and all the libraries installed) installed.

Try the importing lines separately in your IDLE Shell.

from matplotlib import pyplot as plt

import numpy as np

from skimage import measure

@svyshnya
Copy link

Thank you so much for putting this together! It looks amazing!!! I did, however, notice one thing when running the code. It seems that skimage might have undergone some updates, so now the code in line 35 errors. This is the error message I received:

module 'skimage.measure' has no attribute 'marching_cubes'

I was able to resolve the error by changing measure.marching_cubes to measure.marching_cubes_lewiner, according siva's and Lucan's answer here: https://stackoverflow.com/questions/54056565/attributeerror-module-skimage-measure-has-no-attribute-marching-cubes

After this modification, the code ran successfully, and the heart rendered beautifully. Thank you so much again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment