idealpolyhedra / examples /visualization /visualize_sphere_projection.py
igriv's picture
Major reorganization and feature additions
d7d27f0
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from ideal_poly_volume_toolkit.geometry import lift_to_sphere_with_inf
from scipy.spatial import ConvexHull
# The golden ratio configuration
phi = (1 + np.sqrt(5)) / 2
z_points = np.array([
0 + 0j, # z[0]
1 + 0j, # z[1]
2.6180 + 0j, # z[2] β‰ˆ φ²
0.5 - 1.5388j, # z[3]
2.8917 - 2.6037j, # z[4]
0.5 + 1.5388j, # z[5]
-1.6180 + 0j # z[6] β‰ˆ -Ο†
])
# Add infinity point for sphere projection
z_with_inf = np.append(z_points, [np.inf])
sphere_points = lift_to_sphere_with_inf(z_with_inf)
print("Sphere points:")
for i, p in enumerate(sphere_points):
if i < 7:
print(f" z[{i}] β†’ ({p[0]:.4f}, {p[1]:.4f}, {p[2]:.4f})")
else:
print(f" ∞ β†’ ({p[0]:.4f}, {p[1]:.4f}, {p[2]:.4f}) [North pole]")
# Create 3D plot
fig = plt.figure(figsize=(12, 10))
ax = fig.add_subplot(111, projection='3d')
# Plot points
colors = ['red'] * 7 + ['blue'] # Different color for infinity
ax.scatter(sphere_points[:, 0], sphere_points[:, 1], sphere_points[:, 2],
s=200, c=colors, depthshade=False, edgecolors='black', linewidth=2)
# Label points
labels = [f'z[{i}]' for i in range(7)] + ['∞']
for i, (point, label) in enumerate(zip(sphere_points, labels)):
ax.text(point[0]*1.1, point[1]*1.1, point[2]*1.1, label, fontsize=10)
# Try to construct the convex hull on the sphere
# This will give us the ideal polyhedron
try:
hull = ConvexHull(sphere_points)
# Plot the faces
for simplex in hull.simplices:
# Get the three vertices of each triangular face
triangle = sphere_points[simplex]
# Close the triangle
triangle = np.vstack([triangle, triangle[0]])
ax.plot(triangle[:, 0], triangle[:, 1], triangle[:, 2], 'b-', linewidth=1.5)
print(f"\nConvex hull has {len(hull.simplices)} faces")
print("Faces (as vertex indices):")
for i, face in enumerate(hull.simplices):
print(f" Face {i}: {face}")
except Exception as e:
print(f"\nCouldn't compute convex hull: {e}")
print("Drawing edges manually based on Delaunay triangulation...")
# Fall back to drawing edges from Delaunay triangulation
from ideal_poly_volume_toolkit.geometry import delaunay_triangulation_indices
triangles = delaunay_triangulation_indices(z_points)
edges_drawn = set()
for tri in triangles:
for i in range(3):
j = (i + 1) % 3
edge = tuple(sorted([tri[i], tri[j]]))
if edge not in edges_drawn:
edges_drawn.add(edge)
p1 = sphere_points[edge[0]]
p2 = sphere_points[edge[1]]
ax.plot([p1[0], p2[0]], [p1[1], p2[1]], [p1[2], p2[2]],
'b-', linewidth=1.5)
# Connect boundary vertices to infinity
real_coords = z_points.real
imag_coords = z_points.imag
hull_2d = ConvexHull(np.column_stack([real_coords, imag_coords]))
for vertex_idx in hull_2d.vertices:
p1 = sphere_points[vertex_idx]
p2 = sphere_points[7] # infinity
ax.plot([p1[0], p2[0]], [p1[1], p2[1]], [p1[2], p2[2]],
'g-', linewidth=1.5, alpha=0.7)
# Draw unit sphere wireframe
u = np.linspace(0, 2 * np.pi, 20)
v = np.linspace(0, np.pi, 20)
x_sphere = np.outer(np.cos(u), np.sin(v))
y_sphere = np.outer(np.sin(u), np.sin(v))
z_sphere = np.outer(np.ones(np.size(u)), np.cos(v))
ax.plot_wireframe(x_sphere, y_sphere, z_sphere, alpha=0.1, color='gray', linewidth=0.5)
# Add equator and meridians
theta = np.linspace(0, 2*np.pi, 100)
ax.plot(np.cos(theta), np.sin(theta), np.zeros_like(theta), 'k-', alpha=0.3, linewidth=1)
ax.plot([0, 0], [-1, 1], [0, 0], 'k-', alpha=0.3, linewidth=1)
ax.plot([-1, 1], [0, 0], [0, 0], 'k-', alpha=0.3, linewidth=1)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Golden Ratio Configuration\nProjected onto Unit Sphere', fontsize=16)
# Set equal aspect ratio and nice viewing angle
ax.set_box_aspect([1,1,1])
ax.view_init(elev=20, azim=45)
# Set axis limits
ax.set_xlim([-1.2, 1.2])
ax.set_ylim([-1.2, 1.2])
ax.set_zlim([-1.2, 1.2])
plt.tight_layout()
plt.savefig('golden_config_sphere.png', dpi=150, bbox_inches='tight')
print("\nSaved: golden_config_sphere.png")
plt.close()