File size: 4,966 Bytes
fb867c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
131
132
133
134
135
136
137
138
139
#!/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 ❌")