ambi-recurve-parts.scad raw

   1  // Ambidextrous Recurve Bow — Exploded Parts View
   2  // All dimensions in mm. Each part is a separate module.
   3  // Render with OpenSCAD: openscad ambi-recurve-parts.scad
   4  //
   5  // Parts:
   6  //   1. Riser (mulberry wood)
   7  //   2. Limb strip (316L SS, tapered, recurved tips with flared folds)
   8  //   3. M6 countersunk bolts × 3
   9  //   4. M6 threaded inserts (heli-coils) × 3
  10  //   5. Belleville washer stacks × 3 (recoil dampening at limb-riser interface)
  11  //   6. Bowstring (1.5mm SS wire rope)
  12  //   7. String dampers × 2
  13  //   8. Nocking point ferrule
  14  //   9. Arrow shaft (mulberry)
  15  //  10. Arrow point (316 SS, machined from bolt)
  16  //  11. Cam-flight nock (316L sheet)
  17  
  18  $fn = 64;
  19  
  20  // ============================================================
  21  // COLORS
  22  // ============================================================
  23  wood_color   = [0.55, 0.35, 0.18];
  24  steel_color  = [0.7, 0.72, 0.74];
  25  steel_dark   = [0.25, 0.26, 0.27];  // QPQ black nitride
  26  wire_color   = [0.6, 0.62, 0.64];
  27  rubber_color = [0.15, 0.15, 0.15];
  28  
  29  // ============================================================
  30  // 1. RISER
  31  // ============================================================
  32  module riser() {
  33      color(wood_color)
  34      difference() {
  35          // Main body — tapered profile with grip narrowing
  36          hull_riser();
  37          // Limb groove — full length slot
  38          limb_groove();
  39          // Bolt holes × 3
  40          for (i = [-1, 0, 1])
  41              translate([0, i * 30, 0])
  42                  rotate([0, 90, 0])
  43                      cylinder(d=6.5, h=80, center=true);
  44          // Arrow shelves — two symmetric cutouts at ±75mm from center
  45          for (s = [-1, 1])
  46              translate([s > 0 ? -20 : 10, s * 75, 8])
  47                  cube([12, 20, 12]);
  48          // Sight windows — mirrored cutouts above shelves
  49          for (s = [-1, 1])
  50              translate([s > 0 ? -18 : 8, s * 75 + s * 10, 4])
  51                  cube([10, 30, 20]);
  52      }
  53  }
  54  
  55  module hull_riser() {
  56      // C2-symmetric riser body, 280mm long, tapered width
  57      // Grip at center is 76mm wide, throat narrows to 31mm
  58      // Depth 28mm at grip
  59      translate([0, 0, 0])
  60      linear_extrude(height=28, center=false)
  61          riser_profile_2d();
  62  }
  63  
  64  module riser_profile_2d() {
  65      // 2D outline: widest at center (76mm), narrowing toward ends
  66      // Total length 280mm, symmetric
  67      polygon(points=[
  68          // Right side (positive X), from bottom to top
  69          [-38, -140],  // bottom tip, half-width 38 (76/2) — but narrower at ends
  70          [-15.5, -140],  // narrow at bottom end (31mm total)
  71          [-20, -120],
  72          [-28, -80],
  73          [-34, -40],
  74          [-38, 0],      // widest at center grip
  75          [-34, 40],
  76          [-28, 80],
  77          [-20, 120],
  78          [-15.5, 140],   // narrow at top end
  79          [15.5, 140],
  80          [20, 120],
  81          [28, 80],
  82          [34, 40],
  83          [38, 0],
  84          [34, -40],
  85          [28, -80],
  86          [20, -120],
  87          [15.5, -140],
  88      ]);
  89  }
  90  
  91  module limb_groove() {
  92      // Slot through riser back face, tapered width matching limb strip
  93      // Center: 44mm wide × 3.5mm deep
  94      // Ends: 40mm wide × 3.0mm deep
  95      // Runs full 280mm length
  96      for (i = [0:27]) {
  97          frac = abs(i - 13.5) / 13.5;
  98          w = 44 - frac * 4;  // 44 at center, 40 at ends
  99          d = 3.5 - frac * 0.5;  // 3.5 at center, 3.0 at ends
 100          translate([0, -140 + i * 10, 28 - d])
 101              cube([w, 10.1, d + 0.1], center=true);
 102      }
 103  }
 104  
 105  
 106  // ============================================================
 107  // 2. LIMB STRIP — Single piece 316L SS
 108  // ============================================================
 109  module limb_strip() {
 110      color(steel_dark) {
 111          // Central flat section (inside riser, 280mm)
 112          limb_flat_section();
 113          // Upper working limb with recurve
 114          translate([0, 140, 0])
 115              limb_arm(1);
 116          // Lower working limb with recurve (mirror)
 117          translate([0, -140, 0])
 118              mirror([0, 1, 0])
 119                  limb_arm(1);
 120      }
 121  }
 122  
 123  module limb_flat_section() {
 124      // Tapered strip, 280mm long, center in riser
 125      // Center: 44mm × 3.5mm, ends: 40mm × 3.0mm
 126      for (i = [0:27]) {
 127          frac = abs(i - 13.5) / 13.5;
 128          w = 44 - frac * 4;
 129          t = 3.5 - frac * 0.5;
 130          translate([0, -140 + i * 10, 28 - t])
 131              cube([w, 10.1, t], center=true);
 132      }
 133  }
 134  
 135  module limb_arm(side) {
 136      // Working limb: 300mm, tapering, with recurve at tip
 137      // Taper from riser exit to tip
 138      segments = 30;
 139      seg_len = 300 / segments;
 140  
 141      for (i = [0:segments-1]) {
 142          frac = i / segments;
 143          // Width taper: 40mm at base to 20mm at tip
 144          w = 40 - frac * 20;
 145          // Thickness taper: 3.0mm at base to 1.4mm at tip
 146          t = 3.0 - frac * 1.6;
 147  
 148          // Recurve: last 100mm bends forward (away from archer, +X direction)
 149          recurve_start = 200;  // mm from riser exit
 150          pos_y = i * seg_len;
 151          pos_x = 0;
 152          pos_z = 28 - t;
 153  
 154          if (pos_y > recurve_start) {
 155              // Recurve section — arc bending forward
 156              angle = (pos_y - recurve_start) / 100 * 70;  // up to 70 degrees
 157              r = 30;  // bend radius
 158              arc_x = r * (1 - cos(angle));
 159              arc_y = recurve_start + r * sin(angle);
 160              translate([arc_x, arc_y, pos_z])
 161                  rotate([0, 0, 0])
 162                      cube([w, seg_len, t], center=true);
 163          } else {
 164              translate([pos_x, pos_y, pos_z])
 165                  cube([w, seg_len, t], center=true);
 166          }
 167      }
 168  
 169      // Tip folds — flared string retention (J-shaped fold)
 170      translate([0, 280, 24])
 171          tip_fold();
 172  }
 173  
 174  module tip_fold() {
 175      // Flared fold at limb tip for string retention
 176      // 15-20mm folded back, flared trumpet shape
 177      color(steel_dark) {
 178          // Main fold — curved back
 179          for (a = [0:5:130]) {
 180              r = 5;  // mandrel radius
 181              translate([r * (1 - cos(a)), -r * sin(a) * 0.1, 0])
 182                  rotate([a, 0, 0])
 183                      cube([20, 1.4, 1.4], center=true);
 184          }
 185      }
 186  }
 187  
 188  
 189  // ============================================================
 190  // 3. M6 COUNTERSUNK BOLTS × 3
 191  // ============================================================
 192  module m6_bolt() {
 193      color(steel_color) {
 194          // Countersunk head
 195          cylinder(d1=12, d2=6, h=3.3);
 196          // Shaft
 197          translate([0, 0, -20])
 198              cylinder(d=6, h=20);
 199      }
 200  }
 201  
 202  
 203  // ============================================================
 204  // 4. M6 THREADED INSERTS (HELI-COILS) × 3
 205  // ============================================================
 206  module helicoil() {
 207      color(steel_color)
 208      difference() {
 209          cylinder(d=10, h=10);
 210          cylinder(d=5, h=10.1);
 211      }
 212  }
 213  
 214  
 215  // ============================================================
 216  // 5. BELLEVILLE WASHER STACK — Recoil Dampening
 217  //    Spring-valve at limb-riser interface
 218  //    Cut from SS sheet, no new material needed
 219  // ============================================================
 220  module belleville_washer() {
 221      color(steel_color)
 222      difference() {
 223          // Conical disc spring
 224          cylinder(d1=14, d2=12, h=1.2);
 225          cylinder(d=6.5, h=1.3);
 226      }
 227  }
 228  
 229  module belleville_stack() {
 230      // Stack of 4 Belleville washers in alternating orientation
 231      // Provides spring compliance + friction damping between faces
 232      for (i = [0:3]) {
 233          translate([0, 0, i * 1.0])
 234              if (i % 2 == 0)
 235                  belleville_washer();
 236              else
 237                  translate([0, 0, 1.2])
 238                      mirror([0, 0, 1])
 239                          belleville_washer();
 240      }
 241  }
 242  
 243  
 244  // ============================================================
 245  // 6. BOWSTRING — 1.5mm SS wire rope
 246  // ============================================================
 247  module bowstring() {
 248      color(wire_color) {
 249          // Main string — simplified as a cylinder arc
 250          // Brace height ~190mm, string length ~820mm
 251          translate([19, 0, 14]) // brace height offset from riser
 252              rotate([90, 0, 0])
 253                  cylinder(d=1.5, h=800, center=true);
 254  
 255          // Thimble loops at each end
 256          for (s = [-1, 1])
 257              translate([19, s * 400, 14])
 258                  rotate([0, 90, 0])
 259                      difference() {
 260                          torus(r1=6, r2=0.75);
 261                      }
 262  
 263          // Crimp ferrules at loops
 264          for (s = [-1, 1])
 265              translate([19, s * 395, 14])
 266                  cylinder(d=3, h=5, center=true);
 267      }
 268  }
 269  
 270  module torus(r1, r2) {
 271      rotate_extrude()
 272          translate([r1, 0, 0])
 273              circle(r=r2);
 274  }
 275  
 276  
 277  // ============================================================
 278  // 7. STRING DAMPERS × 2
 279  // ============================================================
 280  module string_damper() {
 281      color(rubber_color)
 282      difference() {
 283          cylinder(d=12, h=4, center=true);
 284          cylinder(d=2, h=4.1, center=true);
 285      }
 286  }
 287  
 288  
 289  // ============================================================
 290  // 8. NOCKING POINT FERRULE
 291  // ============================================================
 292  module nocking_point() {
 293      color(steel_color)
 294      difference() {
 295          cylinder(d=4, h=3, center=true);
 296          cylinder(d=1.6, h=3.1, center=true);
 297      }
 298  }
 299  
 300  
 301  // ============================================================
 302  // 9. ARROW SHAFT — Mulberry wood
 303  // ============================================================
 304  module arrow_shaft() {
 305      color(wood_color)
 306      rotate([90, 0, 0])
 307          cylinder(d=8.5, h=700);  // ~700mm shaft length
 308  }
 309  
 310  
 311  // ============================================================
 312  // 10. ARROW POINT — Machined from M12 316 SS bolt
 313  // ============================================================
 314  module arrow_point() {
 315      color(steel_dark) {
 316          // Socket (rear) — accepts shaft, 20mm deep, 8.5mm bore
 317          difference() {
 318              cylinder(d=11, h=25);
 319              translate([0, 0, -0.1])
 320                  cylinder(d=8.6, h=20.1);
 321          }
 322          // Body (middle) — 11mm diameter, 35mm long
 323          translate([0, 0, 25])
 324              cylinder(d=11, h=35);
 325          // Tip (front) — tapered cone, 30mm long
 326          translate([0, 0, 60])
 327              cylinder(d1=11, d2=1, h=30);
 328      }
 329  }
 330  
 331  
 332  // ============================================================
 333  // 11. CAM-FLIGHT NOCK — Unified component from 316L sheet
 334  // ============================================================
 335  module cam_flight_nock() {
 336      color(steel_dark) {
 337          // Cylinder base — rolled from sheet, threaded internally at 45°
 338          difference() {
 339              cylinder(d=12, h=14);
 340              // Bore for shaft
 341              cylinder(d=8.6, h=14.1);
 342          }
 343          // String groove
 344          translate([0, 0, 13])
 345              rotate([90, 0, 0])
 346                  cylinder(d=2.5, h=14, center=true);
 347  
 348          // Two wings at 180° — cam-flight surfaces
 349          for (a = [0, 180]) {
 350              rotate([0, 0, a])
 351                  translate([0, 0, 0])
 352                      cam_wing();
 353          }
 354      }
 355  }
 356  
 357  module cam_wing() {
 358      // Wing: 25mm long, 10mm tall, 0.9mm thick
 359      // Forward section: slight helical twist (cam)
 360      // Rear section: flat vane (flight surface)
 361      color(steel_dark)
 362      translate([0, -0.45, 0]) {
 363          // Cam section (forward, attached to cylinder)
 364          for (i = [0:9]) {
 365              twist = i * 2;  // slight twist for cam indexing
 366              translate([0, 0, -i * 1.5])
 367                  rotate([0, twist, 0])
 368                      cube([10, 0.9, 1.5]);
 369          }
 370          // Flight section (rearward)
 371          translate([0, 0, -25])
 372              cube([10, 0.9, 10]);
 373      }
 374  }
 375  
 376  
 377  // ============================================================
 378  // LAYOUT — Exploded view, all parts spread for visibility
 379  // ============================================================
 380  
 381  // Spacing for exploded layout
 382  explode = 60;
 383  
 384  // === BOW ASSEMBLY ===
 385  
 386  // 1. Riser
 387  translate([0, 0, 0])
 388      riser();
 389  
 390  // 2. Limb strip — offset behind riser
 391  translate([0, 0, -explode])
 392      limb_strip();
 393  
 394  // 3-4-5. Bolts, inserts, and Belleville stacks × 3
 395  for (i = [-1, 0, 1]) {
 396      // Bolt (approaching from back)
 397      translate([-explode, i * 30, 28 + 10])
 398          rotate([0, -90, 0])
 399              m6_bolt();
 400  
 401      // Belleville stack (between bolt head and limb strip)
 402      translate([-explode + 20, i * 30, 28 + 5])
 403          belleville_stack();
 404  
 405      // Heli-coil insert (in front face of riser)
 406      translate([explode, i * 30, 14])
 407          rotate([0, 90, 0])
 408              helicoil();
 409  }
 410  
 411  // 6. Bowstring — offset to the side
 412  translate([explode * 2, 0, 0])
 413      bowstring();
 414  
 415  // 7. String dampers — on the bowstring
 416  translate([explode * 2 + 19, -160, 14])
 417      string_damper();
 418  translate([explode * 2 + 19, 160, 14])
 419      string_damper();
 420  
 421  // 8. Nocking point
 422  translate([explode * 2 + 19, 0, 14])
 423      nocking_point();
 424  
 425  // === ARROW (representative, 1 of 6) ===
 426  
 427  // 9. Arrow shaft
 428  translate([0, -explode * 5, 50])
 429      arrow_shaft();
 430  
 431  // 10. Arrow point — in front of shaft
 432  translate([0, -explode * 5 - 710, 50])
 433      rotate([-90, 0, 0])
 434          arrow_point();
 435  
 436  // 11. Cam-flight nock — behind shaft
 437  translate([0, -explode * 5 + 10, 50])
 438      rotate([-90, 0, 0])
 439          cam_flight_nock();
 440  
 441  
 442  // === LABELS (comment annotations) ===
 443  // OpenSCAD doesn't support text labels in 3D easily,
 444  // but parts are spatially separated for identification:
 445  //
 446  //  Center:           Riser + Limb strip + bolts/inserts/Bellevilles
 447  //  Right (+X):       Bowstring assembly (string, dampers, nocking point)
 448  //  Front (-Y):       Arrow assembly (point, shaft, cam-flight nock)
 449  //
 450  //  The Belleville washer stacks sit between each bolt head
 451  //  and the limb strip surface. Under draw and at rest, the
 452  //  bolt preload compresses the stack. On shot release, the
 453  //  recoil impulse drives additional compression; friction
 454  //  between alternating washer faces converts the return
 455  //  energy to heat, acting as a one-way energy valve —
 456  //  the "spring valve" vibration diode described in the
 457  //  design conversation.
 458