vibe-openscad

tier-3-butt-hinge / gpt-5.4-nano-2026-03-17

7 run / 累計 170.8s / 累計 $0.0162

openai gpt 5.4 nano 2026-03-17 bare

bare (provider default effort)

run detail →
render
no render
render_error 11.9s · 592/1712t · $0.0011
openscad stl render failed (exit 1): ERROR: Parser error: syntax error in file ../../../../../tmp/render-iCUZuD/input.scad, line 94
Can't parse file '/tmp/render-iCUZuD/input.scad'!

SCAD (160 lines)
// Small butt hinge (3 parts assembled) in open position (180deg)

$fn = 64;

// ---- Parameters ----
leaf_L = [30, 25, 2];   // [Y length, X opening direction length, thickness]
t = 2;
Ylen = 30;              // vertical along hinge axis
Xspan = 25;             // opening direction length
pin_d = 4;
pin_len = 32;          // total pin length
knuckle_len = 30;      // along Y
knuckle_segments = 5;  // split into 6mm each
seg = knuckle_len/knuckle_segments; // 6mm
clear = 0.3;
bore_d = pin_d + clear; // 4.6mm

kn_outer = 8;          // outer diameter
kn_inner = bore_d;     // inner bore diameter (with clearance)
gap = 0.2;             // small spacing for boolean robustness

// M3 countersunk holes (3 pcs per leaf)
cs_d_top = 6;          // tapered part top diameter
cs_depth = 1;         // depth of countersink
through_d = 3.2;     // through hole diameter
cs_pitch = 8;         // along Y
// 3 holes: at Y = 8, 16, 24 (given 8mm pitch from top)
hole_ys = [8, 16, 24];

// Open position: leaves are coplanar, flat faces share same plane
// Define leaf thickness along Z.
open180 = 1; // just to clarify

// ---- Helper modules ----

// Leaf plate: centered at hinge line.
// Leaves lie in XY plane at z=0 (thickness along Z).
module leaf_side(x_sign=1) {
    // x_sign: -1 for left (x<0), +1 for right (x>0)
    // Flat face: plane z=0; thickness spans z = [-t/2, +t/2]
    translate([x_sign * (Xspan/2), 0, 0])
        cube([Xspan, Ylen, t], center=true);
}

// Knuckle: cylinder with bore, positioned along Y.
// x0 at 0 by definition.
module knuckle(y_pos=0, side_sign=1) {
    // side_sign not needed for geometry; leaves occupy x!=0.
    // Knuckle sits on leaf thickness (center at z=0), axis along X.
    // But pin axis is Y; knuckles should align with pin axis => cylinder axis along Y.
    // Therefore knuckle cylinder axis along Y, positioned at x=0.
    // Outer: dia 8, Inner bore: dia 4.6 along Y.
    difference() {
        // Outer sleeve
        translate([0, y_pos, 0])
            rotate([0,90,0])  // make cylinder axis along Y (default cylinder axis is Z)
                cylinder(d=kn_outer, h=knuckle_len, center=true);

        // Bore along Y
        translate([0, y_pos, 0])
            rotate([0,90,0])
                cylinder(d=kn_inner, h=knuckle_len + 2*gap, center=true);
    }
}

// Countersunk + through hole pair along Z.
// Hole axis along Z; countersink top on +Z face for each leaf.
module m3_countersink(y_pos=0) {
    // Through cylinder (straight)
    translate([0, y_pos, 0])
        rotate([90,0,0])
            cylinder(d=through_d, h=leaf_L[2] + 4*gap, center=true);

    // Countersink cone: taper with top dia 6, depth 1.
    // Cone axis along Z.
    translate([0, y_pos, leaf_L[2]/2 - cs_depth/2]) {
        // Cone frustum: use cylinder with r1,r2, height=cs_depth
        // Top diameter cs_d_top at top face, bottom at depth end diameter = 3.2
        cylinder(h=cs_depth, r1=cs_d_top/2, r2=through_d/2, center=true);
    }
}

// Build one leaf with its knuckles and 3 screw holes.
module leaf_assembly(x_sign=1, knuckle_count=3, kn_positions=[]) {
    union() {
        // Leaf plate
        leaf_side(x_sign);

        // Knuckles: placed at X=0, on both leaves.
        // For x_sign, knuckle lies at leaf's side near x=0 edge.
        // Leaves are centered at +/- Xspan/2, so their edge at x=sign*Xspan/2.
        // knuckle centerline should be at x=0, which is the hinge axis plane.
        // thus knuckle outer surface overlaps leaf thickness; good enough.
        for (y in kn_positions)
            knuckle(y_pos=y, side_sign=x_sign);
    }
}

// Subtract screw holes from each leaf (their center at the leaf far side).
module leaf_with_holes(x_sign=1, kn_positions=[], holes_on_far_side=true) {
    // far side relative to hinge axis: x_sign * Xspan/2
    // Holes are drilled from the far side surface (towards +x for left?).
    // We'll simply place holes centered on leaf thickness; booleans will cut.
    difference() {
        leaf_assembly(x_sign=x_sign, kn_positions=kn_positions);

        // Countersunk + through holes at 3 Y positions
        for (y in hole_ys) {
            // Hole axis along Z. Place at far side surface (x = x_sign*Xspan/2)
            // Use x location at far face center:
            translate([x_sign * (Xspan/2) , y, 0])
                m3_countersink(y_pos=0); // m3_countersink positions at its local y
        }

        // Bore through knuckles in that leaf for the shared pin
        // (to ensure clean assembly)
        for (y in kn_positions) {
            translate([0, y, 0])
                rotate([0,90,0])
                    cylinder(d=kn_inner, h=kn_outer + 4*gap, center=true);
        }
    }
}

// Pin
module pin() {
    // Pin axis along Y centered at Y=0; length 32mm, centered.
    // knuckle sleeves cover Y=0..0 with center at 0.5? We'll center at Y=0.
    // Place pin so it extends equally; cylinder centered at y=0.
    translate([0, 0, 0])
        rotate([90,0,0]) // make cylinder axis along Y
            cylinder(d=pin_d, h=pin_len, center=true);
}

// ---- Placement of knuckles ----
// Total knuckles separated in Y by 6mm across 30mm (5 segments).
// We use centers at Y = -12, -6, 0, 6, 12 (spanning 30mm).
kn_centers = [-12, -6, 0, 6, 12];

// Left: outer 2 + central 1 => [-12, 0, 12]
left_kn = [kn_centers[0], kn_centers[2], kn_centers[4]];
// Right: "middle 2" => [-6, 6]
right_kn = [kn_centers[1], kn_centers[3]];

// ---- Assemble in open position (180deg) ----
// Ensure leaves are coplanar when open: left x<0, right x>0 already.
module butt_hinge_open180() {
    union() {
        // Left leaf
        leaf_with_holes(x_sign=-1, kn_positions=left_kn);

        // Right leaf
        leaf_with_holes(x_sign= 1, kn_positions=right_kn);

        // Shared pin
        pin();
    }
}

butt_hinge_open180();

prompt

OpenSCAD で、家具用の小型バット蝶番(butt hinge)を作ってください。
3 つのパーツ(左板、右板、ピン軸)が組み合わさって動作する完成品を、
「開いた状態(180°)」で 1 つの SCAD ファイルに配置して出力します。

寸法と配置:
- 板(leaf)2 枚: 30mm × 25mm × 厚さ 2mm の鉄板形状
  - 縦 30mm の辺がピン軸に沿う(ヒンジ軸方向)
  - 横 25mm の辺が回転で開く方向に伸びる
- ピン軸: 直径 4mm の円柱、長さ 32mm(両端 1mm ずつ knuckle から飛び出す)
- knuckle(筒部): 縦 30mm を 5 等分(各 6mm)に区切り、左板に 3 個・右板に 2 個を
  互い違いに配置(左板は外側 2 個 + 中央 1 個、右板は中間 2 個)
- knuckle 外径 8mm、内径はピン軸 + 0.3mm クリアランス(= 4.6mm 穴)
- 左板と右板はピン軸を共有して回転可能。180° 開いた状態で、両板の
  平らな面が同一平面に来るように配置する
- 各板の knuckle から離れた側に、M3 用の皿穴を 3 個ずつ
  (穴ピッチは板の縦方向に 8mm 間隔、皿穴は表面から見て直径 6mm × 深さ 1mm
  のテーパ + 直径 3.2mm の貫通穴)

座標系:
- ピン軸の中心線を Y 軸に重ねる(ピン軸は +Y 方向)
- 板の平らな面は Z 軸に直交し、左板が x<0 側、右板が x>0 側に伸びる(180° 開)
- knuckle は X=0 を中心とし、Y 方向に 6mm ずつ並ぶ

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

variant: effort

low success
low
28.7s · 592/3832t · $0.0023
SCAD (107 lines)
$fn = 64;

// ---------------------- Parameters ----------------------
leaf_len_y = 30;          // along Y
leaf_len_x = 25;          // along X (opening direction)
leaf_thk_z = 2;

knuckle_count_total = 5;
knuckle_seg = 6;          // 30 / 5
knuckle_outer_d = 8;      // outer diameter
pin_d = 4;                // pin diameter
clearance = 0.3;
knuckle_inner_d = pin_d + clearance; // 4.6
knuckle_len_y = knuckle_seg;

pin_len_y = 32;          // 1mm overhang each side (30 + 2)
pin_overhang = 1;

hole_pitch_y = 8;
hole_count = 3;          // y positions: -8, 0, +8
hole_y0 = 0;

screw_d = 3.2;          // through hole diameter
csk_d = 6;              // countersink top diameter
csk_depth = 1;          // countersink depth

leaf_free_edge_offset = 2; // from free edge along X for countersink location (assumed)

knuckle_y_positions = [-12, -6, 0, 6, 12]; // 5 segments over 30mm
left_knuckle_idx  = [0, 2, 4]; // outer, middle
right_knuckle_idx = [1, 3];    // middle two

// ---------------------- Helpers ----------------------
module leaf_plate_with_knuckles(is_left=true) {
    x_min = is_left ? -leaf_len_x : 0;
    x_max = is_left ? 0 : leaf_len_x;
    x_center = (x_min + x_max) / 2;

    difference() {
        // Leaf plate
        translate([x_center, 0, 0])
            cube([leaf_len_x, leaf_len_y, leaf_thk_z], center=true);

        // Knuckle bores on this leaf (to be subtracted from each knuckle barrel)
        for (i = (is_left ? left_knuckle_idx : right_knuckle_idx)) {
            y = knuckle_y_positions[i];
            translate([0, y, 0])
                rotate([90,0,0]) // axis along Y
                    cylinder(h=leaf_thk_z+0.2, d=knuckle_inner_d, center=true);
        }

        // M3 countersunk holes (axis along Z through thickness)
        // Location: near free edge side, on face perpendicular to Z; assumed centered at Z=0.
        for (k = [0:hole_count-1]) {
            y = hole_y0 + (k - (hole_count-1)/2) * hole_pitch_y;

            x = is_left ? (-leaf_len_x + leaf_free_edge_offset) : (leaf_len_x - leaf_free_edge_offset);

            // Through hole
            translate([x, y, 0])
                cylinder(h=leaf_thk_z+4, d=screw_d, center=true);

            // Countersink (taper)
            // Make taper on the same Z side (+Z) for both leaves (open state is coplanar).
            translate([x, y, leaf_thk_z/2])  // top surface z = +1
                rotate([0,0,0])
                    translate([0,0,-csk_depth/2])
                        cylinder(h=csk_depth, d1=csk_d, d2=screw_d, center=true);
        }
    }

    // Add knuckle barrels (with outer diameter), but keep only the portion within plate thickness
    for (i = (is_left ? left_knuckle_idx : right_knuckle_idx)) {
        y = knuckle_y_positions[i];

        // Barrel solid limited to plate thickness by intersection with a slab
        intersection() {
            translate([0, y, 0])
                rotate([90,0,0]) // axis along Y
                    cylinder(h=knuckle_len_y, d=knuckle_outer_d, center=true);

            // slab to limit to leaf thickness in Z
            translate([0, 0, 0])
                cube([leaf_len_x*3, leaf_len_y, leaf_thk_z], center=true);
        }
    }
}

module pin() {
    translate([0, 0, 0])
        rotate([90,0,0]) // axis along Y
            cylinder(h=pin_len_y, d=pin_d, center=true);
}

// ---------------------- Assembly: open state (180°) ----------------------
// Leaves are coplanar; left at x<0, right at x>0 sharing pin axis at X=0.

union() {
    // Pin axis (for visual/assembled state)
    pin();

    // Leaves with knuckles and screw holes
    leaf_plate_with_knuckles(true);  // left
    leaf_plate_with_knuckles(false); // right
}

// Ensure knuckles align at X=0 and Y spacing is centered at y=0.
medium (default) render_error render
render_error
11.9s · 592/1712t · $0.0011
openscad stl render failed (exit 1): ERROR: Parser error: syntax error in file ../../../../../tmp/render-iCUZuD/input.scad, line 94
Can't parse file '/tmp/render-iCUZuD/input.scad'!

SCAD (160 lines)
// Small butt hinge (3 parts assembled) in open position (180deg)

$fn = 64;

// ---- Parameters ----
leaf_L = [30, 25, 2];   // [Y length, X opening direction length, thickness]
t = 2;
Ylen = 30;              // vertical along hinge axis
Xspan = 25;             // opening direction length
pin_d = 4;
pin_len = 32;          // total pin length
knuckle_len = 30;      // along Y
knuckle_segments = 5;  // split into 6mm each
seg = knuckle_len/knuckle_segments; // 6mm
clear = 0.3;
bore_d = pin_d + clear; // 4.6mm

kn_outer = 8;          // outer diameter
kn_inner = bore_d;     // inner bore diameter (with clearance)
gap = 0.2;             // small spacing for boolean robustness

// M3 countersunk holes (3 pcs per leaf)
cs_d_top = 6;          // tapered part top diameter
cs_depth = 1;         // depth of countersink
through_d = 3.2;     // through hole diameter
cs_pitch = 8;         // along Y
// 3 holes: at Y = 8, 16, 24 (given 8mm pitch from top)
hole_ys = [8, 16, 24];

// Open position: leaves are coplanar, flat faces share same plane
// Define leaf thickness along Z.
open180 = 1; // just to clarify

// ---- Helper modules ----

// Leaf plate: centered at hinge line.
// Leaves lie in XY plane at z=0 (thickness along Z).
module leaf_side(x_sign=1) {
    // x_sign: -1 for left (x<0), +1 for right (x>0)
    // Flat face: plane z=0; thickness spans z = [-t/2, +t/2]
    translate([x_sign * (Xspan/2), 0, 0])
        cube([Xspan, Ylen, t], center=true);
}

// Knuckle: cylinder with bore, positioned along Y.
// x0 at 0 by definition.
module knuckle(y_pos=0, side_sign=1) {
    // side_sign not needed for geometry; leaves occupy x!=0.
    // Knuckle sits on leaf thickness (center at z=0), axis along X.
    // But pin axis is Y; knuckles should align with pin axis => cylinder axis along Y.
    // Therefore knuckle cylinder axis along Y, positioned at x=0.
    // Outer: dia 8, Inner bore: dia 4.6 along Y.
    difference() {
        // Outer sleeve
        translate([0, y_pos, 0])
            rotate([0,90,0])  // make cylinder axis along Y (default cylinder axis is Z)
                cylinder(d=kn_outer, h=knuckle_len, center=true);

        // Bore along Y
        translate([0, y_pos, 0])
            rotate([0,90,0])
                cylinder(d=kn_inner, h=knuckle_len + 2*gap, center=true);
    }
}

// Countersunk + through hole pair along Z.
// Hole axis along Z; countersink top on +Z face for each leaf.
module m3_countersink(y_pos=0) {
    // Through cylinder (straight)
    translate([0, y_pos, 0])
        rotate([90,0,0])
            cylinder(d=through_d, h=leaf_L[2] + 4*gap, center=true);

    // Countersink cone: taper with top dia 6, depth 1.
    // Cone axis along Z.
    translate([0, y_pos, leaf_L[2]/2 - cs_depth/2]) {
        // Cone frustum: use cylinder with r1,r2, height=cs_depth
        // Top diameter cs_d_top at top face, bottom at depth end diameter = 3.2
        cylinder(h=cs_depth, r1=cs_d_top/2, r2=through_d/2, center=true);
    }
}

// Build one leaf with its knuckles and 3 screw holes.
module leaf_assembly(x_sign=1, knuckle_count=3, kn_positions=[]) {
    union() {
        // Leaf plate
        leaf_side(x_sign);

        // Knuckles: placed at X=0, on both leaves.
        // For x_sign, knuckle lies at leaf's side near x=0 edge.
        // Leaves are centered at +/- Xspan/2, so their edge at x=sign*Xspan/2.
        // knuckle centerline should be at x=0, which is the hinge axis plane.
        // thus knuckle outer surface overlaps leaf thickness; good enough.
        for (y in kn_positions)
            knuckle(y_pos=y, side_sign=x_sign);
    }
}

// Subtract screw holes from each leaf (their center at the leaf far side).
module leaf_with_holes(x_sign=1, kn_positions=[], holes_on_far_side=true) {
    // far side relative to hinge axis: x_sign * Xspan/2
    // Holes are drilled from the far side surface (towards +x for left?).
    // We'll simply place holes centered on leaf thickness; booleans will cut.
    difference() {
        leaf_assembly(x_sign=x_sign, kn_positions=kn_positions);

        // Countersunk + through holes at 3 Y positions
        for (y in hole_ys) {
            // Hole axis along Z. Place at far side surface (x = x_sign*Xspan/2)
            // Use x location at far face center:
            translate([x_sign * (Xspan/2) , y, 0])
                m3_countersink(y_pos=0); // m3_countersink positions at its local y
        }

        // Bore through knuckles in that leaf for the shared pin
        // (to ensure clean assembly)
        for (y in kn_positions) {
            translate([0, y, 0])
                rotate([0,90,0])
                    cylinder(d=kn_inner, h=kn_outer + 4*gap, center=true);
        }
    }
}

// Pin
module pin() {
    // Pin axis along Y centered at Y=0; length 32mm, centered.
    // knuckle sleeves cover Y=0..0 with center at 0.5? We'll center at Y=0.
    // Place pin so it extends equally; cylinder centered at y=0.
    translate([0, 0, 0])
        rotate([90,0,0]) // make cylinder axis along Y
            cylinder(d=pin_d, h=pin_len, center=true);
}

// ---- Placement of knuckles ----
// Total knuckles separated in Y by 6mm across 30mm (5 segments).
// We use centers at Y = -12, -6, 0, 6, 12 (spanning 30mm).
kn_centers = [-12, -6, 0, 6, 12];

// Left: outer 2 + central 1 => [-12, 0, 12]
left_kn = [kn_centers[0], kn_centers[2], kn_centers[4]];
// Right: "middle 2" => [-6, 6]
right_kn = [kn_centers[1], kn_centers[3]];

// ---- Assemble in open position (180deg) ----
// Ensure leaves are coplanar when open: left x<0, right x>0 already.
module butt_hinge_open180() {
    union() {
        // Left leaf
        leaf_with_holes(x_sign=-1, kn_positions=left_kn);

        // Right leaf
        leaf_with_holes(x_sign= 1, kn_positions=right_kn);

        // Shared pin
        pin();
    }
}

butt_hinge_open180();
high success
high
93.7s · 592/15016t · $0.0091
SCAD (99 lines)
$fn = 64;

EPS = 0.01;

// Plate
plateX = 25;      // open/close direction
plateY = 30;      // along pin axis
plateT = 2;       // thickness
xHalf  = plateX/2;
zMid   = plateT/2;

// Hinge pin
pinD = 4;
pinL = 32;

// Knuckle
knOD = 8;
knID = pinD + 0.3; // clearance
knLen = 6;          // each segment length
knYLeft  = [-12, 0, 12]; // 3 knuckles (outer + middle)
knYRight = [-6, 6];      // 2 knuckles (interleaving)

// Screw holes
holeThroughD = 3.2;
holeCsD      = 6;
holeCsR      = holeCsD/2;
holeCsDepth  = 1;
holePitch    = 8;
holeInset    = 5; // from the far edge

module tubeSegment(od, id, lenY) {
  rotate([90, 0, 0]) {
    difference() {
      cylinder(d=od, h=lenY, center=true);
      cylinder(d=id, h=lenY + 0.02, center=true);
    }
  }
}

module knuckle(side, yCenter) {
  // Keep knuckle only on the leaf side (x<0 for left, x>0 for right)
  intersection() {
    translate([0, yCenter, zMid]) tubeSegment(knOD, knID, knLen);

    // Large clipping half-space
    if (side < 0) {
      // x <= -EPS
      translate([-100, -100, -100]) cube([100 - EPS, 200, 200], center=false);
    } else {
      // x >= +EPS
      translate([EPS, -100, -100]) cube([100, 200, 200], center=false);
    }
  }
}

module countersunkHole(x, y) {
  // countersink cone from top surface (z = plateT) down by holeCsDepth
  translate([x, y, plateT - holeCsDepth])
    cylinder(h=holeCsDepth, r1=0, r2=holeCsR, center=false);

  // through hole
  translate([x, y, -1])
    cylinder(h=plateT + 2, d=holeThroughD, center=false);
}

module leaf(side) {
  knY = (side < 0) ? knYLeft : knYRight;
  xPlateCenter = side * xHalf;
  xHole = side * (plateX - holeInset);

  difference() {
    union() {
      // Flat leaf plate
      translate([xPlateCenter, 0, zMid])
        cube([plateX, plateY, plateT], center=true);

      // Knuckles
      for (yCenter = knY)
        knuckle(side, yCenter);
    }

    // 3x M3 countersunk holes (y: -8, 0, +8)
    for (i = [-1, 0, 1]) {
      countersunkHole(xHole, i * holePitch);
    }
  }
}

// Assembled open state (180°): left leaf at x<0, right leaf at x>0, pin along +Y
union() {
  color([0.75, 0.75, 0.75]) leaf(-1); // left
  color([0.70, 0.70, 0.70]) leaf(1);  // right

  color([0.95, 0.55, 0.15]) {          // pin axis
    translate([0, 0, zMid])
      rotate([90, 0, 0])
        cylinder(d=pinD, h=pinL, center=true);
  }
}
maxnot run
xhighnot run

iteration: iter-png

i1 render_error render
render_error
9.5s · 2405/1331t · $0.0010
openscad stl render failed (exit 1): ERROR: Parser error: syntax error in file ../../../../../tmp/render-e9IRNF/input.scad, line 78
Can't parse file '/tmp/render-e9IRNF/input.scad'!

diff vs bare: +76/-105
  // Small butt hinge (3 parts assembled) in open position (180deg)
  
- $fn = 64;
+ $fn = 96;
  
  // ---- Parameters ----
- leaf_L = [30, 25, 2];   // [Y length, X opening direction length, thickness]
- t = 2;
- Ylen = 30;              // vertical along hinge axis
- Xspan = 25;             // opening direction length
+ t = 2;                 // leaf thickness (Z)
+ Ylen = 30;             // leaf length along hinge axis (Y)
+ Xspan = 25;            // leaf length along opening direction (X)
  pin_d = 4;
- pin_len = 32;          // total pin length
- knuckle_len = 30;      // along Y
- knuckle_segments = 5;  // split into 6mm each
+ pin_len = 32;         // total pin length
+ 
+ knuckle_len = 30;     // along Y
+ knuckle_segments = 5; // split into 6mm each (=> 6mm)
  seg = knuckle_len/knuckle_segments; // 6mm
+ 
  clear = 0.3;
  bore_d = pin_d + clear; // 4.6mm
  
- kn_outer = 8;          // outer diameter
- kn_inner = bore_d;     // inner bore diameter (with clearance)
- gap = 0.2;             // small spacing for boolean robustness
+ kn_outer = 8;
+ kn_inner = bore_d;
  
+ gap = 0.2;            // boolean robustness
+ 
  // M3 countersunk holes (3 pcs per leaf)
- cs_d_top = 6;          // tapered part top diameter
- cs_depth = 1;         // depth of countersink
- through_d = 3.2;     // through hole diameter
- cs_pitch = 8;         // along Y
- // 3 holes: at Y = 8, 16, 24 (given 8mm pitch from top)
- hole_ys = [8, 16, 24];
+ cs_d_top = 6;        // countersink cone top diameter (mm)
+ cs_depth = 1;        // countersink depth (mm)
+ through_d = 3.2;    // through hole diameter (mm)
+ hole_pitch = 8;      // spacing along Y
+ hole_ys = [8, 16, 24];// based on 8mm pitch
  
- // Open position: leaves are coplanar, flat faces share same plane
- // Define leaf thickness along Z.
- open180 = 1; // just to clarify
+ // ---- Helper: make a cylinder whose axis is along Y ----
+ module cyl_y(d=1, h=1, center=true) {
+     rotate([90,0,0]) cylinder(d=d, h=h, center=center);
+ }
  
- // ---- Helper modules ----
- 
- // Leaf plate: centered at hinge line.
- // Leaves lie in XY plane at z=0 (thickness along Z).
- module leaf_side(x_sign=1) {
-     // x_sign: -1 for left (x<0), +1 for right (x>0)
-     // Flat face: plane z=0; thickness spans z = [-t/2, +t/2]
+ // ---- Leaf plate: centered at hinge axis plane (X=0) ----
+ // Leaf lies in the XY plane with Z thickness.
+ module leaf_plate(x_sign=1) {
+     // x_sign=-1 => leaf on x<0, x_sign=+1 => leaf on x>0
      translate([x_sign * (Xspan/2), 0, 0])
          cube([Xspan, Ylen, t], center=true);
  }
  
- // Knuckle: cylinder with bore, positioned along Y.
- // x0 at 0 by definition.
- module knuckle(y_pos=0, side_sign=1) {
-     // side_sign not needed for geometry; leaves occupy x!=0.
-     // Knuckle sits on leaf thickness (center at z=0), axis along X.
-     // But pin axis is Y; knuckles should align with pin axis => cylinder axis along Y.
-     // Therefore knuckle cylinder axis along Y, positioned at x=0.
-     // Outer: dia 8, Inner bore: dia 4.6 along Y.
+ // ---- Knuckle sleeve with bore: sleeve axis along Y ----
+ // Y position sets the sleeve center.
+ module knuckle(y_pos=0) {
      difference() {
-         // Outer sleeve
-         translate([0, y_pos, 0])
-             rotate([0,90,0])  // make cylinder axis along Y (default cylinder axis is Z)
-                 cylinder(d=kn_outer, h=knuckle_len, center=true);
+         // outer sleeve
+         translate([0, y_pos, 0]) cyl_y(d=kn_outer, h=knuckle_len, center=true);
  
-         // Bore along Y
-         translate([0, y_pos, 0])
-             rotate([0,90,0])
-                 cylinder(d=kn_inner, h=knuckle_len + 2*gap, center=true);
+         // bore along Y
+         translate([0, y_pos, 0]) cyl_y(d=kn_inner, h=knuckle_len + 2*gap, center=true);
      }
  }
  
- // Countersunk + through hole pair along Z.
- // Hole axis along Z; countersink top on +Z face for each leaf.
- module m3_countersink(y_pos=0) {
-     // Through cylinder (straight)
-     translate([0, y_pos, 0])
-         rotate([90,0,0])
-             cylinder(d=through_d, h=leaf_L[2] + 4*gap, center=true);
+ // Countersunk + through hole (axis along Z), located at a given Y.
+ // Countersink is on the leaf side corresponding to +Z (we'll subtract; geometry stays correct).
+ module m3_hole_z() {
+     // Through hole
+     cylinder(d=through_d, h=t + 4*gap, center=true);
  
-     // Countersink cone: taper with top dia 6, depth 1.
-     // Cone axis along Z.
-     translate([0, y_pos, leaf_L[2]/2 - cs_depth/2]) {
-         // Cone frustum: use cylinder with r1,r2, height=cs_depth
-         // Top diameter cs_d_top at top face, bottom at depth end diameter = 3.2
-         cylinder(h=cs_depth, r1=cs_d_top/2, r2=through_d/2, center=true);
-     }
+     // Countersink (cone frustum)
+     translate([0,0, (cs_depth/2)])  // start at +Z face
+         cylinder(h=cs_depth, d1=cs_d_top, d2=through_d, center=true);
  }
  
- // Build one leaf with its knuckles and 3 screw holes.
- module leaf_assembly(x_sign=1, knuckle_count=3, kn_positions=[]) {
-     union() {
-         // Leaf plate
-         leaf_side(x_sign);
- 
-         // Knuckles: placed at X=0, on both leaves.
-         // For x_sign, knuckle lies at leaf's side near x=0 edge.
-         // Leaves are centered at +/- Xspan/2, so their edge at x=sign*Xspan/2.
-         // knuckle centerline should be at x=0, which is the hinge axis plane.
-         // thus knuckle outer surface overlaps leaf thickness; good enough.
-         for (y in kn_positions)
-             knuckle(y_pos=y, side_sign=x_sign);
-     }
- }
- 
- // Subtract screw holes from each leaf (their center at the leaf far side).
- module leaf_with_holes(x_sign=1, kn_positions=[], holes_on_far_side=true) {
-     // far side relative to hinge axis: x_sign * Xspan/2
-     // Holes are drilled from the far side surface (towards +x for left?).
-     // We'll simply place holes centered on leaf thickness; booleans will cut.
+ // Build one leaf including its knuckles and screw holes,
+ // while also subtracting bore cylinders so shared knuckles align.
+ module leaf_with_knuckles_and_holes(x_sign=1, kn_positions=[], screw_far_face_sign=1) {
+     // screw_far_face_sign: +1 => countersink normal to +Z face doesn't matter much for subtract,
+     // we'll model only using "top at +Z" countersink. Since both leaves are at Z=0 plane,
+     // subtraction will work regardless of which side is "far"; using +Z countersink is fine.
      difference() {
-         leaf_assembly(x_sign=x_sign, kn_positions=kn_positions);
+         union() {
+             leaf_plate(x_sign);
  
-         // Countersunk + through holes at 3 Y positions
-         for (y in hole_ys) {
-             // Hole axis along Z. Place at far side surface (x = x_sign*Xspan/2)
-             // Use x location at far face center:
-             translate([x_sign * (Xspan/2) , y, 0])
-                 m3_countersink(y_pos=0); // m3_countersink positions at its local y
+             // Add knuckles at X=0 plane (hinge axis plane)
+             for (y in kn_positions) knuckle(y);
          }
  
-         // Bore through knuckles in that leaf for the shared pin
-         // (to ensure clean assembly)
+         // Subtract pin bores through the knuckles that belong to this leaf.
+         // (So left and right both have the aligned holes.)
          for (y in kn_positions) {
-             translate([0, y, 0])
-                 rotate([0,90,0])
-                     cylinder(d=kn_inner, h=kn_outer + 4*gap, center=true);
+             translate([0, y, 0]) cyl_y(d=kn_inner, h=kn_outer + 4*gap, center=true);
          }
+ 
+         // Subtract 3 screw holes.
+         // "Each plate side away from knuckle": given only as "far side", which is at x = x_sign*Xspan/2.
+         // Use that as center for the hole axis along Z.
+         for (yy in hole_ys) {
+             translate([x_sign * (Xspan/2), yy, 0]) {
+                 // Countersink+through. Centered hole modeled along Z.
+                 // Ensure countersink is cut from the +Z face by positioning the cone appropriately.
+                 // The m3_hole_z module uses +Z face countersink by default.
+                 m3_hole_z();
+             }
+         }
      }
  }
  
- // Pin
+ // Pin: cylinder along Y, total length 32mm (centered at Y=0).
  module pin() {
-     // Pin axis along Y centered at Y=0; length 32mm, centered.
-     // knuckle sleeves cover Y=0..0 with center at 0.5? We'll center at Y=0.
-     // Place pin so it extends equally; cylinder centered at y=0.
-     translate([0, 0, 0])
-         rotate([90,0,0]) // make cylinder axis along Y
-             cylinder(d=pin_d, h=pin_len, center=true);
+     cyl_y(d=pin_d, h=pin_len, center=true);
  }
  
- // ---- Placement of knuckles ----
+ // ---- Knuckle placement along Y ----
  // Total knuckles separated in Y by 6mm across 30mm (5 segments).
- // We use centers at Y = -12, -6, 0, 6, 12 (spanning 30mm).
+ // Centers at Y = -12, -6, 0, 6, 12 spanning 30mm.
  kn_centers = [-12, -6, 0, 6, 12];
  
  // Left: outer 2 + central 1 => [-12, 0, 12]
+ // Right: middle 2 => [-6, 6]
  left_kn = [kn_centers[0], kn_centers[2], kn_centers[4]];
- // Right: "middle 2" => [-6, 6]
  right_kn = [kn_centers[1], kn_centers[3]];
  
- // ---- Assemble in open position (180deg) ----
- // Ensure leaves are coplanar when open: left x<0, right x>0 already.
+ // ---- Main assembly in open position (180deg) ----
+ // Leaves already coplanar at Z=0 and placed on x<0 and x>0.
  module butt_hinge_open180() {
      union() {
          // Left leaf
-         leaf_with_holes(x_sign=-1, kn_positions=left_kn);
+         leaf_with_knuckles_and_holes(x_sign=-1, kn_positions=left_kn);
  
          // Right leaf
-         leaf_with_holes(x_sign= 1, kn_positions=right_kn);
+         leaf_with_knuckles_and_holes(x_sign= 1, kn_positions=right_kn);
  
          // Shared pin
-         pin();
+         translate([0, 0, 0]) pin();
      }
  }
  
  butt_hinge_open180();
SCAD (131 lines)
// Small butt hinge (3 parts assembled) in open position (180deg)

$fn = 96;

// ---- Parameters ----
t = 2;                 // leaf thickness (Z)
Ylen = 30;             // leaf length along hinge axis (Y)
Xspan = 25;            // leaf length along opening direction (X)
pin_d = 4;
pin_len = 32;         // total pin length

knuckle_len = 30;     // along Y
knuckle_segments = 5; // split into 6mm each (=> 6mm)
seg = knuckle_len/knuckle_segments; // 6mm

clear = 0.3;
bore_d = pin_d + clear; // 4.6mm

kn_outer = 8;
kn_inner = bore_d;

gap = 0.2;            // boolean robustness

// M3 countersunk holes (3 pcs per leaf)
cs_d_top = 6;        // countersink cone top diameter (mm)
cs_depth = 1;        // countersink depth (mm)
through_d = 3.2;    // through hole diameter (mm)
hole_pitch = 8;      // spacing along Y
hole_ys = [8, 16, 24];// based on 8mm pitch

// ---- Helper: make a cylinder whose axis is along Y ----
module cyl_y(d=1, h=1, center=true) {
    rotate([90,0,0]) cylinder(d=d, h=h, center=center);
}

// ---- Leaf plate: centered at hinge axis plane (X=0) ----
// Leaf lies in the XY plane with Z thickness.
module leaf_plate(x_sign=1) {
    // x_sign=-1 => leaf on x<0, x_sign=+1 => leaf on x>0
    translate([x_sign * (Xspan/2), 0, 0])
        cube([Xspan, Ylen, t], center=true);
}

// ---- Knuckle sleeve with bore: sleeve axis along Y ----
// Y position sets the sleeve center.
module knuckle(y_pos=0) {
    difference() {
        // outer sleeve
        translate([0, y_pos, 0]) cyl_y(d=kn_outer, h=knuckle_len, center=true);

        // bore along Y
        translate([0, y_pos, 0]) cyl_y(d=kn_inner, h=knuckle_len + 2*gap, center=true);
    }
}

// Countersunk + through hole (axis along Z), located at a given Y.
// Countersink is on the leaf side corresponding to +Z (we'll subtract; geometry stays correct).
module m3_hole_z() {
    // Through hole
    cylinder(d=through_d, h=t + 4*gap, center=true);

    // Countersink (cone frustum)
    translate([0,0, (cs_depth/2)])  // start at +Z face
        cylinder(h=cs_depth, d1=cs_d_top, d2=through_d, center=true);
}

// Build one leaf including its knuckles and screw holes,
// while also subtracting bore cylinders so shared knuckles align.
module leaf_with_knuckles_and_holes(x_sign=1, kn_positions=[], screw_far_face_sign=1) {
    // screw_far_face_sign: +1 => countersink normal to +Z face doesn't matter much for subtract,
    // we'll model only using "top at +Z" countersink. Since both leaves are at Z=0 plane,
    // subtraction will work regardless of which side is "far"; using +Z countersink is fine.
    difference() {
        union() {
            leaf_plate(x_sign);

            // Add knuckles at X=0 plane (hinge axis plane)
            for (y in kn_positions) knuckle(y);
        }

        // Subtract pin bores through the knuckles that belong to this leaf.
        // (So left and right both have the aligned holes.)
        for (y in kn_positions) {
            translate([0, y, 0]) cyl_y(d=kn_inner, h=kn_outer + 4*gap, center=true);
        }

        // Subtract 3 screw holes.
        // "Each plate side away from knuckle": given only as "far side", which is at x = x_sign*Xspan/2.
        // Use that as center for the hole axis along Z.
        for (yy in hole_ys) {
            translate([x_sign * (Xspan/2), yy, 0]) {
                // Countersink+through. Centered hole modeled along Z.
                // Ensure countersink is cut from the +Z face by positioning the cone appropriately.
                // The m3_hole_z module uses +Z face countersink by default.
                m3_hole_z();
            }
        }
    }
}

// Pin: cylinder along Y, total length 32mm (centered at Y=0).
module pin() {
    cyl_y(d=pin_d, h=pin_len, center=true);
}

// ---- Knuckle placement along Y ----
// Total knuckles separated in Y by 6mm across 30mm (5 segments).
// Centers at Y = -12, -6, 0, 6, 12 spanning 30mm.
kn_centers = [-12, -6, 0, 6, 12];

// Left: outer 2 + central 1 => [-12, 0, 12]
// Right: middle 2 => [-6, 6]
left_kn = [kn_centers[0], kn_centers[2], kn_centers[4]];
right_kn = [kn_centers[1], kn_centers[3]];

// ---- Main assembly in open position (180deg) ----
// Leaves already coplanar at Z=0 and placed on x<0 and x>0.
module butt_hinge_open180() {
    union() {
        // Left leaf
        leaf_with_knuckles_and_holes(x_sign=-1, kn_positions=left_kn);

        // Right leaf
        leaf_with_knuckles_and_holes(x_sign= 1, kn_positions=right_kn);

        // Shared pin
        translate([0, 0, 0]) pin();
    }
}

butt_hinge_open180();
i2 render_error render
render_error
7.4s · 2024/1197t · $0.0009
openscad stl render failed (exit 1): ERROR: Parser error: syntax error in file ../../../../../tmp/render-K7NwPr/input.scad, line 75
Can't parse file '/tmp/render-K7NwPr/input.scad'!

diff vs i1: +49/-57
  // Small butt hinge (3 parts assembled) in open position (180deg)
  
  $fn = 96;
  
  // ---- Parameters ----
  t = 2;                 // leaf thickness (Z)
  Ylen = 30;             // leaf length along hinge axis (Y)
  Xspan = 25;            // leaf length along opening direction (X)
  pin_d = 4;
- pin_len = 32;         // total pin length
+ pin_len = 32;          // total pin length (centered)
  
  knuckle_len = 30;     // along Y
  knuckle_segments = 5; // split into 6mm each (=> 6mm)
- seg = knuckle_len/knuckle_segments; // 6mm
+ seg = knuckle_len/knuckle_segments; // 6mm (not strictly required further)
  
  clear = 0.3;
  bore_d = pin_d + clear; // 4.6mm
  
  kn_outer = 8;
  kn_inner = bore_d;
  
- gap = 0.2;            // boolean robustness
+ gap = 0.2;             // boolean robustness
  
  // M3 countersunk holes (3 pcs per leaf)
- cs_d_top = 6;        // countersink cone top diameter (mm)
- cs_depth = 1;        // countersink depth (mm)
- through_d = 3.2;    // through hole diameter (mm)
- hole_pitch = 8;      // spacing along Y
- hole_ys = [8, 16, 24];// based on 8mm pitch
+ cs_d_top = 6;         // countersink cone top diameter (mm)
+ cs_depth = 1;         // countersink depth (mm)
+ through_d = 3.2;     // through hole diameter (mm)
+ hole_ys = [8, 16, 24];// pitch 8mm along Y
  
- // ---- Helper: make a cylinder whose axis is along Y ----
+ // ---- Helper: cylinder whose axis is along Y ----
  module cyl_y(d=1, h=1, center=true) {
      rotate([90,0,0]) cylinder(d=d, h=h, center=center);
  }
  
- // ---- Leaf plate: centered at hinge axis plane (X=0) ----
- // Leaf lies in the XY plane with Z thickness.
+ // Leaf plate centered on hinge plane at X=0.
+ // It lies in YZ plane when centered at X=0? In this model: create as XY-plane leaf with Z thickness.
  module leaf_plate(x_sign=1) {
-     // x_sign=-1 => leaf on x<0, x_sign=+1 => leaf on x>0
+     // leaf on x<0 or x>0; flat faces are parallel to X-Y plane, thickness along Z
      translate([x_sign * (Xspan/2), 0, 0])
          cube([Xspan, Ylen, t], center=true);
  }
  
- // ---- Knuckle sleeve with bore: sleeve axis along Y ----
- // Y position sets the sleeve center.
+ // Knuckle sleeve along Y at X=0, centered at given y.
+ // Bore is along Y.
  module knuckle(y_pos=0) {
      difference() {
-         // outer sleeve
-         translate([0, y_pos, 0]) cyl_y(d=kn_outer, h=knuckle_len, center=true);
- 
-         // bore along Y
-         translate([0, y_pos, 0]) cyl_y(d=kn_inner, h=knuckle_len + 2*gap, center=true);
+         translate([0, y_pos, 0])
+             cyl_y(d=kn_outer, h=knuckle_len, center=true);
+         translate([0, y_pos, 0])
+             cyl_y(d=kn_inner, h=knuckle_len + 2*gap, center=true);
      }
  }
  
- // Countersunk + through hole (axis along Z), located at a given Y.
- // Countersink is on the leaf side corresponding to +Z (we'll subtract; geometry stays correct).
+ // Countersunk + through hole along Z axis, centered at current origin.
+ // Countersink is cut from +Z face (and will still be valid as subtraction).
  module m3_hole_z() {
-     // Through hole
-     cylinder(d=through_d, h=t + 4*gap, center=true);
+     // through
+     cylinder(d=through_d, h=t + 6*gap, center=true);
  
-     // Countersink (cone frustum)
-     translate([0,0, (cs_depth/2)])  // start at +Z face
+     // countersink cone: top diameter cs_d_top at +Z face
+     // We place cone center so that its base aligns at z=+t/2 (plate top).
+     // Cone height = cs_depth.
+     translate([0,0, (t/2 - cs_depth/2)])
          cylinder(h=cs_depth, d1=cs_d_top, d2=through_d, center=true);
  }
  
- // Build one leaf including its knuckles and screw holes,
- // while also subtracting bore cylinders so shared knuckles align.
- module leaf_with_knuckles_and_holes(x_sign=1, kn_positions=[], screw_far_face_sign=1) {
-     // screw_far_face_sign: +1 => countersink normal to +Z face doesn't matter much for subtract,
-     // we'll model only using "top at +Z" countersink. Since both leaves are at Z=0 plane,
-     // subtraction will work regardless of which side is "far"; using +Z countersink is fine.
+ // One leaf with knuckles and screw holes; knuckle bores for pin are subtracted here,
+ // but since the other leaf also subtracts, this is safe (shared hole remains).
+ module leaf_with_knuckles_and_holes(x_sign=1, kn_positions=[]) {
      difference() {
          union() {
              leaf_plate(x_sign);
  
-             // Add knuckles at X=0 plane (hinge axis plane)
-             for (y in kn_positions) knuckle(y);
+             // knuckles at X=0 plane
+             for (y in kn_positions)
+                 knuckle(y);
          }
  
-         // Subtract pin bores through the knuckles that belong to this leaf.
-         // (So left and right both have the aligned holes.)
-         for (y in kn_positions) {
-             translate([0, y, 0]) cyl_y(d=kn_inner, h=kn_outer + 4*gap, center=true);
-         }
+         // Subtract the pin bore through the knuckles for this leaf
+         for (y in kn_positions)
+             translate([0, y, 0])
+                 cyl_y(d=kn_inner, h=kn_outer + 4*gap, center=true);
  
-         // Subtract 3 screw holes.
-         // "Each plate side away from knuckle": given only as "far side", which is at x = x_sign*Xspan/2.
-         // Use that as center for the hole axis along Z.
+         // Subtract 3 M3 screw holes at far side from knuckles.
+         // "far side away from knuckle" => leaf face at x = x_sign*(Xspan/2)
+         // Hole axis is along Z at that x location.
          for (yy in hole_ys) {
-             translate([x_sign * (Xspan/2), yy, 0]) {
-                 // Countersink+through. Centered hole modeled along Z.
-                 // Ensure countersink is cut from the +Z face by positioning the cone appropriately.
-                 // The m3_hole_z module uses +Z face countersink by default.
+             translate([x_sign * (Xspan/2), yy, 0])
+                 rotate([90,0,0]) {
+                     // no rotation; m3_hole_z expects axis along Z at its own position
+                     // (keep as-is)
+                 }
+             translate([x_sign * (Xspan/2), yy, 0])
                  m3_hole_z();
-             }
          }
      }
  }
  
- // Pin: cylinder along Y, total length 32mm (centered at Y=0).
+ // Pin: cylinder along Y
  module pin() {
      cyl_y(d=pin_d, h=pin_len, center=true);
  }
  
- // ---- Knuckle placement along Y ----
- // Total knuckles separated in Y by 6mm across 30mm (5 segments).
- // Centers at Y = -12, -6, 0, 6, 12 spanning 30mm.
+ // ---- Knuckle Y positions ----
+ // centers at Y = -12, -6, 0, 6, 12 spanning 30mm with 6mm steps
  kn_centers = [-12, -6, 0, 6, 12];
  
  // Left: outer 2 + central 1 => [-12, 0, 12]
  // Right: middle 2 => [-6, 6]
  left_kn = [kn_centers[0], kn_centers[2], kn_centers[4]];
  right_kn = [kn_centers[1], kn_centers[3]];
  
- // ---- Main assembly in open position (180deg) ----
- // Leaves already coplanar at Z=0 and placed on x<0 and x>0.
+ // ---- Assembly in open position (180deg) ----
  module butt_hinge_open180() {
      union() {
-         // Left leaf
          leaf_with_knuckles_and_holes(x_sign=-1, kn_positions=left_kn);
- 
-         // Right leaf
          leaf_with_knuckles_and_holes(x_sign= 1, kn_positions=right_kn);
  
-         // Shared pin
-         translate([0, 0, 0]) pin();
+         pin();
      }
  }
  
  butt_hinge_open180();
SCAD (123 lines)
// Small butt hinge (3 parts assembled) in open position (180deg)

$fn = 96;

// ---- Parameters ----
t = 2;                 // leaf thickness (Z)
Ylen = 30;             // leaf length along hinge axis (Y)
Xspan = 25;            // leaf length along opening direction (X)
pin_d = 4;
pin_len = 32;          // total pin length (centered)

knuckle_len = 30;     // along Y
knuckle_segments = 5; // split into 6mm each (=> 6mm)
seg = knuckle_len/knuckle_segments; // 6mm (not strictly required further)

clear = 0.3;
bore_d = pin_d + clear; // 4.6mm

kn_outer = 8;
kn_inner = bore_d;

gap = 0.2;             // boolean robustness

// M3 countersunk holes (3 pcs per leaf)
cs_d_top = 6;         // countersink cone top diameter (mm)
cs_depth = 1;         // countersink depth (mm)
through_d = 3.2;     // through hole diameter (mm)
hole_ys = [8, 16, 24];// pitch 8mm along Y

// ---- Helper: cylinder whose axis is along Y ----
module cyl_y(d=1, h=1, center=true) {
    rotate([90,0,0]) cylinder(d=d, h=h, center=center);
}

// Leaf plate centered on hinge plane at X=0.
// It lies in YZ plane when centered at X=0? In this model: create as XY-plane leaf with Z thickness.
module leaf_plate(x_sign=1) {
    // leaf on x<0 or x>0; flat faces are parallel to X-Y plane, thickness along Z
    translate([x_sign * (Xspan/2), 0, 0])
        cube([Xspan, Ylen, t], center=true);
}

// Knuckle sleeve along Y at X=0, centered at given y.
// Bore is along Y.
module knuckle(y_pos=0) {
    difference() {
        translate([0, y_pos, 0])
            cyl_y(d=kn_outer, h=knuckle_len, center=true);
        translate([0, y_pos, 0])
            cyl_y(d=kn_inner, h=knuckle_len + 2*gap, center=true);
    }
}

// Countersunk + through hole along Z axis, centered at current origin.
// Countersink is cut from +Z face (and will still be valid as subtraction).
module m3_hole_z() {
    // through
    cylinder(d=through_d, h=t + 6*gap, center=true);

    // countersink cone: top diameter cs_d_top at +Z face
    // We place cone center so that its base aligns at z=+t/2 (plate top).
    // Cone height = cs_depth.
    translate([0,0, (t/2 - cs_depth/2)])
        cylinder(h=cs_depth, d1=cs_d_top, d2=through_d, center=true);
}

// One leaf with knuckles and screw holes; knuckle bores for pin are subtracted here,
// but since the other leaf also subtracts, this is safe (shared hole remains).
module leaf_with_knuckles_and_holes(x_sign=1, kn_positions=[]) {
    difference() {
        union() {
            leaf_plate(x_sign);

            // knuckles at X=0 plane
            for (y in kn_positions)
                knuckle(y);
        }

        // Subtract the pin bore through the knuckles for this leaf
        for (y in kn_positions)
            translate([0, y, 0])
                cyl_y(d=kn_inner, h=kn_outer + 4*gap, center=true);

        // Subtract 3 M3 screw holes at far side from knuckles.
        // "far side away from knuckle" => leaf face at x = x_sign*(Xspan/2)
        // Hole axis is along Z at that x location.
        for (yy in hole_ys) {
            translate([x_sign * (Xspan/2), yy, 0])
                rotate([90,0,0]) {
                    // no rotation; m3_hole_z expects axis along Z at its own position
                    // (keep as-is)
                }
            translate([x_sign * (Xspan/2), yy, 0])
                m3_hole_z();
        }
    }
}

// Pin: cylinder along Y
module pin() {
    cyl_y(d=pin_d, h=pin_len, center=true);
}

// ---- Knuckle Y positions ----
// centers at Y = -12, -6, 0, 6, 12 spanning 30mm with 6mm steps
kn_centers = [-12, -6, 0, 6, 12];

// Left: outer 2 + central 1 => [-12, 0, 12]
// Right: middle 2 => [-6, 6]
left_kn = [kn_centers[0], kn_centers[2], kn_centers[4]];
right_kn = [kn_centers[1], kn_centers[3]];

// ---- Assembly in open position (180deg) ----
module butt_hinge_open180() {
    union() {
        leaf_with_knuckles_and_holes(x_sign=-1, kn_positions=left_kn);
        leaf_with_knuckles_and_holes(x_sign= 1, kn_positions=right_kn);

        pin();
    }
}

butt_hinge_open180();
i3 render_error render
render_error
7.8s · 1892/1167t · $0.0008
openscad stl render failed (exit 1): ERROR: Parser error: syntax error in file ../../../../../tmp/render-5lzP0v/input.scad, line 75
Can't parse file '/tmp/render-5lzP0v/input.scad'!

diff vs i2: +23/-25
  // Small butt hinge (3 parts assembled) in open position (180deg)
  
  $fn = 96;
  
  // ---- Parameters ----
  t = 2;                 // leaf thickness (Z)
  Ylen = 30;             // leaf length along hinge axis (Y)
  Xspan = 25;            // leaf length along opening direction (X)
+ 
  pin_d = 4;
  pin_len = 32;          // total pin length (centered)
  
  knuckle_len = 30;     // along Y
  knuckle_segments = 5; // split into 6mm each (=> 6mm)
- seg = knuckle_len/knuckle_segments; // 6mm (not strictly required further)
+ seg = knuckle_len/knuckle_segments; // 6mm
  
  clear = 0.3;
  bore_d = pin_d + clear; // 4.6mm
  
  kn_outer = 8;
  kn_inner = bore_d;
  
  gap = 0.2;             // boolean robustness
  
  // M3 countersunk holes (3 pcs per leaf)
  cs_d_top = 6;         // countersink cone top diameter (mm)
  cs_depth = 1;         // countersink depth (mm)
  through_d = 3.2;     // through hole diameter (mm)
  hole_ys = [8, 16, 24];// pitch 8mm along Y
  
  // ---- Helper: cylinder whose axis is along Y ----
  module cyl_y(d=1, h=1, center=true) {
      rotate([90,0,0]) cylinder(d=d, h=h, center=center);
  }
  
- // Leaf plate centered on hinge plane at X=0.
- // It lies in YZ plane when centered at X=0? In this model: create as XY-plane leaf with Z thickness.
+ // Leaf plate: centered at X=0; left at x<0, right at x>0.
+ // In this model leaves are cubes in X-Y plane with thickness along Z.
  module leaf_plate(x_sign=1) {
-     // leaf on x<0 or x>0; flat faces are parallel to X-Y plane, thickness along Z
      translate([x_sign * (Xspan/2), 0, 0])
          cube([Xspan, Ylen, t], center=true);
  }
  
- // Knuckle sleeve along Y at X=0, centered at given y.
+ // Knuckle sleeve along Y at X=0, centered at y_pos.
  // Bore is along Y.
  module knuckle(y_pos=0) {
      difference() {
          translate([0, y_pos, 0])
              cyl_y(d=kn_outer, h=knuckle_len, center=true);
          translate([0, y_pos, 0])
              cyl_y(d=kn_inner, h=knuckle_len + 2*gap, center=true);
      }
  }
  
- // Countersunk + through hole along Z axis, centered at current origin.
- // Countersink is cut from +Z face (and will still be valid as subtraction).
+ // M3 countersunk hole aligned along Z, centered at current origin.
+ // Countersink machined from +Z face.
  module m3_hole_z() {
-     // through
+     // Through hole
      cylinder(d=through_d, h=t + 6*gap, center=true);
  
-     // countersink cone: top diameter cs_d_top at +Z face
-     // We place cone center so that its base aligns at z=+t/2 (plate top).
-     // Cone height = cs_depth.
+     // Countersink cone from the +Z surface.
+     // Plate top surface is at z = +t/2
+     // Cone height is cs_depth. Place cone so its top is at +t/2.
      translate([0,0, (t/2 - cs_depth/2)])
          cylinder(h=cs_depth, d1=cs_d_top, d2=through_d, center=true);
  }
  
- // One leaf with knuckles and screw holes; knuckle bores for pin are subtracted here,
- // but since the other leaf also subtracts, this is safe (shared hole remains).
+ // One leaf with knuckles and screw holes.
+ // We subtract the pin bore here so the final assembly has the correct clearance.
  module leaf_with_knuckles_and_holes(x_sign=1, kn_positions=[]) {
      difference() {
          union() {
              leaf_plate(x_sign);
  
-             // knuckles at X=0 plane
+             // Knuckles
              for (y in kn_positions)
                  knuckle(y);
          }
  
-         // Subtract the pin bore through the knuckles for this leaf
+         // Subtract pin bore through knuckles (shared between both leaves)
          for (y in kn_positions)
              translate([0, y, 0])
                  cyl_y(d=kn_inner, h=kn_outer + 4*gap, center=true);
  
-         // Subtract 3 M3 screw holes at far side from knuckles.
-         // "far side away from knuckle" => leaf face at x = x_sign*(Xspan/2)
-         // Hole axis is along Z at that x location.
+         // Subtract 3 M3 holes at far side from knuckles:
+         // knuckles are at x=0 plane; far side is at x = x_sign*(Xspan/2)
          for (yy in hole_ys) {
              translate([x_sign * (Xspan/2), yy, 0])
-                 rotate([90,0,0]) {
-                     // no rotation; m3_hole_z expects axis along Z at its own position
-                     // (keep as-is)
-                 }
-             translate([x_sign * (Xspan/2), yy, 0])
                  m3_hole_z();
          }
      }
  }
  
  // Pin: cylinder along Y
  module pin() {
      cyl_y(d=pin_d, h=pin_len, center=true);
  }
  
  // ---- Knuckle Y positions ----
- // centers at Y = -12, -6, 0, 6, 12 spanning 30mm with 6mm steps
+ // centers spanning 30mm: [-12, -6, 0, 6, 12]
  kn_centers = [-12, -6, 0, 6, 12];
  
  // Left: outer 2 + central 1 => [-12, 0, 12]
  // Right: middle 2 => [-6, 6]
  left_kn = [kn_centers[0], kn_centers[2], kn_centers[4]];
  right_kn = [kn_centers[1], kn_centers[3]];
  
  // ---- Assembly in open position (180deg) ----
+ // Place both leaves so their flat faces are coplanar.
+ // With our leaves centered at X=±Xspan/2, both faces at z=0? Actually leaves are both centered at z=0,
+ // and their flat faces already coincide in z because both are modeled as thickness along Z.
+ // At 180deg open, we only need they are on opposite sides of the hinge axis.
+ // Using simple placement at x= -Xspan/2 and +Xspan/2 already matches the requested layout.
  module butt_hinge_open180() {
      union() {
          leaf_with_knuckles_and_holes(x_sign=-1, kn_positions=left_kn);
          leaf_with_knuckles_and_holes(x_sign= 1, kn_positions=right_kn);
- 
          pin();
      }
  }
  
  butt_hinge_open180();
SCAD (121 lines)
// Small butt hinge (3 parts assembled) in open position (180deg)

$fn = 96;

// ---- Parameters ----
t = 2;                 // leaf thickness (Z)
Ylen = 30;             // leaf length along hinge axis (Y)
Xspan = 25;            // leaf length along opening direction (X)

pin_d = 4;
pin_len = 32;          // total pin length (centered)

knuckle_len = 30;     // along Y
knuckle_segments = 5; // split into 6mm each (=> 6mm)
seg = knuckle_len/knuckle_segments; // 6mm

clear = 0.3;
bore_d = pin_d + clear; // 4.6mm

kn_outer = 8;
kn_inner = bore_d;

gap = 0.2;             // boolean robustness

// M3 countersunk holes (3 pcs per leaf)
cs_d_top = 6;         // countersink cone top diameter (mm)
cs_depth = 1;         // countersink depth (mm)
through_d = 3.2;     // through hole diameter (mm)
hole_ys = [8, 16, 24];// pitch 8mm along Y

// ---- Helper: cylinder whose axis is along Y ----
module cyl_y(d=1, h=1, center=true) {
    rotate([90,0,0]) cylinder(d=d, h=h, center=center);
}

// Leaf plate: centered at X=0; left at x<0, right at x>0.
// In this model leaves are cubes in X-Y plane with thickness along Z.
module leaf_plate(x_sign=1) {
    translate([x_sign * (Xspan/2), 0, 0])
        cube([Xspan, Ylen, t], center=true);
}

// Knuckle sleeve along Y at X=0, centered at y_pos.
// Bore is along Y.
module knuckle(y_pos=0) {
    difference() {
        translate([0, y_pos, 0])
            cyl_y(d=kn_outer, h=knuckle_len, center=true);
        translate([0, y_pos, 0])
            cyl_y(d=kn_inner, h=knuckle_len + 2*gap, center=true);
    }
}

// M3 countersunk hole aligned along Z, centered at current origin.
// Countersink machined from +Z face.
module m3_hole_z() {
    // Through hole
    cylinder(d=through_d, h=t + 6*gap, center=true);

    // Countersink cone from the +Z surface.
    // Plate top surface is at z = +t/2
    // Cone height is cs_depth. Place cone so its top is at +t/2.
    translate([0,0, (t/2 - cs_depth/2)])
        cylinder(h=cs_depth, d1=cs_d_top, d2=through_d, center=true);
}

// One leaf with knuckles and screw holes.
// We subtract the pin bore here so the final assembly has the correct clearance.
module leaf_with_knuckles_and_holes(x_sign=1, kn_positions=[]) {
    difference() {
        union() {
            leaf_plate(x_sign);

            // Knuckles
            for (y in kn_positions)
                knuckle(y);
        }

        // Subtract pin bore through knuckles (shared between both leaves)
        for (y in kn_positions)
            translate([0, y, 0])
                cyl_y(d=kn_inner, h=kn_outer + 4*gap, center=true);

        // Subtract 3 M3 holes at far side from knuckles:
        // knuckles are at x=0 plane; far side is at x = x_sign*(Xspan/2)
        for (yy in hole_ys) {
            translate([x_sign * (Xspan/2), yy, 0])
                m3_hole_z();
        }
    }
}

// Pin: cylinder along Y
module pin() {
    cyl_y(d=pin_d, h=pin_len, center=true);
}

// ---- Knuckle Y positions ----
// centers spanning 30mm: [-12, -6, 0, 6, 12]
kn_centers = [-12, -6, 0, 6, 12];

// Left: outer 2 + central 1 => [-12, 0, 12]
// Right: middle 2 => [-6, 6]
left_kn = [kn_centers[0], kn_centers[2], kn_centers[4]];
right_kn = [kn_centers[1], kn_centers[3]];

// ---- Assembly in open position (180deg) ----
// Place both leaves so their flat faces are coplanar.
// With our leaves centered at X=±Xspan/2, both faces at z=0? Actually leaves are both centered at z=0,
// and their flat faces already coincide in z because both are modeled as thickness along Z.
// At 180deg open, we only need they are on opposite sides of the hinge axis.
// Using simple placement at x= -Xspan/2 and +Xspan/2 already matches the requested layout.
module butt_hinge_open180() {
    union() {
        leaf_with_knuckles_and_holes(x_sign=-1, kn_positions=left_kn);
        leaf_with_knuckles_and_holes(x_sign= 1, kn_positions=right_kn);
        pin();
    }
}

butt_hinge_open180();