Spaces:
Sleeping
Sleeping
File size: 4,371 Bytes
e0ef700 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
#!/usr/bin/env python3
"""Test geometric realization with correct angle scaling."""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
import numpy as np
from ideal_poly_volume_toolkit.plantri_interface import find_plantri_executable
from ideal_poly_volume_toolkit.planar_utils import extract_faces_from_planar_embedding
from ideal_poly_volume_toolkit.rivin_delaunay import (
check_delaunay_realizability,
realize_angles_as_points,
compute_triangle_angle
)
import subprocess
def get_octahedron():
"""Get the octahedron triangulation."""
plantri = find_plantri_executable()
args = [plantri, '-pc3', '-a', '6']
result = subprocess.run(args, capture_output=True, text=True)
triangulations = []
for line in result.stdout.split('\n'):
line = line.strip()
if not line or line.startswith('>'):
continue
parts = line.split(maxsplit=1)
if len(parts) != 2:
continue
n = int(parts[0])
adj_str = parts[1]
adj = {}
for v_idx, neighbor_str in enumerate(adj_str.split(',')):
neighbors = [ord(c) - ord('a') for c in neighbor_str]
adj[v_idx] = neighbors
closed_tri = extract_faces_from_planar_embedding(n, adj)
planar_tri = [tri for tri in closed_tri if 0 not in tri]
if planar_tri:
triangulations.append(planar_tri)
return triangulations[6] # The octahedron
if __name__ == '__main__':
triangles = get_octahedron()
print("="*70)
print("OCTAHEDRON GEOMETRIC REALIZATION (WITH CORRECT SCALING)")
print("="*70)
print(f"\nTriangles: {triangles}")
# Check strict realizability
result = check_delaunay_realizability(triangles, verbose=False, strict=True)
print(f"\nRealizability: {result['realizable']}")
# Extract angles from LP (in scaled units where π = 1)
angles_scaled = result['angles']
n_triangles = len(triangles)
# FIX: Convert from scaled units to radians
angles_radians = angles_scaled * np.pi
target_angles = angles_radians.reshape((n_triangles, 3))
print(f"\nLP angles (scaled, sum=1): {angles_scaled.reshape((n_triangles, 3))}")
print(f"LP angles (radians, sum=π): {target_angles}")
print(f"LP angles (degrees): {np.degrees(target_angles)}")
# Geometric realization
print(f"\n{'='*70}")
print("GEOMETRIC REALIZATION")
print(f"{'='*70}")
realization = realize_angles_as_points(triangles, target_angles, verbose=True)
if realization['success']:
print(f"\n✓ SUCCESS!")
print(f"Angle error (RMS): {realization.get('angle_error', 0):.6e} rad")
print(f"Angle error (degrees): {realization.get('angle_error_degrees', 0):.6f}°")
print(f"Triangulation preserved: {realization.get('triangulation_preserved', False)}")
points = realization['points']
vertex_list = realization['vertex_list']
vertex_to_idx = {v: i for i, v in enumerate(vertex_list)}
print(f"\nPoint positions:")
for i, v in enumerate(vertex_list):
print(f" v{v}: ({points[i, 0]:8.5f}, {points[i, 1]:8.5f})")
# Verify angles
print(f"\n{'='*70}")
print("VERIFICATION: Target vs Actual Angles")
print(f"{'='*70}")
total_error = 0.0
for i, tri in enumerate(triangles):
v0, v1, v2 = tri
p0 = points[vertex_to_idx[v0]]
p1 = points[vertex_to_idx[v1]]
p2 = points[vertex_to_idx[v2]]
angle0 = compute_triangle_angle(p0, p1, p2)
angle1 = compute_triangle_angle(p1, p2, p0)
angle2 = compute_triangle_angle(p2, p0, p1)
actual = np.array([angle0, angle1, angle2])
error = np.abs(target_angles[i] - actual)
total_error += np.sum(error**2)
print(f"\nTriangle {i}: {tri}")
print(f" Target (deg): {np.degrees(target_angles[i])}")
print(f" Actual (deg): {np.degrees(actual)}")
print(f" Error (deg): {np.degrees(error)}")
rms_error = np.sqrt(total_error / (n_triangles * 3))
print(f"\nOverall RMS error: {rms_error:.6e} rad = {np.degrees(rms_error):.6f}°")
else:
print(f"\n✗ FAILED")
print(f"Message: {realization.get('message', 'Unknown')}")
|