Untitled

 avatar
unknown
plain_text
15 hours ago
14 kB
5
Indexable
//
// Dog Wheelchair (OpenSCAD) — mm, Customizer-ready (v2025-08-22c)
// - Selectable support rule: add the bar if weight >= threshold (default) or <= threshold.
// - Wheels are aligned to the axle hole of the supports (reuse Part E’s transform chain).
// - all_parts arranged in a grid with mirrored versions and print-friendly orientations.
// - Extra-long through holes for straps/screws.
//
// ------------------------------------------------------------

/* [View Mode] */
part = "wheelchair_sim"; // [wheelchair_sim:Wheelchair Simulation,part_a:Part A,part_b:Part B,part_b2:Part B2,part_c:Part C,part_d:Part D,part_e:Part E,all_parts:All Parts]

/* [Dog - Dimensions (mm)] */
// Body width (side-to-side)
dog_width = 152;     // ~6"
// Hind height
dog_height = 203;    // ~8"
// Belly to tail
dog_length = 356;    // ~14"

/* [Wheels & Hardware (mm)] */
wheel_diameter = 102;       // ~4"
screw_diameter = 6.35;      // 1/4"
tube_outer_diameter = 19.7; // 0.776" (tube OD)

/* [Frame] */
wheel_angle = 0;               // Rear upright tilt (deg): 0..15
wheel_axle_back_offset = 90;   // Axle distance behind front crossbar (mm)
clearance_back = 50;           // Shorten simulated frame at the back (mm)
ground_clearance_allowance = 25; // Ground clearance allowance (mm)

/* [Support Bar] */
auto_support = true;  // enable rule
support_rule = "heavier"; // [heavier:Add bar if weight >= threshold, lighter:Add bar if weight <= threshold]
dog_weight_kg = 5.0;
support_threshold_kg = 4.5;
force_extra_support_bar = false; // force the bar regardless of rule

/* [Joints / Bends] */
fit = 0.25;            // tube->socket clearance (mm)
joint_wall = 5;        // radial wall thickness (mm)
joint_cyl_length = 25; // straight cylinder length (mm)
bend_radius = 1;       // torus path radius (mm)
angle_1 = -30;         // lower bend arm (deg)
angle_2 = 60;          // upper bend arm (deg)

/* [Quality] */
$fa = 6;    // max facet angle
$fs = 0.5;  // min facet size

/* [Colors] */
col_parts  = "chartreuse";
col_frame  = "lightgrey";
col_wheels = "dimgray";

/* [Hidden / Derived] */
tube_radius   = tube_outer_diameter/2;
inner_radius  = tube_radius + fit;      // socket radius for tube
outer_radius  = inner_radius + joint_wall;
cyllength     = joint_cyl_length;

wheel_radius  = wheel_diameter/2;
screw_radius  = screw_diameter/2;

// Simulated frame geometry
chair_length  = dog_length - clearance_back;
chair_width   = dog_width;
chair_height  = max(5, dog_height - wheel_radius - ground_clearance_allowance);

ang = wheel_angle; // OpenSCAD uses degrees

// Support rule
bar = force_extra_support_bar ||
      (auto_support
        ? (support_rule == "heavier"
            ? (dog_weight_kg >= support_threshold_kg)
            : (dog_weight_kg <= support_threshold_kg))
        : false);

// Axle position along Y (negative is backward)
chairwheeldistance = wheel_axle_back_offset;

// Grid spacing for "all_parts"
grid_dx = 160;
grid_dy = 110;

/* ---------- Utilities ---------- */
module drill_z(r, h, center=false){ cylinder(r=r, h=h, center=center); }
module drill_x(r, h, center=false){ rotate(90, [0,1,0]) cylinder(r=r, h=h, center=center); }
module drill_y(r, h, center=false){ rotate(90, [1,0,0]) cylinder(r=r, h=h, center=center); }

/* ---------- Wheel (disc) ---------- */
module wheel_disc_raw(){ // flat disc without extra transforms
  color(col_wheels) scale([1,1,0.25]) sphere(r=wheel_radius);
}

/* ---------- Bends (hex section) ---------- */
module bend(){
  difference(){
    rotate_extrude(){ translate([bend_radius + outer_radius, 0, 0]) circle(r=outer_radius, $fn=6); }
    rotate_extrude(){ translate([bend_radius + outer_radius, 0, 0]) circle(r=inner_radius); }
    rotate([0,0,angle_1]) translate([-100,-100,-50]) cube([300,100,100]);
    rotate([0,0,angle_2]) translate([-100,   0,-50]) cube([300,100,100]);
  }
}

module bend2(){
  intersection(){
    rotate([0,0,-30]) translate([0,0,-50]) cube([100,100,100]);
    difference(){
      rotate_extrude(){ translate([bend_radius + outer_radius, 0, 0]) rotate([0,0,90]) circle(r=outer_radius, $fn=6); }
      rotate_extrude(){ translate([bend_radius + outer_radius, 0, 0]) circle(r=inner_radius); }
      rotate([0,0,angle_1]) translate([-100,-100,-50]) cube([300,100,100]);
      rotate([0,0,angle_2]) translate([-100,   0,-50]) cube([300,100,100]);
    }
  }
}

/* ---------- Strap blocks + through-holes ---------- */
module strapholes(){ translate([-15,33,-50]) drill_z(screw_radius, 200); }

module straps1(){
  difference(){
    union(){ translate([-25.38,28.9,-10]) cube([20,20,20]); }
    union(){
      rotate(-30,[1,0,0]) translate([-40,-100,20.926]) cube([200,200,20]);
      rotate( 30,[1,0,0]) translate([-40,-100,-43.63]) cube([200,200,22.7]);
      translate([-40,39,-20]) cube([200,200,50]);
    }
    rotate( 10,[1,0,0]) strapholes();
  }
}

module straps2(){
  difference(){
    union(){ translate([-25.38,28.9,-10]) cube([12,20,20]); }
    union(){
      rotate(-30,[1,0,0]) translate([-40,-100,20.926]) cube([200,200,20]);
      rotate( 30,[1,0,0]) translate([-40,-100,-43.63]) cube([200,200,22.7]);
    }
    translate([-40,39,-20]) cube([200,200,50]);
    rotate(90,[0,1,0]) translate([0,33,-50]) drill_z(screw_radius, 400);
  }
}

module straps3(){
  difference(){
    union(){ translate([-25.38,28.9,-10]) cube([20,20,20]); }
    union(){
      rotate(-30,[1,0,0]) translate([-40,-100,20.926]) cube([200,200,20]);
      rotate( 30,[1,0,0]) translate([-40,-100,-43.63]) cube([200,200,22.7]);
      translate([-40,39,-20]) cube([200,200,50]);
    }
    rotate(-10,[1,0,0]) strapholes();
  }
}

/* ---------- Printable parts (A..E, B2) ---------- */
module partA(){
  color(col_parts)
  union(){
    rotate([0,0,angle_1]) translate([bend_radius+outer_radius,0.02,0]) rotate([90,90,0])
      difference(){ cylinder(r=outer_radius, h=cyllength, $fn=6); translate([0,0,-1]) cylinder(r=inner_radius, h=cyllength+5); }
    rotate([0,0,angle_2]) translate([bend_radius+outer_radius,-0.02,0]) rotate([-90,90,0])
      difference(){ cylinder(r=outer_radius, h=cyllength, $fn=6); translate([0,0,-1]) cylinder(r=inner_radius, h=cyllength+5); }
    bend2();
    rotate(-30,[0,0,1]) straps1();
  }
}

module partB_common(_use_straps3=false){
  color(col_parts)
  union(){
    rotate(120,[0,0,1])
    union(){
      rotate([0,0,angle_1]) translate([bend_radius+outer_radius,0.02,0]) rotate([90,0,ang])
        difference(){ cylinder(r=outer_radius, h=cyllength, $fn=6); translate([0,0,-10]) cylinder(r=inner_radius, h=cyllength+15); }
      rotate([0,0,angle_2]) translate([bend_radius+outer_radius,-38,0]) rotate([-90,0,0])
        difference(){ cylinder(r=outer_radius, h=cyllength*1.75, $fn=6); translate([0,0,-1]) cylinder(r=inner_radius, h=cyllength*2+5); }
      difference(){
        bend();
        rotate([0,0,angle_2]) translate([bend_radius+outer_radius,-40,0]) rotate([-90,0,0])
          translate([0,0,-1]) cylinder(r=inner_radius, h=cyllength*2+5);
      }
    }
    rotate(90,[0,1,0]) rotate(-90,[0,0,1]) translate([-12.62,-15.95,-15.95]){
      if(_use_straps3) straps3(); else straps1();
    }
  }
}
module partB(){  partB_common(false); }
module partB2(){ mirror([1,0,0]) partB_common(true); }

module partC(){
  color(col_parts)
  difference(){
    rotate(120,[0,0,1])
      rotate([0,0,angle_1]) translate([bend_radius+outer_radius,0.02,0]) rotate([90,0,0]) rotate([0,0,90])
        difference(){ cylinder(r=outer_radius, h=cyllength-5.4, $fn=6); translate([0,0,-10]) cylinder(r=inner_radius, h=cyllength+60); }
  }
  translate([25.36,0,0]) straps1();
}

module partD(){
  color(col_parts)
  difference(){
    rotate(120,[0,0,1])
      rotate([0,0,angle_1]) translate([bend_radius+outer_radius,0.02,0]) rotate([90,0,0]) rotate([0,0,90])
        difference(){ cylinder(r=outer_radius, h=cyllength+20, $fn=6); translate([0,0,10]) cylinder(r=inner_radius, h=cyllength+25); }
  }
  translate([50.76,0,0]) straps1();
  translate([25.36,0,0]) straps2();
}

module partE(){
  color(col_parts)
  translate([0,0,-tan(ang)*2.2]) rotate(ang,[1,0,0])
  difference(){
    rotate(120,[0,0,1])
    union(){
      if(bar){
        rotate([0,0,angle_1]) translate([bend_radius+outer_radius,0.02,0]) rotate([90,90,0])
          difference(){ cylinder(r=outer_radius, h=cyllength, $fn=6); translate([0,0,-1]) cylinder(r=inner_radius, h=cyllength+5); }
      }
      rotate([0,0,angle_2]) translate([bend_radius+outer_radius,-43,0]) rotate([-90,90,0])
        difference(){
          cylinder(r=outer_radius, h=cyllength*1.75 + 25.4, $fn=6);
          translate([0,0,-1]) cylinder(r=inner_radius, h=cyllength*2+5);
          // axle hole (very long)
          translate([0,50,60]) rotate(90,[1,0,0]) drill_z(screw_radius, 400);
        }
      if(bar){
        difference(){
          bend2();
          rotate([0,0,angle_2]) translate([bend_radius+outer_radius,-40,0]) rotate([-90,0,0])
            translate([0,0,-1]) cylinder(r=inner_radius, h=cyllength*2+5);
        }
      }
    }
  }
}

/* ---------- Wheels from Part E pose ---------- */
// reproduces the same transforms to the axle, then places the disc
module wheel_from_partE_local(){
  translate([0,0,-tan(ang)*2.2])
  rotate(ang,[1,0,0])
  rotate(120,[0,0,1])
  rotate([0,0,angle_2])
  translate([bend_radius + outer_radius, -43, 0])
  rotate([-90,90,0])
  translate([0,50,60])
  rotate(90,[1,0,0])
  wheel_disc_raw();
}

module wheels_from_partE_pair(){
  // right
  translate([outer_radius , -chairwheeldistance, -chair_height - outer_radius])
  rotate(90,[1,0,0]) wheel_from_partE_local();
  // left (mirrored; same chain as the assembly of Part E)
  mirror([1,0,0])
    translate([-chair_width + outer_radius , -chairwheeldistance, -chair_height - outer_radius])
    rotate(90,[1,0,0]) wheel_from_partE_local();
}

/* ---------- Simulated frame ---------- */
module wheelchair(){
  union(){
    // side rails
    translate([ chair_width, 0 ,0]) rotate(90,[1,0,0]) cylinder(r=inner_radius, h=chair_length);
    translate([ 0, 0 ,0])          rotate(90,[1,0,0]) cylinder(r=inner_radius, h=chair_length);
    // front crossbar
    rotate(90,[0,1,0]) cylinder(r=inner_radius, h=chair_width);
    // rear uprights (angled)
    rotate(ang,[1,0,0]) translate([ 0, -chairwheeldistance , -chair_height]) cylinder(r=inner_radius, h=chair_height);
    mirror([1,0,0]) rotate(ang,[1,0,0]) translate([ -chair_width, -chairwheeldistance , -chair_height]) cylinder(r=inner_radius, h=chair_height);
    // extra support bar (if enabled)
    if(bar){ rotate(90,[0,1,0]) translate([ chair_height, -chairwheeldistance , 0]) cylinder(r=inner_radius, h=chair_width); }
  }
  // wheels aligned to Part E axle
  wheels_from_partE_pair();
}

/* ---------- Print orientations (used by all_parts) ---------- */
module orient_A(){ rotate(-90,[1,0,0]) translate([-80,-30,25]) rotate(120,[0,0,1]) partA(); }
module orient_A_m(){ rotate(-90,[1,0,0]) translate([-80,-30,25]) rotate(120,[0,0,1]) mirror([1,0,0]) partA(); }

module orient_B(){ translate([-90,-20,13]) rotate(180,[1,0,0]) partB(); }
module orient_B2(){ translate([-90,-20,13]) rotate(180,[1,0,0]) partB2(); }

module orient_C(){ translate([-40,10,-3])  rotate(90,[1,0,0]) partC(); }
module orient_C_m(){ translate([-40,10,-3])  rotate(90,[1,0,0]) mirror([1,0,0]) partC(); }

module orient_D(){ translate([30,-35,-3])  rotate(90,[1,0,0]) partD(); }
module orient_D_m(){ translate([30,-35,-3])  rotate(90,[1,0,0]) mirror([1,0,0]) partD(); }

module orient_E(){ translate([-10,-35,29]) rotate(90,[0,0,1]) rotate(-90,[0,1,0]) partE(); }
module orient_E_m(){ translate([-10,-35,29]) rotate(90,[0,0,1]) rotate(-90,[0,1,0]) mirror([1,0,0]) partE(); }

/* ---------- RENDER (selector) ---------- */
print_part();

module print_part(){
  if (part == "wheelchair_sim"){
    union(){
      // part A + mirror
      translate([outer_radius,-outer_radius,0]) rotate(120,[0,0,1]) partA();
      mirror([1,0,0]) translate([outer_radius - chair_width,-outer_radius,0]) rotate(120,[0,0,1]) partA();
      // part B + mirror
      translate([0, -chairwheeldistance - outer_radius , -outer_radius]) rotate(90,[0,1,0]) partB();
      mirror([1,0,0]) translate([ -chair_width, -chairwheeldistance - outer_radius , -outer_radius]) rotate(90,[0,1,0]) partB();
      // part C + mirror
      translate([outer_radius , -chairwheeldistance - 80  , 0]) rotate(90,[0,0,1]) partC();
      mirror([1,0,0]) translate([-chair_width + outer_radius , -chairwheeldistance - 80  , 0]) rotate(90,[0,0,1]) partC();
      // part D + mirror
      translate([outer_radius , -chair_length , 0]) rotate(90,[0,0,1]) partD();
      mirror([1,0,0]) translate([-chair_width + outer_radius , -chair_length , 0]) rotate(90,[0,0,1]) partD();
      // part E + mirror
      translate([outer_radius , -chairwheeldistance  , -chair_height - outer_radius]) rotate(90,[1,0,0]) partE();
      mirror([1,0,0]) translate([ -chair_width + outer_radius , -chairwheeldistance  , -chair_height - outer_radius]) rotate(90,[1,0,0]) partE();
      // simulated frame
      color(col_frame) wheelchair();
    }
  }
  else if (part == "part_a"){ orient_A(); }
  else if (part == "part_b"){ orient_B(); }
  else if (part == "part_b2"){ orient_B2(); }
  else if (part == "part_c"){ orient_C(); }
  else if (part == "part_d"){ orient_D(); }
  else if (part == "part_e"){ orient_E(); }
  else if (part == "all_parts"){
    union(){
      // row 1
      translate([0,        0,0]) orient_A();
      translate([grid_dx,  0,0]) orient_A_m();
      // row 2
      translate([0,       -grid_dy,0]) orient_B();
      translate([grid_dx, -grid_dy,0]) orient_B2();
      // row 3
      translate([0,       -2*grid_dy,0]) orient_C();
      translate([grid_dx, -2*grid_dy,0]) orient_C_m();
      // row 4
      translate([0,       -3*grid_dy,0]) orient_D();
      translate([grid_dx, -3*grid_dy,0]) orient_D_m();
      // row 5
      translate([0,       -4*grid_dy,0]) orient_E();
      translate([grid_dx, -4*grid_dy,0]) orient_E_m();
    }
  }
}

Editor is loading...
Leave a Comment