Spaces:
Paused
Paused
| #!/usr/bin/env python3 | |
| """ | |
| Validation script to compare Python implementation against OpenSCAD model. | |
| This script recreates key calculations from thefelix.md to ensure | |
| our Python implementation matches the geometric prototype. | |
| """ | |
| import math | |
| from src.core.helix_geometry import HelixGeometry | |
| def openscad_get_position(step, turns, segments_per_turn, height, top_radius, bottom_radius): | |
| """ | |
| Recreate the OpenSCAD get_position function for comparison. | |
| From thefelix.md: | |
| function get_position(step, p_turns, p_segs, p_h, p_t_rad, p_b_rad) = let( | |
| total_steps = p_turns * p_segs, | |
| angle = step / total_steps * p_turns * 360, | |
| z = step / total_steps * p_h, | |
| r = p_b_rad * pow(p_t_rad / p_b_rad, z / p_h), | |
| x = r * cos(angle), | |
| y = r * sin(angle) | |
| ) [x, y, z]; | |
| """ | |
| total_steps = turns * segments_per_turn | |
| angle = step / total_steps * turns * 360 # degrees | |
| z = step / total_steps * height | |
| r = bottom_radius * pow(top_radius / bottom_radius, z / height) | |
| x = r * math.cos(math.radians(angle)) | |
| y = r * math.sin(math.radians(angle)) | |
| return (x, y, z) | |
| def validate_implementation(): | |
| """Compare Python implementation against OpenSCAD calculations.""" | |
| # Parameters from thefelix.md | |
| top_radius = 33.0 | |
| bottom_radius = 0.001 | |
| height = 33.0 | |
| turns = 33 | |
| segments_per_turn = 33 | |
| # Create Python helix | |
| helix = HelixGeometry(top_radius, bottom_radius, height, turns) | |
| print("=== OpenSCAD vs Python Implementation Validation ===\n") | |
| # Test specific positions | |
| total_steps = turns * segments_per_turn | |
| test_steps = [0, total_steps // 4, total_steps // 2, 3 * total_steps // 4, total_steps - 1] | |
| print("Comparing positions at key points:") | |
| print("Step | t | OpenSCAD (x, y, z) | Python (x, y, z) | Max Diff | Debug") | |
| print("-" * 90) | |
| max_overall_diff = 0.0 | |
| for step in test_steps: | |
| # OpenSCAD calculation | |
| openscad_pos = openscad_get_position( | |
| step, turns, segments_per_turn, height, top_radius, bottom_radius | |
| ) | |
| # Python calculation - match the exact OpenSCAD conversion | |
| # OpenSCAD: t = step / total_steps, but we need step / (total_steps - 1) for discrete steps | |
| t_openscad = step / total_steps # This is what OpenSCAD actually uses | |
| python_pos = helix.get_position(t_openscad) | |
| # Calculate differences | |
| diff_x = abs(openscad_pos[0] - python_pos[0]) | |
| diff_y = abs(openscad_pos[1] - python_pos[1]) | |
| diff_z = abs(openscad_pos[2] - python_pos[2]) | |
| max_diff = max(diff_x, diff_y, diff_z) | |
| max_overall_diff = max(max_overall_diff, max_diff) | |
| # Debug info | |
| angle_openscad = step / total_steps * turns * 360 | |
| angle_python = t_openscad * turns * 360 | |
| print(f"{step:4d} | {t_openscad:.3f} | ({openscad_pos[0]:8.3f}, {openscad_pos[1]:8.3f}, {openscad_pos[2]:8.3f}) | " | |
| f"({python_pos[0]:8.3f}, {python_pos[1]:8.3f}, {python_pos[2]:8.3f}) | {max_diff:.2e} | " | |
| f"ang={angle_openscad:.1f}") | |
| print(f"\nMaximum overall difference: {max_overall_diff:.2e}") | |
| # Validation threshold - allow for floating point precision | |
| if max_overall_diff < 1e-6: | |
| print("✅ VALIDATION PASSED: Python implementation matches OpenSCAD model") | |
| return True | |
| else: | |
| print("❌ VALIDATION FAILED: Significant differences detected") | |
| return False | |
| def performance_baseline(): | |
| """Establish performance baseline for helix calculations.""" | |
| import time | |
| helix = HelixGeometry(33.0, 0.001, 33.0, 33) | |
| print("\n=== Performance Baseline ===") | |
| # Time single position calculation | |
| start_time = time.perf_counter() | |
| for i in range(10000): | |
| t = i / 9999.0 | |
| pos = helix.get_position(t) | |
| end_time = time.perf_counter() | |
| time_per_calc = (end_time - start_time) / 10000 | |
| print(f"Position calculation: {time_per_calc:.2e} seconds per call") | |
| print(f"Throughput: {1.0/time_per_calc:.0f} calculations per second") | |
| # Time arc length approximation | |
| start_time = time.perf_counter() | |
| arc_length = helix.approximate_arc_length(segments=1000) | |
| end_time = time.perf_counter() | |
| print(f"Arc length calculation (1000 segments): {end_time - start_time:.3f} seconds") | |
| print(f"Total helix arc length: {arc_length:.1f} units") | |
| if __name__ == "__main__": | |
| # Run validation | |
| validation_passed = validate_implementation() | |
| # Run performance baseline | |
| performance_baseline() | |
| # Summary | |
| print(f"\n=== Validation Summary ===") | |
| if validation_passed: | |
| print("Core helix mathematics implementation is VALIDATED ✅") | |
| print("Ready to proceed with agent system implementation.") | |
| else: | |
| print("Validation FAILED - implementation needs correction ❌") |