fork download
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from matplotlib.animation import FuncAnimation
  4. from matplotlib.widgets import Button
  5. from mpl_toolkits.mplot3d import Axes3D
  6.  
  7. # Set up the figure and axis
  8. fig = plt.figure(figsize=(8, 8))
  9. ax = fig.add_subplot(111, projection='3d')
  10.  
  11. # Initial settings
  12. initial_radius = 5 # Initial radius of the sphere
  13. num_galaxies = 20 # Number of other galaxies
  14.  
  15. # Generate random spherical coordinates for galaxies
  16. phi = np.random.uniform(0, 2 * np.pi, num_galaxies)
  17. theta = np.random.uniform(0, np.pi, num_galaxies)
  18. radii = np.random.uniform(0, initial_radius, num_galaxies)
  19.  
  20. # Convert spherical coordinates to Cartesian coordinates
  21. x = radii * np.sin(theta) * np.cos(phi)
  22. y = radii * np.sin(theta) * np.sin(phi)
  23. z = radii * np.cos(theta)
  24. galaxy_positions = np.column_stack((x, y, z))
  25.  
  26. # Scatter the galaxies
  27. galaxies_scatter = ax.scatter(galaxy_positions[:, 0], galaxy_positions[:, 1], galaxy_positions[:, 2],
  28. color='red', s=50, zorder=3)
  29. ax.scatter(0, 0, 0, color='black', zorder=4) # Home galaxy in the center
  30.  
  31. # Initialize traces (lines) for each galaxy
  32. galaxy_traces = []
  33. for i in range(num_galaxies):
  34. trace, = ax.plot([], [], [], 'r--', lw=1, alpha=0.7) # Dotted red lines for traces
  35. galaxy_traces.append(trace)
  36.  
  37. # Set fixed plot limits and title
  38. ax.set_xlim(-initial_radius * 2, initial_radius * 2)
  39. ax.set_ylim(-initial_radius * 2, initial_radius * 2)
  40. ax.set_zlim(-initial_radius * 2, initial_radius * 2)
  41. ax.set_title("Hubble's Law Simulation in 3D (Expanding Universe with Traces)")
  42.  
  43. # Initialize sphere plot
  44. sphere_patch = None
  45.  
  46. # Define the update function for the animation
  47. def update(frame):
  48. global sphere_patch
  49.  
  50. # Stretch the sphere (radius grows)
  51. new_radius = initial_radius + frame * (initial_radius / 100)
  52.  
  53. # Remove the previous sphere if it exists
  54. if sphere_patch is not None:
  55. sphere_patch.remove()
  56.  
  57. # Draw the new sphere
  58. u = np.linspace(0, 2 * np.pi, 100)
  59. v = np.linspace(0, np.pi, 100)
  60. X = new_radius * np.outer(np.cos(u), np.sin(v))
  61. Y = new_radius * np.outer(np.sin(u), np.sin(v))
  62. Z = new_radius * np.outer(np.ones(np.size(u)), np.cos(v))
  63. sphere_patch = ax.plot_surface(X, Y, Z, color='lightblue', alpha=0.2, edgecolor='none')
  64.  
  65. # Move the galaxies (except the home galaxy) with the expansion
  66. new_positions = galaxy_positions * (1 + frame / 100)
  67. galaxies_scatter._offsets3d = (new_positions[:, 0], new_positions[:, 1], new_positions[:, 2])
  68.  
  69. # Update the traces for each galaxy
  70. for i, trace in enumerate(galaxy_traces):
  71. trace.set_data([0, new_positions[i, 0]], [0, new_positions[i, 1]])
  72. trace.set_3d_properties([0, new_positions[i, 2]])
  73.  
  74. # Create the animation
  75. anim = FuncAnimation(fig, update, frames=101, interval=50)
  76.  
  77. # Pause/play button callback function
  78. is_paused = False
  79.  
  80. def toggle_pause(event):
  81. global is_paused
  82. if is_paused:
  83. anim.event_source.start()
  84. button.label.set_text('Pause')
  85. else:
  86. anim.event_source.stop()
  87. button.label.set_text('Play')
  88. is_paused = not is_paused
  89.  
  90. # Add the pause/play button
  91. ax_button = plt.axes([0.4, 0.05, 0.2, 0.075]) # Position of the button
  92. button = Button(ax_button, 'Pause')
  93. button.on_clicked(toggle_pause)
  94.  
  95. plt.show()
  96.  
Success #stdin #stdout #stderr 2.16s 57988KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
/usr/local/lib/python3.9/dist-packages/matplotlib/animation.py:889: UserWarning: Animation was deleted without rendering anything. This is most likely not intended. To prevent deletion, assign the Animation to a variable, e.g. `anim`, that exists until you have outputted the Animation using `plt.show()` or `anim.save()`.