vibe-openscad

tier-2-offset-handle-mug / claude-sonnet-4-6

8 run / 累計 371.3s / 累計 $0.3152

claude sonnet 4.6 bare

bare (provider default effort)

run detail →
render
bare render of tier-2-offset-handle-mug
loading STL…
success 57.7s · 330/3816t · $0.0582
SCAD (224 lines)
// Mug with handle on +X side

// Parameters
outer_r = 40;       // outer radius = 80mm diameter
inner_r = 35;       // inner radius = 70mm diameter
mug_h   = 90;       // mug height
bot_t   = 6;        // bottom thickness

// Handle parameters
// Inner space: height 30mm, width 25mm
// Handle cross-section tube radius
tube_r  = 3.5;      // handle tube cross-section radius (wall thickness ~3.5mm)

// The handle is a D-shape torus arc on +X side
// Center of the D arc is at x = outer_r (on the mug surface)
// The arc spans 180 degrees (semicircle) facing +X
// Handle inner space: 30mm tall, 25mm wide
// So the arc center is at the mug outer surface, and the loop extends outward

h_space_h = 30;     // inner height of handle space
h_space_w = 25;     // inner width of handle space

// The handle loop:
// Two vertical bars connect at y=0 plane (on +X side of mug)
// separated by h_space_h in Z, centered at mug mid-height
// The outer D-curve has radius = h_space_w / 2 + outer connection offset

// Handle center Z position
handle_z = mug_h / 2;

// The handle consists of:
// 1. A swept D-shape path
// We model the handle as a rotate_extrude arc + two connection bars

// Arc radius for the outer D:
// inner space width = 25mm, tube diameter = 2*tube_r = 7mm
// arc center at x = outer_r (mug surface), arc inner radius ≈ h_space_w/2
// arc center offset from mug axis:
arc_cx = outer_r;  // arc center x (at mug outer surface level)
arc_r  = h_space_w / 2 + tube_r;  // radius of arc centerline = 12.5 + 3.5 = 16

// Vertical bar half-height
bar_half = h_space_h / 2 + tube_r;  // = 18.5

module mug_body() {
    difference() {
        // Outer cylinder
        cylinder(r = outer_r, h = mug_h, center = false, $fn = 128);
        // Inner hollow (starts from bottom thickness)
        translate([0, 0, bot_t])
            cylinder(r = inner_r, h = mug_h - bot_t + 0.1, center = false, $fn = 128);
    }
}

module handle() {
    // The handle is on the +X side
    // It consists of:
    //   - Two vertical straight segments (bars) at x=outer_r, y=0,
    //     from z=handle_z-bar_half to z=handle_z+bar_half (but only the tube length)
    //   - A semicircular arc connecting them on the outside
    //   - The bars connect back into the mug body (embedded in mug wall)

    // We build the handle as:
    // A. Semicircular arc (rotate_extrude of 180 deg) at handle Z mid, but this is for
    //    a torus section — we need a 3D path sweep.
    // 
    // Instead, use hull-based approach for robustness:
    // Place spheres along the path and hull them, or use explicit geometry.
    //
    // Approach: 
    //   Top bar: cylinder from mug surface to arc top
    //   Bottom bar: cylinder from mug surface to arc bottom
    //   Outer arc: half torus (rotate_extrude 180 deg of circle translated)
    //   Connection blobs at joints

    // The arc is a half-torus:
    //   - centered at (arc_cx, 0, handle_z)  -- NO, the arc is in the XY plane per Z slice
    //   - Actually we want a half-torus in the XZ plane... 
    //
    // Let me think differently:
    // The D-handle lives in the XZ plane (y≈0 plane, extended in X and Z).
    // The cross-section of the handle tube is a circle of radius tube_r.
    // The path of the handle centerline is:
    //   - Vertical segment: x=outer_r, y=0, z from (handle_z - h_space_h/2) to (handle_z + h_space_h/2)
    //     But this segment is INSIDE the mug wall — the actual visible bars are from x=outer_r outward
    //   Actually the path:
    //   Bottom attachment: (outer_r, 0, handle_z - h_space_h/2)
    //   Top attachment:    (outer_r, 0, handle_z + h_space_h/2)
    //   Outer arc: semicircle of radius arc_r centered at (outer_r, 0) in XY... 
    //   No — centered at (outer_r, 0, handle_z) sweeping in XZ plane

    // The centerline of the handle:
    // Start: (outer_r, 0, handle_z - h_space_h/2)
    // Go to:  semicircle in the XZ plane around center (outer_r, 0, handle_z)
    //         with radius = h_space_h/2, from bottom to top, bulging in +X direction
    // Wait, that would make the arc radius = h_space_h/2 = 15mm, width = 15mm not 25mm

    // Let me redefine:
    // The handle path in the plane y=0:
    //   Bottom point: A = (outer_r, 0, handle_z - h_space_h/2)
    //   Top point:    B = (outer_r, 0, handle_z + h_space_h/2)
    //   The outer arc connects A to B going through +X
    //   Arc center: C = (outer_r, 0, handle_z)
    //   Arc radius in XZ plane: the arc must reach x = outer_r + h_space_w at midpoint
    //   So arc radius = h_space_w = 25mm (from C to the rightmost point)
    //   But then the arc from C to A has length sqrt(h_space_w^2 + (h_space_h/2)^2) ≠ h_space_w
    //   
    //   For a true semicircle: arc_radius = sqrt((h_space_h/2)^2 + h_space_w^2) ... no
    //   
    //   Actually for D-shape: the straight part is the vertical line x=outer_r,
    //   and the curved part is a semicircle.
    //   For semicircle: diameter = h_space_h, so radius = h_space_h/2 = 15
    //   But then width = radius = 15mm, not 25mm.
    //   
    //   To get width=25 with height=30: use an ellipse, or use a larger arc.
    //   Let's use: arc center at (outer_r + h_space_w - arc_rad, 0, handle_z)
    //   where arc_rad is chosen so the arc passes through A and B and extends to x=outer_r+h_space_w
    //   
    //   Simplest: just use a circular arc where:
    //     - the two endpoints are at (outer_r, 0, handle_z ± h_space_h/2)
    //     - the arc bulges to x = outer_r + h_space_w at z = handle_z
    //   
    //   Arc center at (outer_r - d, 0, handle_z) for some d, radius R:
    //     R^2 = d^2 + (h_space_h/2)^2   [passes through endpoints]
    //     R = d + h_space_w              [reaches x = outer_r + h_space_w]
    //   So: (d + h_space_w)^2 = d^2 + (h_space_h/2)^2
    //       d^2 + 2*d*h_space_w + h_space_w^2 = d^2 + (h_space_h/2)^2
    //       2*d*h_space_w = (h_space_h/2)^2 - h_space_w^2
    //       d = ((h_space_h/2)^2 - h_space_w^2) / (2*h_space_w)
    //       d = (225 - 625) / 50 = -400/50 = -8
    //   So d = -8, R = -8 + 25 = 17
    //   Arc center at (outer_r - (-8), 0, handle_z) = (outer_r + 8, 0, handle_z)
    //   Radius = 17mm
    //   Check: distance from center to endpoint = sqrt(8^2 + 15^2) = sqrt(64+225) = sqrt(289) = 17 ✓
    //   Rightmost point: center_x + R = outer_r + 8 + 17 = outer_r + 25 ✓

    arc_center_x = outer_r + 8;
    arc_center_z = handle_z;
    arc_radius = 17;

    // Angle of endpoints from arc center:
    // endpoint is at (outer_r, handle_z ± h_space_h/2) relative to arc center at (outer_r+8, handle_z)
    // vector from arc_center to bottom endpoint: (-8, -15) in (x,z)
    // angle = atan2(-15, -8) ... but we want angle from +X axis in XZ plane
    // angle_bottom = atan2(-(h_space_h/2), -8) measured from +X of arc
    // In standard: angle from +X axis: atan2(z_component, x_component)
    // bottom endpoint relative to arc center: dx = outer_r - arc_center_x = -8, dz = -15
    // angle_bottom (from +X, CCW in XZ) = atan2(-15, -8) ≈ 180+61.9 = -118.1° or 241.9°
    // top endpoint: dx=-8, dz=+15 → angle_top = atan2(15,-8) ≈ 180-61.9 = 118.1°
    // 
    // The arc from bottom to top going through +X (rightmost point at angle=0):
    // from angle_bottom to angle_top going through 0°
    // That's from -118.1° to +118.1° (total arc = 236.2°) ... that's more than semicircle
    // Hmm, let me reconsider.
    
    // Actually the arc should only be the outer curved part (not enclosing the full D).
    // The D shape: straight vertical line on left (at x=outer_r), arc on right.
    // The arc goes from bottom-right to top-right of the straight line, curving outward.
    
    // Let me just build the handle with linear_extrude / hull approach for simplicity.
    
    // SIMPLIFIED APPROACH using hull of cylinders:
    // We'll create the handle cross-section as a tube (hollow) but since we're doing union
    // with the mug, we just need the solid handle shape.
    
    // Build handle as solid D-ring using rotate_extrude trick won't work for D in XZ plane.
    
    // Use polygon + rotate approach:
    // The handle sweep path is in the XZ plane (y=0).
    // Cross section is a circle of radius tube_r.
    // We approximate the handle as a series of hull() segments.
    
    // Let's use N segments for the arc
    N = 32;
    // arc from angle_start to angle_end (in degrees, in XZ plane, 0=+X, 90=+Z)
    a_bottom = atan2(-(h_space_h/2), -8);  // ≈ -118.07°  → let's use 180+atan2(15,8)
    a_top    = atan2( (h_space_h/2), -8);  // ≈  118.07°

    // Going from a_bottom to a_top through 0° (i.e., through +X direction)
    // a_bottom ≈ -118.07, a_top ≈ 118.07
    // sweep from -118.07 to 118.07 through 0 (the short way going via 0)
    
    a_start = atan2(-(h_space_h/2), -(arc_center_x - outer_r));
    a_end   = atan2( (h_space_h/2), -(arc_center_x - outer_r));
    
    // Build the arc as union of hull'd sphere-pairs
    union() {
        // Arc segments
        for (i = [0:N-1]) {
            a1 = a_start + (a_end - a_start) * i / N;
            a2 = a_start + (a_end - a_start) * (i+1) / N;
            x1 = arc_center_x + arc_radius * cos(a1);
            z1 = arc_center_z + arc_radius * sin(a1);
            x2 = arc_center_x + arc_radius * cos(a2);
            z2 = arc_center_z + arc_radius * sin(a2);
            hull() {
                translate([x1, 0, z1]) sphere(r = tube_r, $fn = 16);
                translate([x2, 0, z2]) sphere(r = tube_r, $fn = 16);
            }
        }
        // Bottom vertical bar: from mug axis connection to arc bottom endpoint
        // bottom arc endpoint:
        bot_x = arc_center_x + arc_radius * cos(a_start);
        bot_z = arc_center_z + arc_radius * sin(a_start);
        top_x = arc_center_x + arc_radius * cos(a_end);
        top_z = arc_center_z + arc_radius * sin(a_end);
        // Connect bottom endpoint to mug surface (embed into mug wall)
        hull() {
            translate([bot_x, 0, bot_z]) sphere(r = tube_r, $fn = 16);
            translate([outer_r - tube_r, 0, bot_z]) sphere(r = tube_r, $fn = 16);
        }
        // Connect top endpoint to mug surface
        hull() {
            translate([top_x, 0, top_z]) sphere(r = tube_r, $fn = 16);
            translate([outer_r - tube_r, 0, top_z]) sphere(r = tube_r, $fn = 16);
        }
    }
}

// Main model
union() {
    mug_body();
    handle();
}
パラメータ (7)
スライダを動かすと openscad-wasm で再レンダリング

prompt

OpenSCAD で、向きが指定されたマグカップを作ってください。

本体:
- 外径 80mm、内径 70mm(肉厚 5mm)、高さ 90mm の円筒形マグ
- 底面の厚みは 6mm
- 内側は飲み物を入れられるよう中空

取手(handle):
- マグの **+X 軸方向の側面のみ** に付ける(他の方向には付けない)
- 取手は D 字形状(外側が半円、本体側が直線)で、本体外周にしっかり接続する
- 取手の内側の空間は高さ 30mm × 幅 25mm(指 3 本ぐらい入る)
- 取手はマグの高さ方向の中央付近に付ける
- 本体と取手は確実に union され、マニフォールド(隙間や宙吊りなし)を保つ

完成したコード全体を ```openscad ... ``` のフェンスで囲んで出力してください。コードのみで、追加の説明は不要です。

variant: effort

low success
low
11.8s · 330/826t · $0.0134
SCAD (83 lines)
// Mug with handle on +X side

$fn = 128;

// Body dimensions
outer_r = 40;
inner_r = 35;
height = 90;
bottom_thick = 6;

// Handle dimensions
handle_inner_h = 30;
handle_inner_w = 25;
handle_thick = 5;

module mug_body() {
    difference() {
        cylinder(r = outer_r, h = height);
        translate([0, 0, bottom_thick])
            cylinder(r = inner_r, h = height);
    }
}

module handle() {
    // The handle is a D-shape on the +X side
    // Inner space: 30mm tall x 25mm wide
    // Handle tube thickness: 5mm
    
    // Center height of mug
    center_z = height / 2;
    
    // The handle spans from outer surface outward
    // Inner cavity width (in X) = handle_inner_w = 25
    // Inner cavity height (in Z) = handle_inner_h = 30
    
    // Outer radius of the D arc
    // The arc center is at x = outer_r (on the mug surface)
    // Inner radius of arc = handle_inner_w / 2 = 12.5
    // Outer radius of arc = inner + thick = 17.5
    
    arc_inner_r = handle_inner_w / 2;
    arc_outer_r = arc_inner_r + handle_thick;
    
    bar_half_h = handle_inner_h / 2;
    
    translate([0, 0, center_z]) {
        difference() {
            union() {
                // Outer D torus half (semicircle, +X side)
                // Rotate_extrude only +X half
                intersection() {
                    rotate_extrude(angle = 360)
                        translate([outer_r + arc_inner_r, 0, 0])
                            circle(r = arc_outer_r);
                    translate([outer_r, -500, -500])
                        cube([1000, 1000, 1000]);
                }
                // Top bar
                translate([outer_r, -arc_outer_r, bar_half_h])
                    cube([arc_inner_r, arc_outer_r * 2, handle_thick]);
                // Bottom bar
                translate([outer_r, -arc_outer_r, -bar_half_h - handle_thick])
                    cube([arc_inner_r, arc_outer_r * 2, handle_thick]);
            }
            // Hollow inner arc
            intersection() {
                rotate_extrude(angle = 360)
                    translate([outer_r + arc_inner_r, 0, 0])
                        circle(r = arc_inner_r);
                translate([outer_r, -500, -500])
                    cube([1000, 1000, 1000]);
            }
            // Remove inner space between bars
            translate([outer_r, -arc_inner_r, -bar_half_h])
                cube([arc_inner_r + arc_outer_r, arc_inner_r * 2, handle_inner_h]);
        }
    }
}

union() {
    mug_body();
    handle();
}
mediumnot run
high (default) no_code nocode
no_code
67.3s · 330/4096t · $0.0624
no SCAD code block in response (stopReason=max_tokens)
SCAD (1 lines)

no SCAD

maxnot run
xhighnot run

variant: thinking

off no_code nocode
no_code
67.3s · 330/4096t · $0.0624
no SCAD code block in response (stopReason=max_tokens)
SCAD (1 lines)

no SCAD

adaptive (default) success
adaptive
11.8s · 330/826t · $0.0134
SCAD (83 lines)
// Mug with handle on +X side

$fn = 128;

// Body dimensions
outer_r = 40;
inner_r = 35;
height = 90;
bottom_thick = 6;

// Handle dimensions
handle_inner_h = 30;
handle_inner_w = 25;
handle_thick = 5;

module mug_body() {
    difference() {
        cylinder(r = outer_r, h = height);
        translate([0, 0, bottom_thick])
            cylinder(r = inner_r, h = height);
    }
}

module handle() {
    // The handle is a D-shape on the +X side
    // Inner space: 30mm tall x 25mm wide
    // Handle tube thickness: 5mm
    
    // Center height of mug
    center_z = height / 2;
    
    // The handle spans from outer surface outward
    // Inner cavity width (in X) = handle_inner_w = 25
    // Inner cavity height (in Z) = handle_inner_h = 30
    
    // Outer radius of the D arc
    // The arc center is at x = outer_r (on the mug surface)
    // Inner radius of arc = handle_inner_w / 2 = 12.5
    // Outer radius of arc = inner + thick = 17.5
    
    arc_inner_r = handle_inner_w / 2;
    arc_outer_r = arc_inner_r + handle_thick;
    
    bar_half_h = handle_inner_h / 2;
    
    translate([0, 0, center_z]) {
        difference() {
            union() {
                // Outer D torus half (semicircle, +X side)
                // Rotate_extrude only +X half
                intersection() {
                    rotate_extrude(angle = 360)
                        translate([outer_r + arc_inner_r, 0, 0])
                            circle(r = arc_outer_r);
                    translate([outer_r, -500, -500])
                        cube([1000, 1000, 1000]);
                }
                // Top bar
                translate([outer_r, -arc_outer_r, bar_half_h])
                    cube([arc_inner_r, arc_outer_r * 2, handle_thick]);
                // Bottom bar
                translate([outer_r, -arc_outer_r, -bar_half_h - handle_thick])
                    cube([arc_inner_r, arc_outer_r * 2, handle_thick]);
            }
            // Hollow inner arc
            intersection() {
                rotate_extrude(angle = 360)
                    translate([outer_r + arc_inner_r, 0, 0])
                        circle(r = arc_inner_r);
                translate([outer_r, -500, -500])
                    cube([1000, 1000, 1000]);
            }
            // Remove inner space between bars
            translate([outer_r, -arc_inner_r, -bar_half_h])
                cube([arc_inner_r + arc_outer_r, arc_inner_r * 2, handle_inner_h]);
        }
    }
}

union() {
    mug_body();
    handle();
}
dynamicnot run

iteration: iter-png

i1 success
iter 1
106.2s · 4902/1881t · $0.0429
diff vs bare: +88/-196
  // Mug with handle on +X side
+ // Body: outer_r=40, inner_r=35, height=90, bottom=6mm
+ // Handle: inner space 30mm(H) x 25mm(W), on +X side, centered at mug mid-height
  
- // Parameters
- outer_r = 40;       // outer radius = 80mm diameter
- inner_r = 35;       // inner radius = 70mm diameter
- mug_h   = 90;       // mug height
- bot_t   = 6;        // bottom thickness
+ $fn = 128;
  
- // Handle parameters
- // Inner space: height 30mm, width 25mm
- // Handle cross-section tube radius
- tube_r  = 3.5;      // handle tube cross-section radius (wall thickness ~3.5mm)
+ outer_r = 40;
+ inner_r = 35;
+ mug_h   = 90;
+ bot_t   = 6;
  
- // The handle is a D-shape torus arc on +X side
- // Center of the D arc is at x = outer_r (on the mug surface)
- // The arc spans 180 degrees (semicircle) facing +X
- // Handle inner space: 30mm tall, 25mm wide
- // So the arc center is at the mug outer surface, and the loop extends outward
+ // Handle design
+ // Cross-section radius of handle tube
+ tube_r = 6;
  
- h_space_h = 30;     // inner height of handle space
- h_space_w = 25;     // inner width of handle space
+ // Inner clear space of handle: 30mm tall, 25mm wide
+ h_space_h = 30;
+ h_space_w  = 25;
  
- // The handle loop:
- // Two vertical bars connect at y=0 plane (on +X side of mug)
- // separated by h_space_h in Z, centered at mug mid-height
- // The outer D-curve has radius = h_space_w / 2 + outer connection offset
+ // Handle center Z
+ handle_z = mug_h / 2;  // = 45
  
- // Handle center Z position
- handle_z = mug_h / 2;
+ // The handle path (centerline) lies in the Y=0 plane.
+ // The straight (mug-side) portions run vertically at X = outer_r + tube_r,
+ // from Z = handle_z - h_space_h/2  to  Z = handle_z + h_space_h/2
+ // (embedded into the mug wall for solid union)
+ //
+ // The outer arc is a circular arc connecting the two vertical ends,
+ // bulging in the +X direction.
+ //
+ // Arc geometry:
+ //   Endpoints in XZ plane:
+ //     P_bot = (outer_r + tube_r,  handle_z - h_space_h/2)
+ //     P_top = (outer_r + tube_r,  handle_z + h_space_h/2)
+ //   The arc must extend to X = outer_r + tube_r + h_space_w at Z = handle_z.
+ //
+ //   Let arc center = (cx, handle_z).
+ //   R = cx - (outer_r + tube_r)   [rightmost reach]   → cx = outer_r + tube_r + R - h_space_w ... wait
+ //   R = (outer_r + tube_r + h_space_w) - cx
+ //   Also passes through P_bot:
+ //     R^2 = (outer_r + tube_r - cx)^2 + (h_space_h/2)^2
+ //   Let A = outer_r + tube_r, B = h_space_h/2 = 15, W = h_space_w = 25
+ //   R = (A + W) - cx  →  cx = A + W - R
+ //   R^2 = (A - cx)^2 + B^2
+ //       = (A - (A + W - R))^2 + B^2
+ //       = (R - W)^2 + B^2
+ //   R^2 = R^2 - 2RW + W^2 + B^2
+ //   0 = -2RW + W^2 + B^2
+ //   R = (W^2 + B^2) / (2W)
+ //     = (625 + 225) / 50 = 850/50 = 17
  
- // The handle consists of:
- // 1. A swept D-shape path
- // We model the handle as a rotate_extrude arc + two connection bars
+ arc_R  = (h_space_w*h_space_w + (h_space_h/2)*(h_space_h/2)) / (2*h_space_w);
+ // arc_R = 17
  
- // Arc radius for the outer D:
- // inner space width = 25mm, tube diameter = 2*tube_r = 7mm
- // arc center at x = outer_r (mug surface), arc inner radius ≈ h_space_w/2
- // arc center offset from mug axis:
- arc_cx = outer_r;  // arc center x (at mug outer surface level)
- arc_r  = h_space_w / 2 + tube_r;  // radius of arc centerline = 12.5 + 3.5 = 16
+ // Arc center X:
+ arc_cx = outer_r + tube_r + h_space_w - arc_R;
+ // = 40 + 6 + 25 - 17 = 54
  
- // Vertical bar half-height
- bar_half = h_space_h / 2 + tube_r;  // = 18.5
+ // Angles of endpoints from arc center (in XZ plane, measured from +X axis):
+ // P_bot relative to arc center: (outer_r+tube_r - arc_cx,  -(h_space_h/2))
+ //   dx = 46 - 54 = -8,  dz = -15
+ // P_top: dx=-8, dz=+15
+ a_bot = atan2(-(h_space_h/2), (outer_r + tube_r) - arc_cx);  // atan2(-15,-8) ≈ -118.07°
+ a_top = atan2( (h_space_h/2), (outer_r + tube_r) - arc_cx);  // atan2(+15,-8) ≈ +118.07°
+ // Arc sweeps from a_bot to a_top through 0° (+X direction)
  
- module mug_body() {
-     difference() {
-         // Outer cylinder
-         cylinder(r = outer_r, h = mug_h, center = false, $fn = 128);
-         // Inner hollow (starts from bottom thickness)
-         translate([0, 0, bot_t])
-             cylinder(r = inner_r, h = mug_h - bot_t + 0.1, center = false, $fn = 128);
-     }
- }
+ N_arc = 48;  // number of segments for arc
  
  module handle() {
-     // The handle is on the +X side
-     // It consists of:
-     //   - Two vertical straight segments (bars) at x=outer_r, y=0,
-     //     from z=handle_z-bar_half to z=handle_z+bar_half (but only the tube length)
-     //   - A semicircular arc connecting them on the outside
-     //   - The bars connect back into the mug body (embedded in mug wall)
- 
-     // We build the handle as:
-     // A. Semicircular arc (rotate_extrude of 180 deg) at handle Z mid, but this is for
-     //    a torus section — we need a 3D path sweep.
-     // 
-     // Instead, use hull-based approach for robustness:
-     // Place spheres along the path and hull them, or use explicit geometry.
-     //
-     // Approach: 
-     //   Top bar: cylinder from mug surface to arc top
-     //   Bottom bar: cylinder from mug surface to arc bottom
-     //   Outer arc: half torus (rotate_extrude 180 deg of circle translated)
-     //   Connection blobs at joints
- 
-     // The arc is a half-torus:
-     //   - centered at (arc_cx, 0, handle_z)  -- NO, the arc is in the XY plane per Z slice
-     //   - Actually we want a half-torus in the XZ plane... 
-     //
-     // Let me think differently:
-     // The D-handle lives in the XZ plane (y≈0 plane, extended in X and Z).
-     // The cross-section of the handle tube is a circle of radius tube_r.
-     // The path of the handle centerline is:
-     //   - Vertical segment: x=outer_r, y=0, z from (handle_z - h_space_h/2) to (handle_z + h_space_h/2)
-     //     But this segment is INSIDE the mug wall — the actual visible bars are from x=outer_r outward
-     //   Actually the path:
-     //   Bottom attachment: (outer_r, 0, handle_z - h_space_h/2)
-     //   Top attachment:    (outer_r, 0, handle_z + h_space_h/2)
-     //   Outer arc: semicircle of radius arc_r centered at (outer_r, 0) in XY... 
-     //   No — centered at (outer_r, 0, handle_z) sweeping in XZ plane
- 
-     // The centerline of the handle:
-     // Start: (outer_r, 0, handle_z - h_space_h/2)
-     // Go to:  semicircle in the XZ plane around center (outer_r, 0, handle_z)
-     //         with radius = h_space_h/2, from bottom to top, bulging in +X direction
-     // Wait, that would make the arc radius = h_space_h/2 = 15mm, width = 15mm not 25mm
- 
-     // Let me redefine:
-     // The handle path in the plane y=0:
-     //   Bottom point: A = (outer_r, 0, handle_z - h_space_h/2)
-     //   Top point:    B = (outer_r, 0, handle_z + h_space_h/2)
-     //   The outer arc connects A to B going through +X
-     //   Arc center: C = (outer_r, 0, handle_z)
-     //   Arc radius in XZ plane: the arc must reach x = outer_r + h_space_w at midpoint
-     //   So arc radius = h_space_w = 25mm (from C to the rightmost point)
-     //   But then the arc from C to A has length sqrt(h_space_w^2 + (h_space_h/2)^2) ≠ h_space_w
-     //   
-     //   For a true semicircle: arc_radius = sqrt((h_space_h/2)^2 + h_space_w^2) ... no
-     //   
-     //   Actually for D-shape: the straight part is the vertical line x=outer_r,
-     //   and the curved part is a semicircle.
-     //   For semicircle: diameter = h_space_h, so radius = h_space_h/2 = 15
-     //   But then width = radius = 15mm, not 25mm.
-     //   
-     //   To get width=25 with height=30: use an ellipse, or use a larger arc.
-     //   Let's use: arc center at (outer_r + h_space_w - arc_rad, 0, handle_z)
-     //   where arc_rad is chosen so the arc passes through A and B and extends to x=outer_r+h_space_w
-     //   
-     //   Simplest: just use a circular arc where:
-     //     - the two endpoints are at (outer_r, 0, handle_z ± h_space_h/2)
-     //     - the arc bulges to x = outer_r + h_space_w at z = handle_z
-     //   
-     //   Arc center at (outer_r - d, 0, handle_z) for some d, radius R:
-     //     R^2 = d^2 + (h_space_h/2)^2   [passes through endpoints]
-     //     R = d + h_space_w              [reaches x = outer_r + h_space_w]
-     //   So: (d + h_space_w)^2 = d^2 + (h_space_h/2)^2
-     //       d^2 + 2*d*h_space_w + h_space_w^2 = d^2 + (h_space_h/2)^2
-     //       2*d*h_space_w = (h_space_h/2)^2 - h_space_w^2
-     //       d = ((h_space_h/2)^2 - h_space_w^2) / (2*h_space_w)
-     //       d = (225 - 625) / 50 = -400/50 = -8
-     //   So d = -8, R = -8 + 25 = 17
-     //   Arc center at (outer_r - (-8), 0, handle_z) = (outer_r + 8, 0, handle_z)
-     //   Radius = 17mm
-     //   Check: distance from center to endpoint = sqrt(8^2 + 15^2) = sqrt(64+225) = sqrt(289) = 17 ✓
-     //   Rightmost point: center_x + R = outer_r + 8 + 17 = outer_r + 25 ✓
- 
-     arc_center_x = outer_r + 8;
-     arc_center_z = handle_z;
-     arc_radius = 17;
- 
-     // Angle of endpoints from arc center:
-     // endpoint is at (outer_r, handle_z ± h_space_h/2) relative to arc center at (outer_r+8, handle_z)
-     // vector from arc_center to bottom endpoint: (-8, -15) in (x,z)
-     // angle = atan2(-15, -8) ... but we want angle from +X axis in XZ plane
-     // angle_bottom = atan2(-(h_space_h/2), -8) measured from +X of arc
-     // In standard: angle from +X axis: atan2(z_component, x_component)
-     // bottom endpoint relative to arc center: dx = outer_r - arc_center_x = -8, dz = -15
-     // angle_bottom (from +X, CCW in XZ) = atan2(-15, -8) ≈ 180+61.9 = -118.1° or 241.9°
-     // top endpoint: dx=-8, dz=+15 → angle_top = atan2(15,-8) ≈ 180-61.9 = 118.1°
-     // 
-     // The arc from bottom to top going through +X (rightmost point at angle=0):
-     // from angle_bottom to angle_top going through 0°
-     // That's from -118.1° to +118.1° (total arc = 236.2°) ... that's more than semicircle
-     // Hmm, let me reconsider.
-     
-     // Actually the arc should only be the outer curved part (not enclosing the full D).
-     // The D shape: straight vertical line on left (at x=outer_r), arc on right.
-     // The arc goes from bottom-right to top-right of the straight line, curving outward.
-     
-     // Let me just build the handle with linear_extrude / hull approach for simplicity.
-     
-     // SIMPLIFIED APPROACH using hull of cylinders:
-     // We'll create the handle cross-section as a tube (hollow) but since we're doing union
-     // with the mug, we just need the solid handle shape.
-     
-     // Build handle as solid D-ring using rotate_extrude trick won't work for D in XZ plane.
-     
-     // Use polygon + rotate approach:
-     // The handle sweep path is in the XZ plane (y=0).
-     // Cross section is a circle of radius tube_r.
-     // We approximate the handle as a series of hull() segments.
-     
-     // Let's use N segments for the arc
-     N = 32;
-     // arc from angle_start to angle_end (in degrees, in XZ plane, 0=+X, 90=+Z)
-     a_bottom = atan2(-(h_space_h/2), -8);  // ≈ -118.07°  → let's use 180+atan2(15,8)
-     a_top    = atan2( (h_space_h/2), -8);  // ≈  118.07°
- 
-     // Going from a_bottom to a_top through 0° (i.e., through +X direction)
-     // a_bottom ≈ -118.07, a_top ≈ 118.07
-     // sweep from -118.07 to 118.07 through 0 (the short way going via 0)
-     
-     a_start = atan2(-(h_space_h/2), -(arc_center_x - outer_r));
-     a_end   = atan2( (h_space_h/2), -(arc_center_x - outer_r));
-     
-     // Build the arc as union of hull'd sphere-pairs
      union() {
-         // Arc segments
-         for (i = [0:N-1]) {
-             a1 = a_start + (a_end - a_start) * i / N;
-             a2 = a_start + (a_end - a_start) * (i+1) / N;
-             x1 = arc_center_x + arc_radius * cos(a1);
-             z1 = arc_center_z + arc_radius * sin(a1);
-             x2 = arc_center_x + arc_radius * cos(a2);
-             z2 = arc_center_z + arc_radius * sin(a2);
+         // --- Outer arc (tube swept along arc path) ---
+         for (i = [0 : N_arc-1]) {
+             a1 = a_bot + (a_top - a_bot) * i       / N_arc;
+             a2 = a_bot + (a_top - a_bot) * (i+1)   / N_arc;
+             x1 = arc_cx + arc_R * cos(a1);
+             z1 = handle_z + arc_R * sin(a1);
+             x2 = arc_cx + arc_R * cos(a2);
+             z2 = handle_z + arc_R * sin(a2);
              hull() {
-                 translate([x1, 0, z1]) sphere(r = tube_r, $fn = 16);
-                 translate([x2, 0, z2]) sphere(r = tube_r, $fn = 16);
+                 translate([x1, 0, z1]) sphere(r = tube_r, $fn = 24);
+                 translate([x2, 0, z2]) sphere(r = tube_r, $fn = 24);
              }
          }
-         // Bottom vertical bar: from mug axis connection to arc bottom endpoint
-         // bottom arc endpoint:
-         bot_x = arc_center_x + arc_radius * cos(a_start);
-         bot_z = arc_center_z + arc_radius * sin(a_start);
-         top_x = arc_center_x + arc_radius * cos(a_end);
-         top_z = arc_center_z + arc_radius * sin(a_end);
-         // Connect bottom endpoint to mug surface (embed into mug wall)
+ 
+         // --- Top connection bar ---
+         // From arc top endpoint back to mug body (X = 0 plane intersect, embed deep)
+         x_top = arc_cx + arc_R * cos(a_top);
+         z_top = handle_z + arc_R * sin(a_top);
          hull() {
-             translate([bot_x, 0, bot_z]) sphere(r = tube_r, $fn = 16);
-             translate([outer_r - tube_r, 0, bot_z]) sphere(r = tube_r, $fn = 16);
+             translate([x_top,       0, z_top]) sphere(r = tube_r, $fn = 24);
+             translate([outer_r - 2, 0, z_top]) sphere(r = tube_r, $fn = 24);
          }
-         // Connect top endpoint to mug surface
+ 
+         // --- Bottom connection bar ---
+         x_bot = arc_cx + arc_R * cos(a_bot);
+         z_bot = handle_z + arc_R * sin(a_bot);
          hull() {
-             translate([top_x, 0, top_z]) sphere(r = tube_r, $fn = 16);
-             translate([outer_r - tube_r, 0, top_z]) sphere(r = tube_r, $fn = 16);
+             translate([x_bot,       0, z_bot]) sphere(r = tube_r, $fn = 24);
+             translate([outer_r - 2, 0, z_bot]) sphere(r = tube_r, $fn = 24);
          }
      }
  }
  
- // Main model
+ module mug_body() {
+     difference() {
+         cylinder(r = outer_r, h = mug_h);
+         translate([0, 0, bot_t])
+             cylinder(r = inner_r, h = mug_h - bot_t + 0.1);
+     }
+ }
+ 
+ // Final model
  union() {
      mug_body();
      handle();
  }
SCAD (116 lines)
// Mug with handle on +X side
// Body: outer_r=40, inner_r=35, height=90, bottom=6mm
// Handle: inner space 30mm(H) x 25mm(W), on +X side, centered at mug mid-height

$fn = 128;

outer_r = 40;
inner_r = 35;
mug_h   = 90;
bot_t   = 6;

// Handle design
// Cross-section radius of handle tube
tube_r = 6;

// Inner clear space of handle: 30mm tall, 25mm wide
h_space_h = 30;
h_space_w  = 25;

// Handle center Z
handle_z = mug_h / 2;  // = 45

// The handle path (centerline) lies in the Y=0 plane.
// The straight (mug-side) portions run vertically at X = outer_r + tube_r,
// from Z = handle_z - h_space_h/2  to  Z = handle_z + h_space_h/2
// (embedded into the mug wall for solid union)
//
// The outer arc is a circular arc connecting the two vertical ends,
// bulging in the +X direction.
//
// Arc geometry:
//   Endpoints in XZ plane:
//     P_bot = (outer_r + tube_r,  handle_z - h_space_h/2)
//     P_top = (outer_r + tube_r,  handle_z + h_space_h/2)
//   The arc must extend to X = outer_r + tube_r + h_space_w at Z = handle_z.
//
//   Let arc center = (cx, handle_z).
//   R = cx - (outer_r + tube_r)   [rightmost reach]   → cx = outer_r + tube_r + R - h_space_w ... wait
//   R = (outer_r + tube_r + h_space_w) - cx
//   Also passes through P_bot:
//     R^2 = (outer_r + tube_r - cx)^2 + (h_space_h/2)^2
//   Let A = outer_r + tube_r, B = h_space_h/2 = 15, W = h_space_w = 25
//   R = (A + W) - cx  →  cx = A + W - R
//   R^2 = (A - cx)^2 + B^2
//       = (A - (A + W - R))^2 + B^2
//       = (R - W)^2 + B^2
//   R^2 = R^2 - 2RW + W^2 + B^2
//   0 = -2RW + W^2 + B^2
//   R = (W^2 + B^2) / (2W)
//     = (625 + 225) / 50 = 850/50 = 17

arc_R  = (h_space_w*h_space_w + (h_space_h/2)*(h_space_h/2)) / (2*h_space_w);
// arc_R = 17

// Arc center X:
arc_cx = outer_r + tube_r + h_space_w - arc_R;
// = 40 + 6 + 25 - 17 = 54

// Angles of endpoints from arc center (in XZ plane, measured from +X axis):
// P_bot relative to arc center: (outer_r+tube_r - arc_cx,  -(h_space_h/2))
//   dx = 46 - 54 = -8,  dz = -15
// P_top: dx=-8, dz=+15
a_bot = atan2(-(h_space_h/2), (outer_r + tube_r) - arc_cx);  // atan2(-15,-8) ≈ -118.07°
a_top = atan2( (h_space_h/2), (outer_r + tube_r) - arc_cx);  // atan2(+15,-8) ≈ +118.07°
// Arc sweeps from a_bot to a_top through 0° (+X direction)

N_arc = 48;  // number of segments for arc

module handle() {
    union() {
        // --- Outer arc (tube swept along arc path) ---
        for (i = [0 : N_arc-1]) {
            a1 = a_bot + (a_top - a_bot) * i       / N_arc;
            a2 = a_bot + (a_top - a_bot) * (i+1)   / N_arc;
            x1 = arc_cx + arc_R * cos(a1);
            z1 = handle_z + arc_R * sin(a1);
            x2 = arc_cx + arc_R * cos(a2);
            z2 = handle_z + arc_R * sin(a2);
            hull() {
                translate([x1, 0, z1]) sphere(r = tube_r, $fn = 24);
                translate([x2, 0, z2]) sphere(r = tube_r, $fn = 24);
            }
        }

        // --- Top connection bar ---
        // From arc top endpoint back to mug body (X = 0 plane intersect, embed deep)
        x_top = arc_cx + arc_R * cos(a_top);
        z_top = handle_z + arc_R * sin(a_top);
        hull() {
            translate([x_top,       0, z_top]) sphere(r = tube_r, $fn = 24);
            translate([outer_r - 2, 0, z_top]) sphere(r = tube_r, $fn = 24);
        }

        // --- Bottom connection bar ---
        x_bot = arc_cx + arc_R * cos(a_bot);
        z_bot = handle_z + arc_R * sin(a_bot);
        hull() {
            translate([x_bot,       0, z_bot]) sphere(r = tube_r, $fn = 24);
            translate([outer_r - 2, 0, z_bot]) sphere(r = tube_r, $fn = 24);
        }
    }
}

module mug_body() {
    difference() {
        cylinder(r = outer_r, h = mug_h);
        translate([0, 0, bot_t])
            cylinder(r = inner_r, h = mug_h - bot_t + 0.1);
    }
}

// Final model
union() {
    mug_body();
    handle();
}
i2 success
iter 2
23.3s · 2772/1496t · $0.0308
diff vs i1: +57/-84
- // Mug with handle on +X side
- // Body: outer_r=40, inner_r=35, height=90, bottom=6mm
- // Handle: inner space 30mm(H) x 25mm(W), on +X side, centered at mug mid-height
- 
  $fn = 128;
  
  outer_r = 40;
  inner_r = 35;
  mug_h   = 90;
  bot_t   = 6;
  
- // Handle design
- // Cross-section radius of handle tube
- tube_r = 6;
+ handle_z    = mug_h / 2;   // 45mm: 高さ方向中央
+ h_space_h   = 30;          // 取手内側空間 高さ
+ h_space_w   = 25;          // 取手内側空間 幅
+ handle_t    = 8;           // 取手の肉厚(断面幅)
  
- // Inner clear space of handle: 30mm tall, 25mm wide
- h_space_h = 30;
- h_space_w  = 25;
- 
- // Handle center Z
- handle_z = mug_h / 2;  // = 45
- 
- // The handle path (centerline) lies in the Y=0 plane.
- // The straight (mug-side) portions run vertically at X = outer_r + tube_r,
- // from Z = handle_z - h_space_h/2  to  Z = handle_z + h_space_h/2
- // (embedded into the mug wall for solid union)
+ // 取手の概念:
+ //   - 外形: 半円(+X側) + 上下の直線部分(本体に接続)
+ //   - 内空: 高さ h_space_h x 幅 h_space_w
+ //   - 本体外壁(X=outer_r)から生える
  //
- // The outer arc is a circular arc connecting the two vertical ends,
- // bulging in the +X direction.
+ // 構成:
+ //   1. 上バー: 本体壁からX方向に伸びる直方体
+ //   2. 下バー: 同上
+ //   3. 外側半円アーム: 上バーと下バーの外端を繋ぐ半円管
+ //      半円の中心: (outer_r + handle_t + h_space_w/2 + ... ) を計算
  //
- // Arc geometry:
- //   Endpoints in XZ plane:
- //     P_bot = (outer_r + tube_r,  handle_z - h_space_h/2)
- //     P_top = (outer_r + tube_r,  handle_z + h_space_h/2)
- //   The arc must extend to X = outer_r + tube_r + h_space_w at Z = handle_z.
- //
- //   Let arc center = (cx, handle_z).
- //   R = cx - (outer_r + tube_r)   [rightmost reach]   → cx = outer_r + tube_r + R - h_space_w ... wait
- //   R = (outer_r + tube_r + h_space_w) - cx
- //   Also passes through P_bot:
- //     R^2 = (outer_r + tube_r - cx)^2 + (h_space_h/2)^2
- //   Let A = outer_r + tube_r, B = h_space_h/2 = 15, W = h_space_w = 25
- //   R = (A + W) - cx  →  cx = A + W - R
- //   R^2 = (A - cx)^2 + B^2
- //       = (A - (A + W - R))^2 + B^2
- //       = (R - W)^2 + B^2
- //   R^2 = R^2 - 2RW + W^2 + B^2
- //   0 = -2RW + W^2 + B^2
- //   R = (W^2 + B^2) / (2W)
- //     = (625 + 225) / 50 = 850/50 = 17
+ // 取手の外側半円:
+ //   上バー外端 X座標 = outer_r + handle_t + h_space_w
+ //   上バー Z = handle_z + h_space_h/2
+ //   下バー Z = handle_z - h_space_h/2
+ //   半円アームの中心Z = handle_z, 中心X = outer_r + handle_t + h_space_w
+ //   半円アームの半径 = h_space_h/2 = 15
+ //   アーム断面 = handle_t x handle_t の正方形断面を rotate_extrude
  
- arc_R  = (h_space_w*h_space_w + (h_space_h/2)*(h_space_h/2)) / (2*h_space_w);
- // arc_R = 17
+ // 各部寸法
+ bar_x_start = outer_r - 3;               // 本体に3mm食い込んで確実に結合
+ bar_x_end   = outer_r + handle_t + h_space_w; // バーの外端X
+ bar_x_len   = bar_x_end - bar_x_start;
+ bar_z_top   = handle_z + h_space_h / 2;  // 45+15=60
+ bar_z_bot   = handle_z - h_space_h / 2;  // 45-15=30
+ arc_cx      = bar_x_end;                 // 半円中心X
+ arc_cz      = handle_z;                  // 半円中心Z
+ arc_r       = h_space_h / 2;             // =15 (半円の回転半径=内空高さ/2)
  
- // Arc center X:
- arc_cx = outer_r + tube_r + h_space_w - arc_R;
- // = 40 + 6 + 25 - 17 = 54
+ module handle_bar(z_center) {
+     // Y方向に handle_t の幅を持つ直方体バー
+     translate([bar_x_start, -handle_t/2, z_center - handle_t/2])
+         cube([bar_x_len, handle_t, handle_t]);
+ }
  
- // Angles of endpoints from arc center (in XZ plane, measured from +X axis):
- // P_bot relative to arc center: (outer_r+tube_r - arc_cx,  -(h_space_h/2))
- //   dx = 46 - 54 = -8,  dz = -15
- // P_top: dx=-8, dz=+15
- a_bot = atan2(-(h_space_h/2), (outer_r + tube_r) - arc_cx);  // atan2(-15,-8) ≈ -118.07°
- a_top = atan2( (h_space_h/2), (outer_r + tube_r) - arc_cx);  // atan2(+15,-8) ≈ +118.07°
- // Arc sweeps from a_bot to a_top through 0° (+X direction)
- 
- N_arc = 48;  // number of segments for arc
- 
- module handle() {
-     union() {
-         // --- Outer arc (tube swept along arc path) ---
-         for (i = [0 : N_arc-1]) {
-             a1 = a_bot + (a_top - a_bot) * i       / N_arc;
-             a2 = a_bot + (a_top - a_bot) * (i+1)   / N_arc;
-             x1 = arc_cx + arc_R * cos(a1);
-             z1 = handle_z + arc_R * sin(a1);
-             x2 = arc_cx + arc_R * cos(a2);
-             z2 = handle_z + arc_R * sin(a2);
-             hull() {
-                 translate([x1, 0, z1]) sphere(r = tube_r, $fn = 24);
-                 translate([x2, 0, z2]) sphere(r = tube_r, $fn = 24);
-             }
-         }
- 
-         // --- Top connection bar ---
-         // From arc top endpoint back to mug body (X = 0 plane intersect, embed deep)
-         x_top = arc_cx + arc_R * cos(a_top);
-         z_top = handle_z + arc_R * sin(a_top);
+ module handle_arc() {
+     // XZ平面内で、(arc_cx, arc_cz) を中心に半円を描く
+     // 断面: handle_t x handle_t の正方形
+     // +X側の半円(角度 -90° → +90°)
+     N = 64;
+     for (i = [0 : N-1]) {
+         a1 = -90 + 180 * i       / N;
+         a2 = -90 + 180 * (i+1)   / N;
+         x1 = arc_cx + arc_r * cos(a1);
+         z1 = arc_cz + arc_r * sin(a1);
+         x2 = arc_cx + arc_r * cos(a2);
+         z2 = arc_cz + arc_r * sin(a2);
          hull() {
-             translate([x_top,       0, z_top]) sphere(r = tube_r, $fn = 24);
-             translate([outer_r - 2, 0, z_top]) sphere(r = tube_r, $fn = 24);
+             translate([x1, -handle_t/2, z1])
+                 cube([handle_t, handle_t, 0.01]);
+             translate([x2, -handle_t/2, z2])
+                 cube([handle_t, handle_t, 0.01]);
          }
+     }
+ }
  
-         // --- Bottom connection bar ---
-         x_bot = arc_cx + arc_R * cos(a_bot);
-         z_bot = handle_z + arc_R * sin(a_bot);
-         hull() {
-             translate([x_bot,       0, z_bot]) sphere(r = tube_r, $fn = 24);
-             translate([outer_r - 2, 0, z_bot]) sphere(r = tube_r, $fn = 24);
-         }
+ module handle() {
+     union() {
+         handle_bar(bar_z_top);
+         handle_bar(bar_z_bot);
+         handle_arc();
      }
  }
  
  module mug_body() {
      difference() {
          cylinder(r = outer_r, h = mug_h);
          translate([0, 0, bot_t])
              cylinder(r = inner_r, h = mug_h - bot_t + 0.1);
      }
  }
  
  // Final model
  union() {
      mug_body();
      handle();
  }
SCAD (89 lines)
$fn = 128;

outer_r = 40;
inner_r = 35;
mug_h   = 90;
bot_t   = 6;

handle_z    = mug_h / 2;   // 45mm: 高さ方向中央
h_space_h   = 30;          // 取手内側空間 高さ
h_space_w   = 25;          // 取手内側空間 幅
handle_t    = 8;           // 取手の肉厚(断面幅)

// 取手の概念:
//   - 外形: 半円(+X側) + 上下の直線部分(本体に接続)
//   - 内空: 高さ h_space_h x 幅 h_space_w
//   - 本体外壁(X=outer_r)から生える
//
// 構成:
//   1. 上バー: 本体壁からX方向に伸びる直方体
//   2. 下バー: 同上
//   3. 外側半円アーム: 上バーと下バーの外端を繋ぐ半円管
//      半円の中心: (outer_r + handle_t + h_space_w/2 + ... ) を計算
//
// 取手の外側半円:
//   上バー外端 X座標 = outer_r + handle_t + h_space_w
//   上バー Z = handle_z + h_space_h/2
//   下バー Z = handle_z - h_space_h/2
//   半円アームの中心Z = handle_z, 中心X = outer_r + handle_t + h_space_w
//   半円アームの半径 = h_space_h/2 = 15
//   アーム断面 = handle_t x handle_t の正方形断面を rotate_extrude

// 各部寸法
bar_x_start = outer_r - 3;               // 本体に3mm食い込んで確実に結合
bar_x_end   = outer_r + handle_t + h_space_w; // バーの外端X
bar_x_len   = bar_x_end - bar_x_start;
bar_z_top   = handle_z + h_space_h / 2;  // 45+15=60
bar_z_bot   = handle_z - h_space_h / 2;  // 45-15=30
arc_cx      = bar_x_end;                 // 半円中心X
arc_cz      = handle_z;                  // 半円中心Z
arc_r       = h_space_h / 2;             // =15 (半円の回転半径=内空高さ/2)

module handle_bar(z_center) {
    // Y方向に handle_t の幅を持つ直方体バー
    translate([bar_x_start, -handle_t/2, z_center - handle_t/2])
        cube([bar_x_len, handle_t, handle_t]);
}

module handle_arc() {
    // XZ平面内で、(arc_cx, arc_cz) を中心に半円を描く
    // 断面: handle_t x handle_t の正方形
    // +X側の半円(角度 -90° → +90°)
    N = 64;
    for (i = [0 : N-1]) {
        a1 = -90 + 180 * i       / N;
        a2 = -90 + 180 * (i+1)   / N;
        x1 = arc_cx + arc_r * cos(a1);
        z1 = arc_cz + arc_r * sin(a1);
        x2 = arc_cx + arc_r * cos(a2);
        z2 = arc_cz + arc_r * sin(a2);
        hull() {
            translate([x1, -handle_t/2, z1])
                cube([handle_t, handle_t, 0.01]);
            translate([x2, -handle_t/2, z2])
                cube([handle_t, handle_t, 0.01]);
        }
    }
}

module handle() {
    union() {
        handle_bar(bar_z_top);
        handle_bar(bar_z_bot);
        handle_arc();
    }
}

module mug_body() {
    difference() {
        cylinder(r = outer_r, h = mug_h);
        translate([0, 0, bot_t])
            cylinder(r = inner_r, h = mug_h - bot_t + 0.1);
    }
}

// Final model
union() {
    mug_body();
    handle();
}
i3 success
iter 3
25.8s · 2347/1642t · $0.0317
diff vs i2: +67/-51
  $fn = 128;
  
- outer_r = 40;
- inner_r = 35;
- mug_h   = 90;
- bot_t   = 6;
+ outer_r  = 40;
+ inner_r  = 35;
+ mug_h    = 90;
+ bot_t    = 6;
  
- handle_z    = mug_h / 2;   // 45mm: 高さ方向中央
- h_space_h   = 30;          // 取手内側空間 高さ
- h_space_w   = 25;          // 取手内側空間 幅
- handle_t    = 8;           // 取手の肉厚(断面幅)
+ handle_z   = mug_h / 2;   // 高さ方向中央 = 45mm
+ h_space_h  = 30;          // 取手内側空間 高さ
+ h_space_w  = 25;          // 取手内側空間 幅
+ handle_t   = 10;          // 取手断面の太さ
  
- // 取手の概念:
- //   - 外形: 半円(+X側) + 上下の直線部分(本体に接続)
- //   - 内空: 高さ h_space_h x 幅 h_space_w
- //   - 本体外壁(X=outer_r)から生える
- //
- // 構成:
- //   1. 上バー: 本体壁からX方向に伸びる直方体
- //   2. 下バー: 同上
- //   3. 外側半円アーム: 上バーと下バーの外端を繋ぐ半円管
- //      半円の中心: (outer_r + handle_t + h_space_w/2 + ... ) を計算
- //
- // 取手の外側半円:
- //   上バー外端 X座標 = outer_r + handle_t + h_space_w
- //   上バー Z = handle_z + h_space_h/2
- //   下バー Z = handle_z - h_space_h/2
- //   半円アームの中心Z = handle_z, 中心X = outer_r + handle_t + h_space_w
- //   半円アームの半径 = h_space_h/2 = 15
- //   アーム断面 = handle_t x handle_t の正方形断面を rotate_extrude
- 
  // 各部寸法
- bar_x_start = outer_r - 3;               // 本体に3mm食い込んで確実に結合
- bar_x_end   = outer_r + handle_t + h_space_w; // バーの外端X
+ // バーはX軸方向に伸びる。本体に食い込んで確実結合
+ bar_x_start = outer_r - 3;
+ bar_x_end   = outer_r + h_space_w;         // バー外端X
  bar_x_len   = bar_x_end - bar_x_start;
- bar_z_top   = handle_z + h_space_h / 2;  // 45+15=60
- bar_z_bot   = handle_z - h_space_h / 2;  // 45-15=30
- arc_cx      = bar_x_end;                 // 半円中心X
- arc_cz      = handle_z;                  // 半円中心Z
- arc_r       = h_space_h / 2;             // =15 (半円の回転半径=内空高さ/2)
  
- module handle_bar(z_center) {
-     // Y方向に handle_t の幅を持つ直方体バー
-     translate([bar_x_start, -handle_t/2, z_center - handle_t/2])
+ bar_z_top   = handle_z + h_space_h / 2;   // = 60
+ bar_z_bot   = handle_z - h_space_h / 2;   // = 30
+ 
+ // 半円アーム中心: (bar_x_end, handle_z)
+ // 半円の回転半径 (中心線ベース) = h_space_h/2 = 15
+ arc_cx = bar_x_end;
+ arc_cz = handle_z;
+ arc_r  = h_space_h / 2;  // = 15
+ 
+ // 上バー: Z中心 = bar_z_top, 断面 handle_t x handle_t
+ module top_bar() {
+     translate([bar_x_start, -handle_t/2, bar_z_top - handle_t/2])
          cube([bar_x_len, handle_t, handle_t]);
  }
  
- module handle_arc() {
-     // XZ平面内で、(arc_cx, arc_cz) を中心に半円を描く
-     // 断面: handle_t x handle_t の正方形
-     // +X側の半円(角度 -90° → +90°)
-     N = 64;
+ // 下バー
+ module bot_bar() {
+     translate([bar_x_start, -handle_t/2, bar_z_bot - handle_t/2])
+         cube([bar_x_len, handle_t, handle_t]);
+ }
+ 
+ // 半円アーム: XZ平面内で -90°〜+90° の半円
+ // 各セグメントを hull() で繋ぐ
+ // 断面: handle_t x handle_t の立方体
+ module arc_arm() {
+     N = 48;
      for (i = [0 : N-1]) {
-         a1 = -90 + 180 * i       / N;
+         a1 = -90 + 180 *  i      / N;
          a2 = -90 + 180 * (i+1)   / N;
          x1 = arc_cx + arc_r * cos(a1);
          z1 = arc_cz + arc_r * sin(a1);
          x2 = arc_cx + arc_r * cos(a2);
          z2 = arc_cz + arc_r * sin(a2);
          hull() {
-             translate([x1, -handle_t/2, z1])
-                 cube([handle_t, handle_t, 0.01]);
-             translate([x2, -handle_t/2, z2])
-                 cube([handle_t, handle_t, 0.01]);
+             translate([x1 - handle_t/2, -handle_t/2, z1 - handle_t/2])
+                 cube([handle_t, handle_t, handle_t]);
+             translate([x2 - handle_t/2, -handle_t/2, z2 - handle_t/2])
+                 cube([handle_t, handle_t, handle_t]);
          }
      }
  }
  
+ // バーと半円を滑らかに繋ぐジョイント
+ module top_joint() {
+     x1 = arc_cx + arc_r * cos(-90);
+     z1 = arc_cz + arc_r * sin(-90);
+     hull() {
+         translate([bar_x_end - handle_t/2, -handle_t/2, bar_z_top - handle_t/2])
+             cube([handle_t, handle_t, handle_t]);
+         translate([x1 - handle_t/2, -handle_t/2, z1 - handle_t/2])
+             cube([handle_t, handle_t, handle_t]);
+     }
+ }
+ 
+ module bot_joint() {
+     x1 = arc_cx + arc_r * cos(90);
+     z1 = arc_cz + arc_r * sin(90);
+     hull() {
+         translate([bar_x_end - handle_t/2, -handle_t/2, bar_z_bot - handle_t/2])
+             cube([handle_t, handle_t, handle_t]);
+         translate([x1 - handle_t/2, -handle_t/2, z1 - handle_t/2])
+             cube([handle_t, handle_t, handle_t]);
+     }
+ }
+ 
  module handle() {
      union() {
-         handle_bar(bar_z_top);
-         handle_bar(bar_z_bot);
-         handle_arc();
+         top_bar();
+         bot_bar();
+         arc_arm();
+         top_joint();
+         bot_joint();
      }
  }
  
  module mug_body() {
      difference() {
          cylinder(r = outer_r, h = mug_h);
          translate([0, 0, bot_t])
              cylinder(r = inner_r, h = mug_h - bot_t + 0.1);
      }
  }
  
- // Final model
  union() {
      mug_body();
      handle();
  }
SCAD (105 lines)
$fn = 128;

outer_r  = 40;
inner_r  = 35;
mug_h    = 90;
bot_t    = 6;

handle_z   = mug_h / 2;   // 高さ方向中央 = 45mm
h_space_h  = 30;          // 取手内側空間 高さ
h_space_w  = 25;          // 取手内側空間 幅
handle_t   = 10;          // 取手断面の太さ

// 各部寸法
// バーはX軸方向に伸びる。本体に食い込んで確実結合
bar_x_start = outer_r - 3;
bar_x_end   = outer_r + h_space_w;         // バー外端X
bar_x_len   = bar_x_end - bar_x_start;

bar_z_top   = handle_z + h_space_h / 2;   // = 60
bar_z_bot   = handle_z - h_space_h / 2;   // = 30

// 半円アーム中心: (bar_x_end, handle_z)
// 半円の回転半径 (中心線ベース) = h_space_h/2 = 15
arc_cx = bar_x_end;
arc_cz = handle_z;
arc_r  = h_space_h / 2;  // = 15

// 上バー: Z中心 = bar_z_top, 断面 handle_t x handle_t
module top_bar() {
    translate([bar_x_start, -handle_t/2, bar_z_top - handle_t/2])
        cube([bar_x_len, handle_t, handle_t]);
}

// 下バー
module bot_bar() {
    translate([bar_x_start, -handle_t/2, bar_z_bot - handle_t/2])
        cube([bar_x_len, handle_t, handle_t]);
}

// 半円アーム: XZ平面内で -90°〜+90° の半円
// 各セグメントを hull() で繋ぐ
// 断面: handle_t x handle_t の立方体
module arc_arm() {
    N = 48;
    for (i = [0 : N-1]) {
        a1 = -90 + 180 *  i      / N;
        a2 = -90 + 180 * (i+1)   / N;
        x1 = arc_cx + arc_r * cos(a1);
        z1 = arc_cz + arc_r * sin(a1);
        x2 = arc_cx + arc_r * cos(a2);
        z2 = arc_cz + arc_r * sin(a2);
        hull() {
            translate([x1 - handle_t/2, -handle_t/2, z1 - handle_t/2])
                cube([handle_t, handle_t, handle_t]);
            translate([x2 - handle_t/2, -handle_t/2, z2 - handle_t/2])
                cube([handle_t, handle_t, handle_t]);
        }
    }
}

// バーと半円を滑らかに繋ぐジョイント
module top_joint() {
    x1 = arc_cx + arc_r * cos(-90);
    z1 = arc_cz + arc_r * sin(-90);
    hull() {
        translate([bar_x_end - handle_t/2, -handle_t/2, bar_z_top - handle_t/2])
            cube([handle_t, handle_t, handle_t]);
        translate([x1 - handle_t/2, -handle_t/2, z1 - handle_t/2])
            cube([handle_t, handle_t, handle_t]);
    }
}

module bot_joint() {
    x1 = arc_cx + arc_r * cos(90);
    z1 = arc_cz + arc_r * sin(90);
    hull() {
        translate([bar_x_end - handle_t/2, -handle_t/2, bar_z_bot - handle_t/2])
            cube([handle_t, handle_t, handle_t]);
        translate([x1 - handle_t/2, -handle_t/2, z1 - handle_t/2])
            cube([handle_t, handle_t, handle_t]);
    }
}

module handle() {
    union() {
        top_bar();
        bot_bar();
        arc_arm();
        top_joint();
        bot_joint();
    }
}

module mug_body() {
    difference() {
        cylinder(r = outer_r, h = mug_h);
        translate([0, 0, bot_t])
            cylinder(r = inner_r, h = mug_h - bot_t + 0.1);
    }
}

union() {
    mug_body();
    handle();
}