vibe-openscad

tier-2-offset-handle-mug / gemini-2.5-flash

6 run / 累計 306.6s / 累計 $0.0239

gemini flash 2.5 bare

bare (provider default effort)

run detail →
render
bare render of tier-2-offset-handle-mug
loading STL…
success 63.0s · 232/1364t · $0.0035
SCAD (110 lines)
// OpenSCAD Mug with Handle
// Global rendering quality (higher value = smoother curves)
$fn = 64;

// Mug body parameters
mug_outer_radius = 80 / 2; // 40mm
mug_inner_radius = 70 / 2; // 35mm
mug_height = 90;
mug_bottom_thickness = 6;

// Handle parameters
handle_thickness = 10;          // Thickness of the handle material
handle_inner_width = 25;        // Internal width of the finger hole (X direction)
handle_inner_height = 30;       // Internal height of the finger hole (Z direction)

// Calculate handle positioning
handle_z_center = mug_height / 2; // Center of the handle vertically on the mug
handle_y_center = 0;              // Center of the handle horizontally (aligned with mug's Y axis)

module mug_body() {
    difference() {
        // Outer cylinder of the mug
        cylinder(h = mug_height, r = mug_outer_radius);

        // Inner hollow part
        // Lifted by mug_bottom_thickness to create the solid bottom
        translate([0, 0, mug_bottom_thickness])
            cylinder(h = mug_height - mug_bottom_thickness, r = mug_inner_radius);
    }
}

module mug_handle() {
    union() {
        // 1. Vertical connecting bar
        // This bar connects the handle to the mug's outer surface (+X direction).
        // It spans the full height of the D-shaped handle.
        translate([
            mug_outer_radius,                           // Starts at the mug's outer surface (X)
            handle_y_center - handle_thickness / 2,     // Centered on Y axis
            handle_z_center - (handle_inner_height / 2 + handle_thickness) // Bottom Z of the handle
        ]) {
            cube([
                handle_thickness,                               // X-dimension (depth from mug into handle)
                handle_thickness,                               // Y-dimension (handle's thickness)
                handle_inner_height + 2 * handle_thickness      // Z-dimension (total height of the handle)
            ]);
        }

        // 2. Top horizontal bar
        // This bar forms the top part of the D-shape.
        translate([
            mug_outer_radius + handle_thickness,        // Starts after the vertical connecting bar (X)
            handle_y_center - handle_thickness / 2,     // Centered on Y axis
            handle_z_center + handle_inner_height / 2   // Top Z of the finger hole
        ]) {
            cube([
                handle_inner_width,                     // X-dimension (width of the finger hole part)
                handle_thickness,                       // Y-dimension (handle's thickness)
                handle_thickness                        // Z-dimension (height of this bar)
            ]);
        }

        // 3. Bottom horizontal bar
        // This bar forms the bottom part of the D-shape.
        translate([
            mug_outer_radius + handle_thickness,        // Starts after the vertical connecting bar (X)
            handle_y_center - handle_thickness / 2,     // Centered on Y axis
            handle_z_center - handle_inner_height / 2 - handle_thickness // Bottom Z of the finger hole
        ]) {
            cube([
                handle_inner_width,                     // X-dimension (width of the finger hole part)
                handle_thickness,                       // Y-dimension (handle's thickness)
                handle_thickness                        // Z-dimension (height of this bar)
            ]);
        }

        // 4. Outer D-shape arc
        // This creates the curved part of the D-shape handle.
        // It's formed by differencing two concentric cylinders and then cutting one half.
        outer_arc_radius = handle_inner_height / 2 + handle_thickness; // Radius of the outer curve
        inner_arc_radius = handle_inner_height / 2;                   // Radius of the inner cut for the arc

        arc_x_position = mug_outer_radius + handle_thickness + handle_inner_width; // X position of the arc's center
        arc_z_position = handle_z_center;                                          // Z position of the arc's center

        translate([arc_x_position, handle_y_center, arc_z_position])
        rotate([90, 0, 0]) { // Rotate so the cylinder's height is along Y, and the arc is in the XZ plane
            difference() {
                // Outer cylinder that defines the overall arc shape
                cylinder(r = outer_arc_radius, h = handle_thickness, center = true);
                
                // Inner cylinder to cut out the inside of the arc, creating a ring shape
                // Use a slightly larger height to ensure a clean cut through the entire handle_thickness
                cylinder(r = inner_arc_radius, h = handle_thickness * 1.01, center = true);
                
                // Cutting cube to remove the left half of the ring, forming the D-shape arc.
                // The cylinders are centered at [0,0,0] in this rotated coordinate system.
                // We want to keep the positive X half (right side), so we cut the negative X half (left side).
                translate([-(outer_arc_radius + 0.1), 0, 0]) // Position cutting cube to completely cover the negative X half
                    cube([outer_arc_radius + 0.2, handle_thickness * 1.01, outer_arc_radius * 2 + 0.2], center=true);
            }
        }
    }
}

// Assemble the complete mug by combining the body and the handle
union() {
    mug_body();
    mug_handle();
}
パラメータ (6)
スライダを動かすと openscad-wasm で再レンダリング

prompt

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

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

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

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

variant: thinking

off success
off
4.0s · 232/579t · $0.0015
SCAD (60 lines)
// Mug body parameters
outer_radius = 80 / 2;
inner_radius = 70 / 2;
wall_thickness = outer_radius - inner_radius; // Should be 5mm
height = 90;
bottom_thickness = 6;

// Handle parameters
handle_inner_height = 30;
handle_inner_width = 25;
handle_thickness = wall_thickness; // Same thickness as mug wall

// Calculate handle outer dimensions
handle_outer_radius = handle_inner_width / 2 + handle_thickness;
handle_outer_height = handle_inner_height + 2 * handle_thickness;

// Position handle in the middle of the mug height
handle_z_offset = (height - handle_outer_height) / 2;

module mug_body() {
    difference() {
        // Outer cylinder
        cylinder(h = height, r = outer_radius, $fn = 64);

        // Inner cylinder (for hollow space)
        translate([0, 0, bottom_thickness])
        cylinder(h = height - bottom_thickness, r = inner_radius, $fn = 64);
    }
}

module mug_handle() {
    // Position handle on the +X side of the mug
    // The handle's 'straight' side will be aligned with the mug's outer radius
    translate([outer_radius, 0, handle_z_offset]) {
        difference() {
            // Outer handle shape (rounded rectangle / half-cylinder extrusion)
            linear_extrude(height = handle_outer_height) {
                union() {
                    circle(r = handle_outer_radius, $fn = 32);
                    // Square to connect half-circle to straight edge, ensuring full arc
                    square([handle_outer_radius, 2 * handle_outer_radius], center = false);
                }
            }

            // Inner handle shape (to create the D-shape hole)
            translate([handle_thickness, 0, 0]) // Shift inner shape to the right to create the D
            linear_extrude(height = handle_inner_height) {
                union() {
                    circle(r = handle_inner_width / 2, $fn = 32);
                    square([handle_inner_width / 2, handle_inner_width], center = false);
                }
            }
        }
    }
}

union() {
    mug_body();
    mug_handle();
}
adaptivenot run
dynamic (default) success
dynamic
63.0s · 232/1364t · $0.0035
SCAD (110 lines)
// OpenSCAD Mug with Handle
// Global rendering quality (higher value = smoother curves)
$fn = 64;

// Mug body parameters
mug_outer_radius = 80 / 2; // 40mm
mug_inner_radius = 70 / 2; // 35mm
mug_height = 90;
mug_bottom_thickness = 6;

// Handle parameters
handle_thickness = 10;          // Thickness of the handle material
handle_inner_width = 25;        // Internal width of the finger hole (X direction)
handle_inner_height = 30;       // Internal height of the finger hole (Z direction)

// Calculate handle positioning
handle_z_center = mug_height / 2; // Center of the handle vertically on the mug
handle_y_center = 0;              // Center of the handle horizontally (aligned with mug's Y axis)

module mug_body() {
    difference() {
        // Outer cylinder of the mug
        cylinder(h = mug_height, r = mug_outer_radius);

        // Inner hollow part
        // Lifted by mug_bottom_thickness to create the solid bottom
        translate([0, 0, mug_bottom_thickness])
            cylinder(h = mug_height - mug_bottom_thickness, r = mug_inner_radius);
    }
}

module mug_handle() {
    union() {
        // 1. Vertical connecting bar
        // This bar connects the handle to the mug's outer surface (+X direction).
        // It spans the full height of the D-shaped handle.
        translate([
            mug_outer_radius,                           // Starts at the mug's outer surface (X)
            handle_y_center - handle_thickness / 2,     // Centered on Y axis
            handle_z_center - (handle_inner_height / 2 + handle_thickness) // Bottom Z of the handle
        ]) {
            cube([
                handle_thickness,                               // X-dimension (depth from mug into handle)
                handle_thickness,                               // Y-dimension (handle's thickness)
                handle_inner_height + 2 * handle_thickness      // Z-dimension (total height of the handle)
            ]);
        }

        // 2. Top horizontal bar
        // This bar forms the top part of the D-shape.
        translate([
            mug_outer_radius + handle_thickness,        // Starts after the vertical connecting bar (X)
            handle_y_center - handle_thickness / 2,     // Centered on Y axis
            handle_z_center + handle_inner_height / 2   // Top Z of the finger hole
        ]) {
            cube([
                handle_inner_width,                     // X-dimension (width of the finger hole part)
                handle_thickness,                       // Y-dimension (handle's thickness)
                handle_thickness                        // Z-dimension (height of this bar)
            ]);
        }

        // 3. Bottom horizontal bar
        // This bar forms the bottom part of the D-shape.
        translate([
            mug_outer_radius + handle_thickness,        // Starts after the vertical connecting bar (X)
            handle_y_center - handle_thickness / 2,     // Centered on Y axis
            handle_z_center - handle_inner_height / 2 - handle_thickness // Bottom Z of the finger hole
        ]) {
            cube([
                handle_inner_width,                     // X-dimension (width of the finger hole part)
                handle_thickness,                       // Y-dimension (handle's thickness)
                handle_thickness                        // Z-dimension (height of this bar)
            ]);
        }

        // 4. Outer D-shape arc
        // This creates the curved part of the D-shape handle.
        // It's formed by differencing two concentric cylinders and then cutting one half.
        outer_arc_radius = handle_inner_height / 2 + handle_thickness; // Radius of the outer curve
        inner_arc_radius = handle_inner_height / 2;                   // Radius of the inner cut for the arc

        arc_x_position = mug_outer_radius + handle_thickness + handle_inner_width; // X position of the arc's center
        arc_z_position = handle_z_center;                                          // Z position of the arc's center

        translate([arc_x_position, handle_y_center, arc_z_position])
        rotate([90, 0, 0]) { // Rotate so the cylinder's height is along Y, and the arc is in the XZ plane
            difference() {
                // Outer cylinder that defines the overall arc shape
                cylinder(r = outer_arc_radius, h = handle_thickness, center = true);
                
                // Inner cylinder to cut out the inside of the arc, creating a ring shape
                // Use a slightly larger height to ensure a clean cut through the entire handle_thickness
                cylinder(r = inner_arc_radius, h = handle_thickness * 1.01, center = true);
                
                // Cutting cube to remove the left half of the ring, forming the D-shape arc.
                // The cylinders are centered at [0,0,0] in this rotated coordinate system.
                // We want to keep the positive X half (right side), so we cut the negative X half (left side).
                translate([-(outer_arc_radius + 0.1), 0, 0]) // Position cutting cube to completely cover the negative X half
                    cube([outer_arc_radius + 0.2, handle_thickness * 1.01, outer_arc_radius * 2 + 0.2], center=true);
            }
        }
    }
}

// Assemble the complete mug by combining the body and the handle
union() {
    mug_body();
    mug_handle();
}

iteration: iter-png

i1 success
iter 1
55.7s · 1922/1735t · $0.0049
diff vs bare: +46/-24
  // OpenSCAD Mug with Handle
  // Global rendering quality (higher value = smoother curves)
  $fn = 64;
  
  // Mug body parameters
  mug_outer_radius = 80 / 2; // 40mm
  mug_inner_radius = 70 / 2; // 35mm
  mug_height = 90;
  mug_bottom_thickness = 6;
  
  // Handle parameters
  handle_thickness = 10;          // Thickness of the handle material
  handle_inner_width = 25;        // Internal width of the finger hole (X direction)
  handle_inner_height = 30;       // Internal height of the finger hole (Z direction)
  
+ // Overlap for robust union between handle and mug body
+ // A small positive value ensures the handle slightly penetrates the mug body
+ // which helps OpenSCAD create a manifold solid and avoids Z-fighting artifacts.
+ handle_mug_overlap = 0.5; // Example: 0.5mm overlap into the mug body
+ 
  // Calculate handle positioning
  handle_z_center = mug_height / 2; // Center of the handle vertically on the mug
  handle_y_center = 0;              // Center of the handle horizontally (aligned with mug's Y axis)
  
  module mug_body() {
      difference() {
          // Outer cylinder of the mug
          cylinder(h = mug_height, r = mug_outer_radius);
  
          // Inner hollow part
          // Lifted by mug_bottom_thickness to create the solid bottom
          translate([0, 0, mug_bottom_thickness])
              cylinder(h = mug_height - mug_bottom_thickness, r = mug_inner_radius);
      }
  }
  
  module mug_handle() {
+     // Define key X-coordinates for the handle construction for clarity and precision.
+     // The X-coordinate where the handle's outermost surface (if no overlap) would meet the mug.
+     x_mug_outer_surface = mug_outer_radius;
+ 
+     // The X-coordinate where the handle's vertical bar starts, embedded into the mug.
+     x_handle_start_embedded = x_mug_outer_surface - handle_mug_overlap;
+ 
+     // The X-coordinate of the inner face of the handle material, after the mug connection.
+     // This is also where the horizontal bars of the D-shape begin.
+     x_handle_inner_material_face = x_mug_outer_surface + handle_thickness;
+ 
+     // The X-coordinate where the straight part of the finger hole ends and the arc begins.
+     // This is the X-coordinate of the "straight edge" of the D-arc.
+     x_handle_arc_straight_edge = x_handle_inner_material_face + handle_inner_width;
+ 
      union() {
          // 1. Vertical connecting bar
          // This bar connects the handle to the mug's outer surface (+X direction).
          // It spans the full height of the D-shaped handle.
+         // Its X-dimension extends from x_handle_start_embedded to x_handle_inner_material_face.
          translate([
-             mug_outer_radius,                           // Starts at the mug's outer surface (X)
-             handle_y_center - handle_thickness / 2,     // Centered on Y axis
+             x_handle_start_embedded,                         // Starts slightly inside the mug (X)
+             handle_y_center - handle_thickness / 2,          // Centered on Y axis
              handle_z_center - (handle_inner_height / 2 + handle_thickness) // Bottom Z of the handle
          ]) {
              cube([
-                 handle_thickness,                               // X-dimension (depth from mug into handle)
-                 handle_thickness,                               // Y-dimension (handle's thickness)
-                 handle_inner_height + 2 * handle_thickness      // Z-dimension (total height of the handle)
+                 handle_thickness + handle_mug_overlap,       // X-dimension (handle_thickness + the overlap)
+                 handle_thickness,                            // Y-dimension (handle's thickness)
+                 handle_inner_height + 2 * handle_thickness   // Z-dimension (total height of the handle)
              ]);
          }
  
          // 2. Top horizontal bar
-         // This bar forms the top part of the D-shape.
+         // This bar forms the top part of the D-shape, connecting the vertical bar to the arc.
          translate([
-             mug_outer_radius + handle_thickness,        // Starts after the vertical connecting bar (X)
-             handle_y_center - handle_thickness / 2,     // Centered on Y axis
-             handle_z_center + handle_inner_height / 2   // Top Z of the finger hole
+             x_handle_inner_material_face,                    // Starts after the vertical connecting bar (X)
+             handle_y_center - handle_thickness / 2,          // Centered on Y axis
+             handle_z_center + handle_inner_height / 2        // Top Z of the finger hole
          ]) {
              cube([
-                 handle_inner_width,                     // X-dimension (width of the finger hole part)
-                 handle_thickness,                       // Y-dimension (handle's thickness)
-                 handle_thickness                        // Z-dimension (height of this bar)
+                 handle_inner_width,                          // X-dimension (width of the finger hole part)
+                 handle_thickness,                            // Y-dimension (handle's thickness)
+                 handle_thickness                             // Z-dimension (height of this bar)
              ]);
          }
  
          // 3. Bottom horizontal bar
          // This bar forms the bottom part of the D-shape.
          translate([
-             mug_outer_radius + handle_thickness,        // Starts after the vertical connecting bar (X)
-             handle_y_center - handle_thickness / 2,     // Centered on Y axis
+             x_handle_inner_material_face,                    // Starts after the vertical connecting bar (X)
+             handle_y_center - handle_thickness / 2,          // Centered on Y axis
              handle_z_center - handle_inner_height / 2 - handle_thickness // Bottom Z of the finger hole
          ]) {
              cube([
-                 handle_inner_width,                     // X-dimension (width of the finger hole part)
-                 handle_thickness,                       // Y-dimension (handle's thickness)
-                 handle_thickness                        // Z-dimension (height of this bar)
+                 handle_inner_width,                          // X-dimension (width of the finger hole part)
+                 handle_thickness,                            // Y-dimension (handle's thickness)
+                 handle_thickness                             // Z-dimension (height of this bar)
              ]);
          }
  
          // 4. Outer D-shape arc
          // This creates the curved part of the D-shape handle.
          // It's formed by differencing two concentric cylinders and then cutting one half.
          outer_arc_radius = handle_inner_height / 2 + handle_thickness; // Radius of the outer curve
          inner_arc_radius = handle_inner_height / 2;                   // Radius of the inner cut for the arc
  
-         arc_x_position = mug_outer_radius + handle_thickness + handle_inner_width; // X position of the arc's center
-         arc_z_position = handle_z_center;                                          // Z position of the arc's center
- 
-         translate([arc_x_position, handle_y_center, arc_z_position])
+         // The arc is generated such that its straight (left) edge is at X=0 in its local coordinates
+         // after the difference and cutting operations.
+         // We then translate it so this X=0 aligns with x_handle_arc_straight_edge.
+         translate([x_handle_arc_straight_edge, handle_y_center, handle_z_center])
          rotate([90, 0, 0]) { // Rotate so the cylinder's height is along Y, and the arc is in the XZ plane
              difference() {
-                 // Outer cylinder that defines the overall arc shape
+                 // Outer cylinder that defines the overall arc shape (centered in XZ plane)
                  cylinder(r = outer_arc_radius, h = handle_thickness, center = true);
                  
                  // Inner cylinder to cut out the inside of the arc, creating a ring shape
                  // Use a slightly larger height to ensure a clean cut through the entire handle_thickness
                  cylinder(r = inner_arc_radius, h = handle_thickness * 1.01, center = true);
                  
-                 // Cutting cube to remove the left half of the ring, forming the D-shape arc.
+                 // Cutting cube to remove the 'negative X' half of the ring, forming the D-shape arc.
                  // The cylinders are centered at [0,0,0] in this rotated coordinate system.
                  // We want to keep the positive X half (right side), so we cut the negative X half (left side).
-                 translate([-(outer_arc_radius + 0.1), 0, 0]) // Position cutting cube to completely cover the negative X half
+                 // This cube effectively cuts everything from X < ~0.
+                 translate([-outer_arc_radius - 0.1, 0, 0]) // Position cutting cube to completely cover the negative X half
                      cube([outer_arc_radius + 0.2, handle_thickness * 1.01, outer_arc_radius * 2 + 0.2], center=true);
              }
          }
      }
  }
  
  // Assemble the complete mug by combining the body and the handle
  union() {
      mug_body();
      mug_handle();
  }
SCAD (132 lines)
// OpenSCAD Mug with Handle
// Global rendering quality (higher value = smoother curves)
$fn = 64;

// Mug body parameters
mug_outer_radius = 80 / 2; // 40mm
mug_inner_radius = 70 / 2; // 35mm
mug_height = 90;
mug_bottom_thickness = 6;

// Handle parameters
handle_thickness = 10;          // Thickness of the handle material
handle_inner_width = 25;        // Internal width of the finger hole (X direction)
handle_inner_height = 30;       // Internal height of the finger hole (Z direction)

// Overlap for robust union between handle and mug body
// A small positive value ensures the handle slightly penetrates the mug body
// which helps OpenSCAD create a manifold solid and avoids Z-fighting artifacts.
handle_mug_overlap = 0.5; // Example: 0.5mm overlap into the mug body

// Calculate handle positioning
handle_z_center = mug_height / 2; // Center of the handle vertically on the mug
handle_y_center = 0;              // Center of the handle horizontally (aligned with mug's Y axis)

module mug_body() {
    difference() {
        // Outer cylinder of the mug
        cylinder(h = mug_height, r = mug_outer_radius);

        // Inner hollow part
        // Lifted by mug_bottom_thickness to create the solid bottom
        translate([0, 0, mug_bottom_thickness])
            cylinder(h = mug_height - mug_bottom_thickness, r = mug_inner_radius);
    }
}

module mug_handle() {
    // Define key X-coordinates for the handle construction for clarity and precision.
    // The X-coordinate where the handle's outermost surface (if no overlap) would meet the mug.
    x_mug_outer_surface = mug_outer_radius;

    // The X-coordinate where the handle's vertical bar starts, embedded into the mug.
    x_handle_start_embedded = x_mug_outer_surface - handle_mug_overlap;

    // The X-coordinate of the inner face of the handle material, after the mug connection.
    // This is also where the horizontal bars of the D-shape begin.
    x_handle_inner_material_face = x_mug_outer_surface + handle_thickness;

    // The X-coordinate where the straight part of the finger hole ends and the arc begins.
    // This is the X-coordinate of the "straight edge" of the D-arc.
    x_handle_arc_straight_edge = x_handle_inner_material_face + handle_inner_width;

    union() {
        // 1. Vertical connecting bar
        // This bar connects the handle to the mug's outer surface (+X direction).
        // It spans the full height of the D-shaped handle.
        // Its X-dimension extends from x_handle_start_embedded to x_handle_inner_material_face.
        translate([
            x_handle_start_embedded,                         // Starts slightly inside the mug (X)
            handle_y_center - handle_thickness / 2,          // Centered on Y axis
            handle_z_center - (handle_inner_height / 2 + handle_thickness) // Bottom Z of the handle
        ]) {
            cube([
                handle_thickness + handle_mug_overlap,       // X-dimension (handle_thickness + the overlap)
                handle_thickness,                            // Y-dimension (handle's thickness)
                handle_inner_height + 2 * handle_thickness   // Z-dimension (total height of the handle)
            ]);
        }

        // 2. Top horizontal bar
        // This bar forms the top part of the D-shape, connecting the vertical bar to the arc.
        translate([
            x_handle_inner_material_face,                    // Starts after the vertical connecting bar (X)
            handle_y_center - handle_thickness / 2,          // Centered on Y axis
            handle_z_center + handle_inner_height / 2        // Top Z of the finger hole
        ]) {
            cube([
                handle_inner_width,                          // X-dimension (width of the finger hole part)
                handle_thickness,                            // Y-dimension (handle's thickness)
                handle_thickness                             // Z-dimension (height of this bar)
            ]);
        }

        // 3. Bottom horizontal bar
        // This bar forms the bottom part of the D-shape.
        translate([
            x_handle_inner_material_face,                    // Starts after the vertical connecting bar (X)
            handle_y_center - handle_thickness / 2,          // Centered on Y axis
            handle_z_center - handle_inner_height / 2 - handle_thickness // Bottom Z of the finger hole
        ]) {
            cube([
                handle_inner_width,                          // X-dimension (width of the finger hole part)
                handle_thickness,                            // Y-dimension (handle's thickness)
                handle_thickness                             // Z-dimension (height of this bar)
            ]);
        }

        // 4. Outer D-shape arc
        // This creates the curved part of the D-shape handle.
        // It's formed by differencing two concentric cylinders and then cutting one half.
        outer_arc_radius = handle_inner_height / 2 + handle_thickness; // Radius of the outer curve
        inner_arc_radius = handle_inner_height / 2;                   // Radius of the inner cut for the arc

        // The arc is generated such that its straight (left) edge is at X=0 in its local coordinates
        // after the difference and cutting operations.
        // We then translate it so this X=0 aligns with x_handle_arc_straight_edge.
        translate([x_handle_arc_straight_edge, handle_y_center, handle_z_center])
        rotate([90, 0, 0]) { // Rotate so the cylinder's height is along Y, and the arc is in the XZ plane
            difference() {
                // Outer cylinder that defines the overall arc shape (centered in XZ plane)
                cylinder(r = outer_arc_radius, h = handle_thickness, center = true);
                
                // Inner cylinder to cut out the inside of the arc, creating a ring shape
                // Use a slightly larger height to ensure a clean cut through the entire handle_thickness
                cylinder(r = inner_arc_radius, h = handle_thickness * 1.01, center = true);
                
                // Cutting cube to remove the 'negative X' half of the ring, forming the D-shape arc.
                // The cylinders are centered at [0,0,0] in this rotated coordinate system.
                // We want to keep the positive X half (right side), so we cut the negative X half (left side).
                // This cube effectively cuts everything from X < ~0.
                translate([-outer_arc_radius - 0.1, 0, 0]) // Position cutting cube to completely cover the negative X half
                    cube([outer_arc_radius + 0.2, handle_thickness * 1.01, outer_arc_radius * 2 + 0.2], center=true);
            }
        }
    }
}

// Assemble the complete mug by combining the body and the handle
union() {
    mug_body();
    mug_handle();
}
i2 success
iter 2
60.3s · 2293/1802t · $0.0052
diff vs i1: +17/-14
  // OpenSCAD Mug with Handle
  // Global rendering quality (higher value = smoother curves)
  $fn = 64;
  
  // Mug body parameters
  mug_outer_radius = 80 / 2; // 40mm
  mug_inner_radius = 70 / 2; // 35mm
  mug_height = 90;
  mug_bottom_thickness = 6;
  
  // Handle parameters
  handle_thickness = 10;          // Thickness of the handle material
  handle_inner_width = 25;        // Internal width of the finger hole (X direction)
  handle_inner_height = 30;       // Internal height of the finger hole (Z direction)
  
- // Overlap for robust union between handle and mug body
- // A small positive value ensures the handle slightly penetrates the mug body
+ // Overlap for robust union between handle and mug body, and between handle components
+ // A small positive value ensures parts slightly penetrate each other,
  // which helps OpenSCAD create a manifold solid and avoids Z-fighting artifacts.
- handle_mug_overlap = 0.5; // Example: 0.5mm overlap into the mug body
+ handle_overlap_epsilon = 0.5; // Example: 0.5mm overlap
  
  // Calculate handle positioning
  handle_z_center = mug_height / 2; // Center of the handle vertically on the mug
  handle_y_center = 0;              // Center of the handle horizontally (aligned with mug's Y axis)
  
  module mug_body() {
      difference() {
          // Outer cylinder of the mug
          cylinder(h = mug_height, r = mug_outer_radius);
  
          // Inner hollow part
          // Lifted by mug_bottom_thickness to create the solid bottom
+         // Slightly increased height to avoid Z-fighting artifacts on the top surface
          translate([0, 0, mug_bottom_thickness])
-             cylinder(h = mug_height - mug_bottom_thickness, r = mug_inner_radius);
+             cylinder(h = mug_height - mug_bottom_thickness + handle_overlap_epsilon, r = mug_inner_radius);
      }
  }
  
  module mug_handle() {
      // Define key X-coordinates for the handle construction for clarity and precision.
      // The X-coordinate where the handle's outermost surface (if no overlap) would meet the mug.
      x_mug_outer_surface = mug_outer_radius;
  
      // The X-coordinate where the handle's vertical bar starts, embedded into the mug.
-     x_handle_start_embedded = x_mug_outer_surface - handle_mug_overlap;
+     x_handle_start_embedded = x_mug_outer_surface - handle_overlap_epsilon;
  
      // The X-coordinate of the inner face of the handle material, after the mug connection.
      // This is also where the horizontal bars of the D-shape begin.
      x_handle_inner_material_face = x_mug_outer_surface + handle_thickness;
  
      // The X-coordinate where the straight part of the finger hole ends and the arc begins.
      // This is the X-coordinate of the "straight edge" of the D-arc.
      x_handle_arc_straight_edge = x_handle_inner_material_face + handle_inner_width;
  
      union() {
-         // 1. Vertical connecting bar
-         // This bar connects the handle to the mug's outer surface (+X direction).
-         // It spans the full height of the D-shaped handle.
+         // 1. Vertical connecting bar (connects handle to mug)
+         // This bar spans the full height of the D-shaped handle.
          // Its X-dimension extends from x_handle_start_embedded to x_handle_inner_material_face.
          translate([
              x_handle_start_embedded,                         // Starts slightly inside the mug (X)
              handle_y_center - handle_thickness / 2,          // Centered on Y axis
              handle_z_center - (handle_inner_height / 2 + handle_thickness) // Bottom Z of the handle
          ]) {
              cube([
-                 handle_thickness + handle_mug_overlap,       // X-dimension (handle_thickness + the overlap)
+                 handle_thickness + handle_overlap_epsilon,   // X-dimension (handle_thickness + the overlap into mug)
                  handle_thickness,                            // Y-dimension (handle's thickness)
                  handle_inner_height + 2 * handle_thickness   // Z-dimension (total height of the handle)
              ]);
          }
  
          // 2. Top horizontal bar
          // This bar forms the top part of the D-shape, connecting the vertical bar to the arc.
+         // It's extended slightly into the arc region to ensure robust union.
          translate([
              x_handle_inner_material_face,                    // Starts after the vertical connecting bar (X)
              handle_y_center - handle_thickness / 2,          // Centered on Y axis
              handle_z_center + handle_inner_height / 2        // Top Z of the finger hole
          ]) {
              cube([
-                 handle_inner_width,                          // X-dimension (width of the finger hole part)
+                 handle_inner_width + handle_overlap_epsilon, // X-dimension (width of the finger hole part + overlap)
                  handle_thickness,                            // Y-dimension (handle's thickness)
                  handle_thickness                             // Z-dimension (height of this bar)
              ]);
          }
  
          // 3. Bottom horizontal bar
          // This bar forms the bottom part of the D-shape.
+         // It's extended slightly into the arc region to ensure robust union.
          translate([
              x_handle_inner_material_face,                    // Starts after the vertical connecting bar (X)
              handle_y_center - handle_thickness / 2,          // Centered on Y axis
              handle_z_center - handle_inner_height / 2 - handle_thickness // Bottom Z of the finger hole
          ]) {
              cube([
-                 handle_inner_width,                          // X-dimension (width of the finger hole part)
+                 handle_inner_width + handle_overlap_epsilon, // X-dimension (width of the finger hole part + overlap)
                  handle_thickness,                            // Y-dimension (handle's thickness)
                  handle_thickness                             // Z-dimension (height of this bar)
              ]);
          }
  
          // 4. Outer D-shape arc
          // This creates the curved part of the D-shape handle.
          // It's formed by differencing two concentric cylinders and then cutting one half.
          outer_arc_radius = handle_inner_height / 2 + handle_thickness; // Radius of the outer curve
          inner_arc_radius = handle_inner_height / 2;                   // Radius of the inner cut for the arc
  
          // The arc is generated such that its straight (left) edge is at X=0 in its local coordinates
          // after the difference and cutting operations.
-         // We then translate it so this X=0 aligns with x_handle_arc_straight_edge.
-         translate([x_handle_arc_straight_edge, handle_y_center, handle_z_center])
+         // We translate it so its straight edge overlaps with the horizontal bars.
+         translate([x_handle_arc_straight_edge - handle_overlap_epsilon, handle_y_center, handle_z_center])
          rotate([90, 0, 0]) { // Rotate so the cylinder's height is along Y, and the arc is in the XZ plane
              difference() {
                  // Outer cylinder that defines the overall arc shape (centered in XZ plane)
                  cylinder(r = outer_arc_radius, h = handle_thickness, center = true);
                  
                  // Inner cylinder to cut out the inside of the arc, creating a ring shape
                  // Use a slightly larger height to ensure a clean cut through the entire handle_thickness
                  cylinder(r = inner_arc_radius, h = handle_thickness * 1.01, center = true);
                  
                  // Cutting cube to remove the 'negative X' half of the ring, forming the D-shape arc.
                  // The cylinders are centered at [0,0,0] in this rotated coordinate system.
                  // We want to keep the positive X half (right side), so we cut the negative X half (left side).
                  // This cube effectively cuts everything from X < ~0.
-                 translate([-outer_arc_radius - 0.1, 0, 0]) // Position cutting cube to completely cover the negative X half
+                 // The cube is positioned to cover the negative X half, ensuring a clean cut.
+                 translate([-outer_arc_radius - 0.1, 0, 0])
                      cube([outer_arc_radius + 0.2, handle_thickness * 1.01, outer_arc_radius * 2 + 0.2], center=true);
              }
          }
      }
  }
  
  // Assemble the complete mug by combining the body and the handle
  union() {
      mug_body();
      mug_handle();
  }
SCAD (135 lines)
// OpenSCAD Mug with Handle
// Global rendering quality (higher value = smoother curves)
$fn = 64;

// Mug body parameters
mug_outer_radius = 80 / 2; // 40mm
mug_inner_radius = 70 / 2; // 35mm
mug_height = 90;
mug_bottom_thickness = 6;

// Handle parameters
handle_thickness = 10;          // Thickness of the handle material
handle_inner_width = 25;        // Internal width of the finger hole (X direction)
handle_inner_height = 30;       // Internal height of the finger hole (Z direction)

// Overlap for robust union between handle and mug body, and between handle components
// A small positive value ensures parts slightly penetrate each other,
// which helps OpenSCAD create a manifold solid and avoids Z-fighting artifacts.
handle_overlap_epsilon = 0.5; // Example: 0.5mm overlap

// Calculate handle positioning
handle_z_center = mug_height / 2; // Center of the handle vertically on the mug
handle_y_center = 0;              // Center of the handle horizontally (aligned with mug's Y axis)

module mug_body() {
    difference() {
        // Outer cylinder of the mug
        cylinder(h = mug_height, r = mug_outer_radius);

        // Inner hollow part
        // Lifted by mug_bottom_thickness to create the solid bottom
        // Slightly increased height to avoid Z-fighting artifacts on the top surface
        translate([0, 0, mug_bottom_thickness])
            cylinder(h = mug_height - mug_bottom_thickness + handle_overlap_epsilon, r = mug_inner_radius);
    }
}

module mug_handle() {
    // Define key X-coordinates for the handle construction for clarity and precision.
    // The X-coordinate where the handle's outermost surface (if no overlap) would meet the mug.
    x_mug_outer_surface = mug_outer_radius;

    // The X-coordinate where the handle's vertical bar starts, embedded into the mug.
    x_handle_start_embedded = x_mug_outer_surface - handle_overlap_epsilon;

    // The X-coordinate of the inner face of the handle material, after the mug connection.
    // This is also where the horizontal bars of the D-shape begin.
    x_handle_inner_material_face = x_mug_outer_surface + handle_thickness;

    // The X-coordinate where the straight part of the finger hole ends and the arc begins.
    // This is the X-coordinate of the "straight edge" of the D-arc.
    x_handle_arc_straight_edge = x_handle_inner_material_face + handle_inner_width;

    union() {
        // 1. Vertical connecting bar (connects handle to mug)
        // This bar spans the full height of the D-shaped handle.
        // Its X-dimension extends from x_handle_start_embedded to x_handle_inner_material_face.
        translate([
            x_handle_start_embedded,                         // Starts slightly inside the mug (X)
            handle_y_center - handle_thickness / 2,          // Centered on Y axis
            handle_z_center - (handle_inner_height / 2 + handle_thickness) // Bottom Z of the handle
        ]) {
            cube([
                handle_thickness + handle_overlap_epsilon,   // X-dimension (handle_thickness + the overlap into mug)
                handle_thickness,                            // Y-dimension (handle's thickness)
                handle_inner_height + 2 * handle_thickness   // Z-dimension (total height of the handle)
            ]);
        }

        // 2. Top horizontal bar
        // This bar forms the top part of the D-shape, connecting the vertical bar to the arc.
        // It's extended slightly into the arc region to ensure robust union.
        translate([
            x_handle_inner_material_face,                    // Starts after the vertical connecting bar (X)
            handle_y_center - handle_thickness / 2,          // Centered on Y axis
            handle_z_center + handle_inner_height / 2        // Top Z of the finger hole
        ]) {
            cube([
                handle_inner_width + handle_overlap_epsilon, // X-dimension (width of the finger hole part + overlap)
                handle_thickness,                            // Y-dimension (handle's thickness)
                handle_thickness                             // Z-dimension (height of this bar)
            ]);
        }

        // 3. Bottom horizontal bar
        // This bar forms the bottom part of the D-shape.
        // It's extended slightly into the arc region to ensure robust union.
        translate([
            x_handle_inner_material_face,                    // Starts after the vertical connecting bar (X)
            handle_y_center - handle_thickness / 2,          // Centered on Y axis
            handle_z_center - handle_inner_height / 2 - handle_thickness // Bottom Z of the finger hole
        ]) {
            cube([
                handle_inner_width + handle_overlap_epsilon, // X-dimension (width of the finger hole part + overlap)
                handle_thickness,                            // Y-dimension (handle's thickness)
                handle_thickness                             // Z-dimension (height of this bar)
            ]);
        }

        // 4. Outer D-shape arc
        // This creates the curved part of the D-shape handle.
        // It's formed by differencing two concentric cylinders and then cutting one half.
        outer_arc_radius = handle_inner_height / 2 + handle_thickness; // Radius of the outer curve
        inner_arc_radius = handle_inner_height / 2;                   // Radius of the inner cut for the arc

        // The arc is generated such that its straight (left) edge is at X=0 in its local coordinates
        // after the difference and cutting operations.
        // We translate it so its straight edge overlaps with the horizontal bars.
        translate([x_handle_arc_straight_edge - handle_overlap_epsilon, handle_y_center, handle_z_center])
        rotate([90, 0, 0]) { // Rotate so the cylinder's height is along Y, and the arc is in the XZ plane
            difference() {
                // Outer cylinder that defines the overall arc shape (centered in XZ plane)
                cylinder(r = outer_arc_radius, h = handle_thickness, center = true);
                
                // Inner cylinder to cut out the inside of the arc, creating a ring shape
                // Use a slightly larger height to ensure a clean cut through the entire handle_thickness
                cylinder(r = inner_arc_radius, h = handle_thickness * 1.01, center = true);
                
                // Cutting cube to remove the 'negative X' half of the ring, forming the D-shape arc.
                // The cylinders are centered at [0,0,0] in this rotated coordinate system.
                // We want to keep the positive X half (right side), so we cut the negative X half (left side).
                // This cube effectively cuts everything from X < ~0.
                // The cube is positioned to cover the negative X half, ensuring a clean cut.
                translate([-outer_arc_radius - 0.1, 0, 0])
                    cube([outer_arc_radius + 0.2, handle_thickness * 1.01, outer_arc_radius * 2 + 0.2], center=true);
            }
        }
    }
}

// Assemble the complete mug by combining the body and the handle
union() {
    mug_body();
    mug_handle();
}
i3 success
iter 3
60.6s · 2360/1835t · $0.0053
diff vs i2: +89/-90
  // OpenSCAD Mug with Handle
  // Global rendering quality (higher value = smoother curves)
  $fn = 64;
  
  // Mug body parameters
  mug_outer_radius = 80 / 2; // 40mm
  mug_inner_radius = 70 / 2; // 35mm
  mug_height = 90;
  mug_bottom_thickness = 6;
  
  // Handle parameters
  handle_thickness = 10;          // Thickness of the handle material
  handle_inner_width = 25;        // Internal width of the finger hole (X direction)
  handle_inner_height = 30;       // Internal height of the finger hole (Z direction)
  
  // Overlap for robust union between handle and mug body, and between handle components
  // A small positive value ensures parts slightly penetrate each other,
  // which helps OpenSCAD create a manifold solid and avoids Z-fighting artifacts.
  handle_overlap_epsilon = 0.5; // Example: 0.5mm overlap
  
- // Calculate handle positioning
- handle_z_center = mug_height / 2; // Center of the handle vertically on the mug
- handle_y_center = 0;              // Center of the handle horizontally (aligned with mug's Y axis)
- 
  module mug_body() {
      difference() {
          // Outer cylinder of the mug
          cylinder(h = mug_height, r = mug_outer_radius);
  
          // Inner hollow part
          // Lifted by mug_bottom_thickness to create the solid bottom
          // Slightly increased height to avoid Z-fighting artifacts on the top surface
          translate([0, 0, mug_bottom_thickness])
              cylinder(h = mug_height - mug_bottom_thickness + handle_overlap_epsilon, r = mug_inner_radius);
      }
  }
  
  module mug_handle() {
-     // Define key X-coordinates for the handle construction for clarity and precision.
-     // The X-coordinate where the handle's outermost surface (if no overlap) would meet the mug.
-     x_mug_outer_surface = mug_outer_radius;
+     // Calculate dimensions for the D-shape handle
+     // Total height of the handle from top edge to bottom edge
+     handle_total_height = handle_inner_height + 2 * handle_thickness;
+     // Outer radius of the D-arc (half of total height)
+     outer_d_arc_radius = handle_total_height / 2;
+     // Inner radius of the D-arc (half of inner height)
+     inner_d_arc_radius = handle_inner_height / 2;
  
-     // The X-coordinate where the handle's vertical bar starts, embedded into the mug.
-     x_handle_start_embedded = x_mug_outer_surface - handle_overlap_epsilon;
+     // Position the handle:
+     // Translate its "attachment point" (the X-coordinate where it meets the mug)
+     // to mug_outer_radius. We subtract handle_overlap_epsilon to embed it slightly.
+     // Its Y-center is 0 (aligned with mug's Y axis).
+     // Its Z-center is mug_height / 2 (aligned with mug's height center).
+     translate([
+         mug_outer_radius - handle_overlap_epsilon, // X: start slightly inside mug
+         0,                                          // Y: centered
+         mug_height / 2                              // Z: centered
+     ]) {
+         // Build the handle using difference between its outer solid shape and its inner cut-out shape.
+         difference() {
+             // 1. Outer solid handle shape
+             union() {
+                 // Rectangular part of the outer handle (from mug to the start of the arc)
+                 // In its local coordinate system:
+                 // X starts at -handle_overlap_epsilon (to embed into the mug)
+                 // X ends at handle_thickness + handle_inner_width (where the arc begins)
+                 cube([
+                     handle_thickness + handle_inner_width + handle_overlap_epsilon, // X-dimension
+                     handle_thickness,                                               // Y-thickness
+                     handle_total_height                                             // Z-height
+                 ], center = [
+                     (handle_thickness + handle_inner_width + handle_overlap_epsilon) / 2 - handle_overlap_epsilon, // X-center to align start at -overlap_epsilon
+                     0, // Y-center
+                     0  // Z-center
+                 ]);
  
-     // The X-coordinate of the inner face of the handle material, after the mug connection.
-     // This is also where the horizontal bars of the D-shape begin.
-     x_handle_inner_material_face = x_mug_outer_surface + handle_thickness;
+                 // Outer arc part (semi-cylinder)
+                 // The arc's straight edge is at X = handle_thickness + handle_inner_width.
+                 // We translate to this point for the cylinder's local origin.
+                 translate([
+                     handle_thickness + handle_inner_width, // X: where the arc's straight edge is
+                     0,                                     // Y
+                     0                                      // Z
+                 ])
+                 rotate([90, 0, 0]) { // Rotate cylinder (default along Z) so its axis is along Y, profile in XZ.
+                     difference() {
+                         cylinder(r = outer_d_arc_radius, h = handle_thickness, center = true);
+                         // Cut off the "left" half of the cylinder to form the D-shape arc.
+                         // The cube starts outside the cylinder's negative X range to ensure a full cut.
+                         translate([-outer_d_arc_radius - handle_overlap_epsilon * 2, 0, 0])
+                             cube([outer_d_arc_radius * 2 + handle_overlap_epsilon * 4, handle_thickness * 1.1, outer_d_arc_radius * 2 + handle_overlap_epsilon * 4], center=true);
+                     }
+                 }
+             }
  
-     // The X-coordinate where the straight part of the finger hole ends and the arc begins.
-     // This is the X-coordinate of the "straight edge" of the D-arc.
-     x_handle_arc_straight_edge = x_handle_inner_material_face + handle_inner_width;
+             // 2. Inner cut-out shape (finger hole)
+             // This starts after the mug-connecting material, at X = handle_thickness.
+             translate([
+                 handle_thickness, // X: Start of finger hole relative to mug's outer surface
+                 0,                // Y: centered
+                 0                 // Z: centered
+             ]) {
+                 union() {
+                     // Straight part of the finger hole cut-out
+                     cube([
+                         handle_inner_width + handle_overlap_epsilon, // X: Inner width + slight overlap into arc for clean cut
+                         handle_thickness * 1.1,                      // Y: Slightly larger than handle_thickness for clean cut
+                         handle_inner_height                          // Z: Inner height
+                     ], center=[
+                         (handle_inner_width + handle_overlap_epsilon) / 2, // X-center
+                         0,                                               // Y-center
+                         0                                                // Z-center
+                     ]);
  
-     union() {
-         // 1. Vertical connecting bar (connects handle to mug)
-         // This bar spans the full height of the D-shaped handle.
-         // Its X-dimension extends from x_handle_start_embedded to x_handle_inner_material_face.
-         translate([
-             x_handle_start_embedded,                         // Starts slightly inside the mug (X)
-             handle_y_center - handle_thickness / 2,          // Centered on Y axis
-             handle_z_center - (handle_inner_height / 2 + handle_thickness) // Bottom Z of the handle
-         ]) {
-             cube([
-                 handle_thickness + handle_overlap_epsilon,   // X-dimension (handle_thickness + the overlap into mug)
-                 handle_thickness,                            // Y-dimension (handle's thickness)
-                 handle_inner_height + 2 * handle_thickness   // Z-dimension (total height of the handle)
-             ]);
-         }
- 
-         // 2. Top horizontal bar
-         // This bar forms the top part of the D-shape, connecting the vertical bar to the arc.
-         // It's extended slightly into the arc region to ensure robust union.
-         translate([
-             x_handle_inner_material_face,                    // Starts after the vertical connecting bar (X)
-             handle_y_center - handle_thickness / 2,          // Centered on Y axis
-             handle_z_center + handle_inner_height / 2        // Top Z of the finger hole
-         ]) {
-             cube([
-                 handle_inner_width + handle_overlap_epsilon, // X-dimension (width of the finger hole part + overlap)
-                 handle_thickness,                            // Y-dimension (handle's thickness)
-                 handle_thickness                             // Z-dimension (height of this bar)
-             ]);
-         }
- 
-         // 3. Bottom horizontal bar
-         // This bar forms the bottom part of the D-shape.
-         // It's extended slightly into the arc region to ensure robust union.
-         translate([
-             x_handle_inner_material_face,                    // Starts after the vertical connecting bar (X)
-             handle_y_center - handle_thickness / 2,          // Centered on Y axis
-             handle_z_center - handle_inner_height / 2 - handle_thickness // Bottom Z of the finger hole
-         ]) {
-             cube([
-                 handle_inner_width + handle_overlap_epsilon, // X-dimension (width of the finger hole part + overlap)
-                 handle_thickness,                            // Y-dimension (handle's thickness)
-                 handle_thickness                             // Z-dimension (height of this bar)
-             ]);
-         }
- 
-         // 4. Outer D-shape arc
-         // This creates the curved part of the D-shape handle.
-         // It's formed by differencing two concentric cylinders and then cutting one half.
-         outer_arc_radius = handle_inner_height / 2 + handle_thickness; // Radius of the outer curve
-         inner_arc_radius = handle_inner_height / 2;                   // Radius of the inner cut for the arc
- 
-         // The arc is generated such that its straight (left) edge is at X=0 in its local coordinates
-         // after the difference and cutting operations.
-         // We translate it so its straight edge overlaps with the horizontal bars.
-         translate([x_handle_arc_straight_edge - handle_overlap_epsilon, handle_y_center, handle_z_center])
-         rotate([90, 0, 0]) { // Rotate so the cylinder's height is along Y, and the arc is in the XZ plane
-             difference() {
-                 // Outer cylinder that defines the overall arc shape (centered in XZ plane)
-                 cylinder(r = outer_arc_radius, h = handle_thickness, center = true);
-                 
-                 // Inner cylinder to cut out the inside of the arc, creating a ring shape
-                 // Use a slightly larger height to ensure a clean cut through the entire handle_thickness
-                 cylinder(r = inner_arc_radius, h = handle_thickness * 1.01, center = true);
-                 
-                 // Cutting cube to remove the 'negative X' half of the ring, forming the D-shape arc.
-                 // The cylinders are centered at [0,0,0] in this rotated coordinate system.
-                 // We want to keep the positive X half (right side), so we cut the negative X half (left side).
-                 // This cube effectively cuts everything from X < ~0.
-                 // The cube is positioned to cover the negative X half, ensuring a clean cut.
-                 translate([-outer_arc_radius - 0.1, 0, 0])
-                     cube([outer_arc_radius + 0.2, handle_thickness * 1.01, outer_arc_radius * 2 + 0.2], center=true);
+                     // Inner arc part of the finger hole cut-out
+                     // The inner arc's straight edge is at X = handle_inner_width (relative to its own translate).
+                     translate([
+                         handle_inner_width, // X: where the inner arc's straight edge is
+                         0,
+                         0
+                     ])
+                     rotate([90, 0, 0]) { // Same rotation as outer arc
+                         difference() {
+                             cylinder(r = inner_d_arc_radius, h = handle_thickness * 1.1, center = true); // Slightly larger height for clean cut
+                             // Cut off the "left" half of the inner cylinder.
+                             translate([-inner_d_arc_radius - handle_overlap_epsilon * 2, 0, 0])
+                                 cube([inner_d_arc_radius * 2 + handle_overlap_epsilon * 4, handle_thickness * 1.2, inner_d_arc_radius * 2 + handle_overlap_epsilon * 4], center=true);
+                         }
+                     }
+                 }
              }
-         }
-     }
- }
+         } // End of difference for the handle
+     } // End of translate for the handle position
+ } // End of mug_handle module
  
  // Assemble the complete mug by combining the body and the handle
  union() {
      mug_body();
      mug_handle();
  }
SCAD (134 lines)
// OpenSCAD Mug with Handle
// Global rendering quality (higher value = smoother curves)
$fn = 64;

// Mug body parameters
mug_outer_radius = 80 / 2; // 40mm
mug_inner_radius = 70 / 2; // 35mm
mug_height = 90;
mug_bottom_thickness = 6;

// Handle parameters
handle_thickness = 10;          // Thickness of the handle material
handle_inner_width = 25;        // Internal width of the finger hole (X direction)
handle_inner_height = 30;       // Internal height of the finger hole (Z direction)

// Overlap for robust union between handle and mug body, and between handle components
// A small positive value ensures parts slightly penetrate each other,
// which helps OpenSCAD create a manifold solid and avoids Z-fighting artifacts.
handle_overlap_epsilon = 0.5; // Example: 0.5mm overlap

module mug_body() {
    difference() {
        // Outer cylinder of the mug
        cylinder(h = mug_height, r = mug_outer_radius);

        // Inner hollow part
        // Lifted by mug_bottom_thickness to create the solid bottom
        // Slightly increased height to avoid Z-fighting artifacts on the top surface
        translate([0, 0, mug_bottom_thickness])
            cylinder(h = mug_height - mug_bottom_thickness + handle_overlap_epsilon, r = mug_inner_radius);
    }
}

module mug_handle() {
    // Calculate dimensions for the D-shape handle
    // Total height of the handle from top edge to bottom edge
    handle_total_height = handle_inner_height + 2 * handle_thickness;
    // Outer radius of the D-arc (half of total height)
    outer_d_arc_radius = handle_total_height / 2;
    // Inner radius of the D-arc (half of inner height)
    inner_d_arc_radius = handle_inner_height / 2;

    // Position the handle:
    // Translate its "attachment point" (the X-coordinate where it meets the mug)
    // to mug_outer_radius. We subtract handle_overlap_epsilon to embed it slightly.
    // Its Y-center is 0 (aligned with mug's Y axis).
    // Its Z-center is mug_height / 2 (aligned with mug's height center).
    translate([
        mug_outer_radius - handle_overlap_epsilon, // X: start slightly inside mug
        0,                                          // Y: centered
        mug_height / 2                              // Z: centered
    ]) {
        // Build the handle using difference between its outer solid shape and its inner cut-out shape.
        difference() {
            // 1. Outer solid handle shape
            union() {
                // Rectangular part of the outer handle (from mug to the start of the arc)
                // In its local coordinate system:
                // X starts at -handle_overlap_epsilon (to embed into the mug)
                // X ends at handle_thickness + handle_inner_width (where the arc begins)
                cube([
                    handle_thickness + handle_inner_width + handle_overlap_epsilon, // X-dimension
                    handle_thickness,                                               // Y-thickness
                    handle_total_height                                             // Z-height
                ], center = [
                    (handle_thickness + handle_inner_width + handle_overlap_epsilon) / 2 - handle_overlap_epsilon, // X-center to align start at -overlap_epsilon
                    0, // Y-center
                    0  // Z-center
                ]);

                // Outer arc part (semi-cylinder)
                // The arc's straight edge is at X = handle_thickness + handle_inner_width.
                // We translate to this point for the cylinder's local origin.
                translate([
                    handle_thickness + handle_inner_width, // X: where the arc's straight edge is
                    0,                                     // Y
                    0                                      // Z
                ])
                rotate([90, 0, 0]) { // Rotate cylinder (default along Z) so its axis is along Y, profile in XZ.
                    difference() {
                        cylinder(r = outer_d_arc_radius, h = handle_thickness, center = true);
                        // Cut off the "left" half of the cylinder to form the D-shape arc.
                        // The cube starts outside the cylinder's negative X range to ensure a full cut.
                        translate([-outer_d_arc_radius - handle_overlap_epsilon * 2, 0, 0])
                            cube([outer_d_arc_radius * 2 + handle_overlap_epsilon * 4, handle_thickness * 1.1, outer_d_arc_radius * 2 + handle_overlap_epsilon * 4], center=true);
                    }
                }
            }

            // 2. Inner cut-out shape (finger hole)
            // This starts after the mug-connecting material, at X = handle_thickness.
            translate([
                handle_thickness, // X: Start of finger hole relative to mug's outer surface
                0,                // Y: centered
                0                 // Z: centered
            ]) {
                union() {
                    // Straight part of the finger hole cut-out
                    cube([
                        handle_inner_width + handle_overlap_epsilon, // X: Inner width + slight overlap into arc for clean cut
                        handle_thickness * 1.1,                      // Y: Slightly larger than handle_thickness for clean cut
                        handle_inner_height                          // Z: Inner height
                    ], center=[
                        (handle_inner_width + handle_overlap_epsilon) / 2, // X-center
                        0,                                               // Y-center
                        0                                                // Z-center
                    ]);

                    // Inner arc part of the finger hole cut-out
                    // The inner arc's straight edge is at X = handle_inner_width (relative to its own translate).
                    translate([
                        handle_inner_width, // X: where the inner arc's straight edge is
                        0,
                        0
                    ])
                    rotate([90, 0, 0]) { // Same rotation as outer arc
                        difference() {
                            cylinder(r = inner_d_arc_radius, h = handle_thickness * 1.1, center = true); // Slightly larger height for clean cut
                            // Cut off the "left" half of the inner cylinder.
                            translate([-inner_d_arc_radius - handle_overlap_epsilon * 2, 0, 0])
                                cube([inner_d_arc_radius * 2 + handle_overlap_epsilon * 4, handle_thickness * 1.2, inner_d_arc_radius * 2 + handle_overlap_epsilon * 4], center=true);
                        }
                    }
                }
            }
        } // End of difference for the handle
    } // End of translate for the handle position
} // End of mug_handle module

// Assemble the complete mug by combining the body and the handle
union() {
    mug_body();
    mug_handle();
}