Last active
October 2, 2023 07:05
-
-
Save franktoffel/f79d84319f043c1d3c897f3732489460 to your computer and use it in GitHub Desktop.
How to plot a 3D heart for San Valentin with Python (matplotlib)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
================================= | |
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
tomeasure.marching_cubes_lewiner
, according siva's and Lucan's answer here: https://stackoverflow.com/questions/54056565/attributeerror-module-skimage-measure-has-no-attribute-marching-cubesAfter this modification, the code ran successfully, and the heart rendered beautifully. Thank you so much again!