TIER 4 · COMPLEX GEOMETRY·t4_04

A helical compression spring: 20mm outer diameter, 1.5mm wire diameter, 10 active coils, 50mm free length, with flat ground ends.

Claude Opus 4.6Zoo ML-ephantGemini 2.5 FlashGPT-5Text2CadQuery (Qwen 3B)
3D RENDER · Claude Opus 4.6
CADQUERY (PYTHON)SOURCE
✓ executed
import cadquery as cq
import math

# Spring parameters
outer_diameter = 20.0  # mm
wire_diameter = 1.5  # mm
active_coils = 10
free_length = 50.0  # mm
mean_diameter = outer_diameter - wire_diameter
mean_radius = mean_diameter / 2.0

# Flat ground ends: typically 1 dead coil at each end (ground flat)
dead_coils_per_end = 1.0
total_coils = active_coils + 2 * dead_coils_per_end  # 12 total coils

# Pitch for active coils
# The dead coils at each end have zero pitch (flat)
# Total height = dead_end_height_bottom + active_height + dead_end_height_top
# For ground ends, the dead coils are compressed (pitch ~ 0) and ground flat
# Free length = active_coils * pitch + 2 * wire_diameter (approx for flat ends)
pitch = (free_length - 2 * wire_diameter) / active_coils

# Build the helix as a swept circle along a helical path
# We'll create the path using points along the helix
# Break into segments: bottom dead coil + active coils + top dead coil

segments_per_coil = 60  # points per coil for smoothness

# Build the helical spine points
points = []

# Bottom dead coil (ground flat - no rise, 1 coil)
n_bottom = int(dead_coils_per_end * segments_per_coil)
for i in range(n_bottom + 1):
    t = i / segments_per_coil  # fraction of coil
    angle = 2 * math.pi * t
    x = mean_radius * math.cos(angle)
    y = mean_radius * math.sin(angle)
    # Gradual transition: start at z = wire_diameter/2 (ground flat sits at z=0)
    z = wire_diameter / 2.0  # flat at bottom
    points.append((x, y, z))

# Active coils (with pitch)
z_start = wire_diameter / 2.0
n_active = int(active_coils * segments_per_coil)
for i in range(1, n_active + 1):
    t = i / segments_per_coil  # fraction of coil
    angle = 2 * math.pi * (dead_coils_per_end + t)
    x = mean_radius * math.cos(angle)
    y = mean_radius * math.sin(angle)
    z = z_start + (t / active_coils) * (active_coils * pitch)
    points.append((x, y, z))

# Top dead coil (ground flat - no rise, 1 coil)
z_top = z_start + active_coils * pitch
n_top = int(dead_coils_per_end * segments_per_coil)
for i in range(1, n_top + 1):
    t = i / segments_per_coil
    angle = 2 * math.pi * (dead_coils_per_end + active_coils + t)
    x = mean_radius * math.cos(angle)
    y = mean_radius * math.sin(angle)
    z = z_top + wire_diameter / 2.0 - wire_diameter / 2.0  # flat at top
    z = z_top
    points.append((x, y, z))

# Add transition zones: smooth the transition from flat to helical
# Re-build with proper transitions
points = []
transition_coils = 0.5  # half coil for transition

total_segments = int(total_coils * segments_per_coil)
for i in range(total_segments + 1):
    coil_pos = i / segments_per_coil  # position in coils from start
    angle = 2 * math.pi * coil_pos
    x = mean_radius * math.cos(angle)
    y = mean_radius * math.sin(angle)
    
    # Calculate z based on position
    if coil_pos <= dead_coils_per_end:
        # Bottom dead coil - flat
        z = wire_diameter / 2.0
    elif coil_pos >= (total_coils - dead_coils_per_end):
        # Top dead coil - flat
        z = wire_diameter / 2.0 + active_coils * pitch
    else:
        # Active region
        active_pos = coil_pos - dead_coils_per_end
        z = wire_diameter / 2.0 + active_pos * pitch
    
    points.append((x, y, z))

# Create the helix path as a spline
path = cq.Workplane("XZ").spline(points)

# Create the wire cross-section at the start of the path
# Position the circle at the first point, perpendicular to the path
start_point = points[0]
next_point = points[1]
tangent = (next_point[0] - start_point[0], next_point[1] - start_point[1], next_point[2] - start_point[2])

# Sweep a circle along the helical path
result = (
    cq.Workplane("XY")
    .center(start_point[0], start_point[1])
    .workplane(offset=start_point[2])
    .circle(wire_diameter / 2.0)
    .sweep(path, isFrenet=True)
)
COMPARE · SAME PROMPT
Zoo ML-ephant
Timeout after 120s (job_id=f131e1bc-3dc3-4b77-8430-b0b8abb97
Gemini 2.5 Flash
No variable named 'result' found after exec()
GPT-5
no output
Text2CadQuery (Qwen 3B)
No variable named 'result' found after exec()