Restructure files into src

This commit is contained in:
Dejvino
2021-01-20 09:23:46 +01:00
parent f17455be4f
commit 4d0931df73
5 changed files with 45 additions and 41 deletions
+34
View File
@@ -0,0 +1,34 @@
/*
export=0; // <-- prepend to the main file to activate the export
*/
function is_not_export() = is_undef(export) || export == 0;
function is_export() = !is_not_export();
function is_model_strict(m) = is_export() && export == m;
function is_model(m) = is_not_export() || export == m;
MODEL_DEMO=0;
// Harness
MODEL_HARNESS_LEFT=101;
MODEL_HARNESS_RIGHT=102;
MODEL_HARNESS_BOTTOM=103;
MODEL_HARNESS_BOTTOM_PIP=104;
MODEL_HARNESS_TOP=105;
MODEL_HARNESS_SLIDER_FRONT=106;
MODEL_HARNESS_SLIDER_BACK=107;
MODEL_HARNESS_BUTTONS=108;
// Platform
MODEL_STRAP_PLATFORM_BASE=210;
MODEL_STRAP_PLATFORM_RIB=211;
MODEL_STRAP_PLATFORM_RIB_BRACE=212;
MODEL_STRAP_SECONDARY=213;
// Strap
MODEL_LINKS=301;
MODEL_CLIP_A=302;
MODEL_CLIP_B=303;
MODEL_CLIP_RATCHETING=304;
MODEL_CLIP_RATCHETING_A=305;
MODEL_CLIP_RATCHETING_B=306;
+428
View File
@@ -0,0 +1,428 @@
include <export.scad>
// dependency: https://github.com/revarbat/BOSL
include <BOSL/constants.scad>
use <BOSL/transforms.scad>
use <BOSL/shapes.scad>
use <BOSL/masks.scad>
use <BOSL/sliders.scad>
// DEBUG:
//validation = 1;
XRAY_POSITIVE=1;
XRAY_BACKPLANE=2;
XRAY_BOTTOM=3;
//xray = 2;
function get_phone_size() = [161.2, 77.2, 10];
function use_slideout_backplane() = is_model_strict(MODEL_HARNESS_BOTTOM_PIP) || is_model_strict(MODEL_HARNESS_LEFT) || is_model_strict(MODEL_HARNESS_RIGHT);
backplane_pip_slideout=10;
module cubi(s, fillet=0, edges=EDGES_ALL) {
if ($preview) {
cube(s, center=true);
} else {
cuboid(s, fillet=fillet, edges=edges);
}
}
module dotted_grill_cutout(vents_area, vents_x=10, vents_y=10, mesh=1.5, cut_corners=false) {
function is_corner(x, y, xm, ym) = (x == 0 || x == xm) && (y == 0 || y == ym);
vent_size=[vents_area.x/vents_x-mesh, vents_area.y/vents_y-mesh, vents_area.z];
translate([-vents_area.x/2 - vent_size.x/2, vents_area.y/2 - vent_size.y/2, 0])
for (x=[0:vents_x-1]) {
for (y=[0:vents_y-1]) {
if (!cut_corners || !is_corner(x, y, vents_x-1, vents_y-1)) {
right(x*(vent_size.x+mesh))
fwd(y*(vent_size.y+mesh))
cubi(vent_size, fillet=min(vent_size.x/2, vent_size.y/2));
}
}
}
}
module phone() {
s=get_phone_size();
color("gray")
cubi(s, fillet=5);
}
module arm() {
$fn=6;
s=[210, 55, 50];
color("SaddleBrown")
down(s.z/2 + get_phone_size().z/2) cubi(s, fillet=20);
}
module phone_harness() {
ops=get_phone_size();
ps=[ops.x+0.2, ops.y+0.2, ops.z+0.2];
shell_wall=3;
shell_rim_wall=3;
rim_edge_thickness=1.5;
rim_edge_tolerance=0.4;
expose_back_camera=true;
screwmount_screw=3;
harness_divider=[1, 0, 1.3];
harness_size=[ps.x+shell_wall*2, ps.y+shell_wall*2, ps.z+shell_wall*2];
rim_size=[harness_size.x+2*shell_rim_wall, harness_size.y+2*shell_rim_wall, 8];
w=shell_wall;
f=2;
rf=5;
hs=harness_size;
backplane_rim_size=[40, ps.y*0.95, shell_wall/2];
backplane_teeth=6;
// ==== SHELL ====
module shell() {
$fn = $preview ? 6 : 30;
difference() {
cubi(hs, fillet=f);
cubi(ps, fillet=f);
}
shell_rim();
shell_screwmounts();
}
module shell_rim() {
$fn = $preview ? 6 : 30;
w=shell_rim_wall;
s=rim_size;
intersection() {
difference() {
cubi(s, fillet=rf, edges=EDGES_Z_ALL);
cubi(ps, fillet=f, edges=EDGES_Z_ALL);
}
cubi(s, fillet=1);
}
rail_extension=10;
fwd(hs.y/2) xrot(90) harness_rail(slider_len_front+rail_extension);
back(hs.y/2) xrot(-90) harness_rail(slider_len_back+rail_extension);
}
module shell_rim_edge(thickness, groove, tolerance=rim_edge_tolerance) {
$fn = $preview ? 6 : 30;
w=thickness + (groove ? tolerance : 0);
offset=(groove ? 0 : tolerance/2);
res=[hs.x+2*(w+offset), hs.y+2*(w+offset), 3];
resi=[hs.x+2*offset, hs.y+2*offset, res.z+1];
up(0.0) difference() {
intersection() {
cubi(res, fillet=rf, edges=EDGES_Z_ALL);
cubi(res, fillet=(groove?1:1.5), edges=EDGES_BOTTOM);
}
cubi(resi, fillet=rf, edges=EDGES_Z_ALL);
}
}
module foreach_screwmount() {
for(x = [0:1]) for (y = [0:1]) {
translate([(-0.5+x)*ps.x, (-0.5+y)*ps.y, -hs.z/2])
children();
}
}
module shell_screwmounts() {
$fn = $preview ? 6 : 30;
r=3;
foreach_screwmount() {
cylinder(r=r, h=hs.z);
}
}
module shell_screwmounts_holes() {
$fn = $preview ? 6 : 30;
foreach_screwmount() {
up(w) cylinder(d2=screwmount_screw, d1=screwmount_screw*0.5, h=hs.z+1);
up(hs.z-1) cylinder(d=screwmount_screw+1.5, h=5);
}
}
module shell_backplane(groove) {
module groove_scale() { scale([groove?1.05:1, groove?1.05:1, groove?1.2:1]) children(); }
if (use_slideout_backplane()) {
down(hs.z/2 - shell_wall/3) up(backplane_rim_size.z/2) right(harness_divider.x) {
back(backplane_rim_size.y/2) {
teeth=backplane_teeth;
segment=backplane_rim_size.y/teeth;
tooth_size=[backplane_rim_size.x, segment/2, backplane_rim_size.z];
joiner_base=5;
joiner_size=[joiner_base + (groove?backplane_pip_slideout:0), segment*1.5, backplane_rim_size.z];
for (i = [0:teeth-1]) {
fwd(i*segment) fwd(tooth_size.y) {
groove_scale() cubi(tooth_size, fillet=0.5, edges=EDGES_X_ALL);
if (i%2 == 0) {
left(backplane_rim_size.x/2 + joiner_base/2) fwd(joiner_size.y/3) left(-joiner_size.x/2) groove_scale() cubi(joiner_size, fillet=2, edges=EDGES_Z_ALL);
}
}
}
}
}
}
}
// ==== SHELL SLIDER AND RAIL ====
rail_angle=36;
rail_wall=1;
slider_slop=0.1;
slider_len_back=hs.x*0.3;
slider_len_front=hs.x*0.15;
module harness_slider(l) {
base=2;
ss=[l, shell_rim_wall, rim_size.z+rail_wall*2];
up(ss.y + base) xrot(180) difference() {
slider(l=ss.x, w=ss.z, h=ss.y, base=base, chamfer=0.9, wall=2, ang=rail_angle, slop=slider_slop, orient=ORIENT_X, align=V_UP);
screws=2;
screws_area_l=0.7*l;
for (i=[0:screws-1]) {
$fn=$preview ? 6 : 16;
right(-screws_area_l/2 + screws_area_l/(screws-1) * i) cylinder(d2=screwmount_screw*0.5, d1=screwmount_screw, h=ss.y*0.7);
}
}
}
module harness_rail(l) {
sw=2;
ss=[l, shell_rim_wall, rim_size.z+rail_wall*2];
rail(l=ss.x, w=ss.z, h=ss.y, chamfer=0.5, ang=rail_angle, orient=ORIENT_X, align=V_UP);
}
// ==== SHELL CUTOUTS ====
module shell_cutouts() {
top_cutout();
bottom_cutout();
left_cutout();
right_cutout();
front_cutout();
shell_screwmounts_holes();
}
// -- TOP --
module screen_cutout() {
$fn=$preview ? 4 : 12;
s=[138, 69, 12];
b = 10;
s1=[s.x, s.y];
s2=[s.x+b, s.y+b];
h=s.z;
up(5) rounded_prismoid(size1=s1, size2=s2, h=h, r1=1, r2=15);
}
top_offset=6.5;
module top_speaker_cutout() {
s=[3, 12, 100];
right(ps.x/2 - top_offset) up(s.z/2 - ps.z/3) cubi(s, fillet=1);
}
module front_camera_cutout() {
$fn = $preview ? 6 : 30;
d=5;
s=[d, d, 100];
right(ps.x/2 - top_offset) fwd(11.5) cylinder(d=s.x, h=s.z);
}
module leds_cutout() {
s=[4, 14, 100];
right(ps.x/2 - top_offset) up(s.z/2 - ps.z/3) back(23) cubi(s, fillet=1);
}
module top_cutout() {
screen_cutout();
top_speaker_cutout();
front_camera_cutout();
leds_cutout();
}
// -- BOTTOM --
module back_camera_cutout() {
s=[13, 25, expose_back_camera ? 100 : 11];
right(ps.x/2 - 7.5) fwd(ps.y/2 - 24.5) down(s.z/2 - ps.z/3) cubi(s, fillet=6, edges=EDGES_Z_ALL);
}
module bottom_speaker_cutout() {
s=[8, 49, 100];
left(ps.x/2 - 13)
down(s.z/2 - ps.z/3)
dotted_grill_cutout(s, vents_x=4, vents_y=8, cut_corners=true, mesh=1);
}
module bottom_vents_cutout() {
vents_x=10;
vents_y=6;
vents_area=[35, 50, 10];
vents_pos=[45, 0, -ps.z/2];
mesh=1.5;
translate(vents_pos)
dotted_grill_cutout(vents_area, vents_x=vents_x, vents_y=vents_y, mesh=mesh, cut_corners=true);
}
module bottom_cutout() {
back_camera_cutout();
bottom_speaker_cutout();
bottom_vents_cutout();
}
// -- RIGHT --
module headphones_cutout() {
$fn = $preview ? 10 : 30;
d1=8.8;
d2=14;
p=[ps.x/2, ps.y/2-24, -0.88];
h=22;
translate(p) yrot(90) down(10) cylinder(h=h, d1=d1, d2=d2);
}
module right_cutout() {
headphones_cutout();
}
// -- LEFT --
module usbc_cutout() {
s=[20, 20, 7];
left(ps.x/2) down(2) cubi(s, fillet=1);
}
module left_cutout() {
usbc_cutout();
}
// -- FRONT --
buttons_cutout_size=[42, 100, 4.5];
buttons_cutout_pos=[ps.x/2 - 44.5, -ps.y/2 - 3, 0.25];
module buttons_cutout() {
s=buttons_cutout_size;
p=buttons_cutout_pos;
translate(p) cubi(s, fillet=1);
}
module front_cutout() {
buttons_cutout();
}
module front_buttons(socket) {
s=[buttons_cutout_size.x-2, 4, buttons_cutout_size.z-0.5];
p=buttons_cutout_pos;
t=socket ? 0.2 : 0;
pin_size=[3 + t, 3 + t, s.z+2 + t/2];
touch_size=[2, s.y, 2];
touch_power_size=[3, touch_size.y, touch_size.z];
translate(p) {
cs=[4, s.y, s.z];
left(5) {
bs=[13, s.y, s.z];
left(bs.x/6) cubi(pin_size);
left(bs.x/2) {
difference() {
cubi(bs);
back(1) cubi(cs);
}
}
fwd(1) left(bs.x*0.8) cubi(touch_power_size, fillet=1);
}
right(8) {
bs=[18, s.y, s.z];
cubi(pin_size);
difference() {
cubi(bs);
back(1) {
left(bs.x/4) cubi(cs);
right(bs.x/4) cubi(cs);
}
}
fwd(1) {
left(bs.x*0.4) cubi(touch_size, fillet=1);
right(bs.x*0.4) cubi(touch_size, fillet=1);
}
}
}
}
// ==== MODEL ====
divider=harness_divider;
module model_harness_left() {
intersection() {
intersection() {
translate(divider) downcube([1000, 1000, 1000]);
translate(divider) leftcube([1000, 1000, 1000]);
}
difference() {
shell();
shell_rim_edge(rim_edge_thickness, groove=true, tolerance=rim_edge_tolerance);
shell_cutouts();
shell_backplane(groove=true);
}
}
}
module model_harness_right() {
intersection() {
intersection() {
translate(divider) downcube([1000, 1000, 1000]);
translate(divider) rightcube([1000, 1000, 1000]);
}
difference() {
shell();
shell_rim_edge(rim_edge_thickness, groove=true, tolerance=rim_edge_tolerance);
shell_cutouts();
front_buttons(socket=true);
}
}
shell_backplane(groove=false);
}
module model_harness_top() {
intersection() {
translate(divider) upcube([1000, 1000, 1000]);
difference() {
shell();
shell_cutouts();
front_buttons(socket=true);
}
}
difference() {
shell_rim_edge(rim_edge_thickness, groove=false);
shell_cutouts();
front_buttons(socket=true);
}
}
module model_harness_slider_front() {
difference() {
fwd(hs.y/2) xrot(90) harness_slider(slider_len_front);
front_cutout();
}
}
module model_harness_slider_back() {
back(hs.y/2) xrot(-90) harness_slider(slider_len_back);
}
module model_harness_buttons() {
front_buttons(socket=false);
}
if (is_model(MODEL_HARNESS_LEFT)) model_harness_left();
if (is_model(MODEL_HARNESS_RIGHT)) model_harness_right();
if (is_model_strict(MODEL_HARNESS_BOTTOM)) {
model_harness_left();
model_harness_right();
}
if (is_model_strict(MODEL_HARNESS_BOTTOM_PIP)) {
model_harness_left();
right(backplane_pip_slideout) model_harness_right();
}
if (is_model(MODEL_HARNESS_TOP)) model_harness_top();
if (is_model(MODEL_HARNESS_SLIDER_FRONT)) model_harness_slider_front();
if (is_model(MODEL_HARNESS_SLIDER_BACK)) model_harness_slider_back();
if (is_model(MODEL_HARNESS_BUTTONS)) model_harness_buttons();
}
module model() {
phone_harness();
}
if (!is_undef(validation)) {
intersection() {
phone();
model();
}
} else {
intersection() {
if (!is_undef(xray)) {
if (xray == XRAY_POSITIVE) {
span_cube([0,1000], [0,1000], [-1000,1000]);
} else if (abs(xray) == XRAY_BACKPLANE) {
span_cube([-1000,1000], [-1000,1000], [-1000*sign(xray),-6]);
} else if (xray == XRAY_BOTTOM) {
span_cube([-1000,1000], [-1000,1000], [-1000,0]);
}
}
union() {
if (is_not_export()) {
//phone();
//arm();
}
model();
}
}
}
+6
View File
@@ -0,0 +1,6 @@
export=0;
include <export.scad>
include <harness.scad>
include <platform.scad>
include <strap.scad>
+123
View File
@@ -0,0 +1,123 @@
// dependency: https://github.com/revarbat/BOSL
include <BOSL/constants.scad>
use <BOSL/transforms.scad>
use <BOSL/shapes.scad>
use <BOSL/masks.scad>
use <BOSL/sliders.scad>
// DEBUG:
//validation = 1;
//xray = 1;
function get_phone_size() = [160, 76.7, 10];
module arm() {
$fn=$preview ? 10 : 30;
arm_size=[200, 55, 40];
color("gray")
down(arm_size.z/2) {
cuboid(arm_size, fillet=16, edges=EDGES_X_ALL);
left(arm_size.x*0.6) scale([1, 1, 0.8]) yrot(90) cylinder(d1=arm_size.y*1.4, d2=arm_size.y*0.95, h=arm_size.x/2);
}
}
module strap_platform() {
base_size=[40, 70, 2];
rib_thickness=5;
rib_height=20;
rib_pos=[base_size.x/2 - rib_thickness, 0, -1.3];
brace_size=[base_size.x, 3.6, 4.8];
brace_pos=[0, base_size.y/2 - 4, -1.3];
module platform_base() {
cutout_size=[(base_size.x-rib_thickness*2 - 2*(base_size.x/2-rib_pos.x)), (base_size.y - 5), 2*base_size.z];
difference() {
down(base_size.z/2) cuboid(base_size, fillet=2, edges=EDGES_Z_ALL);
down(base_size.z/2) cuboid(cutout_size, fillet=2, edges=EDGES_Z_ALL);
model_rib_left(socket=true);
model_rib_right(socket=true);
}
}
module platform_rib(socket=false) {
rib_size=[rib_thickness, base_size.y - 2, rib_height];
difference() {
union() {
difference() {
down(rib_size.z/2) scale(socket ? 1.01 : 1) sparse_strut(h=rib_size.z, l=rib_size.y, thick=rib_size.x, strut=1.2, maxang=40, max_bridge=4);
arm();
}
difference() {
intersection() {
down(rib_size.z/2) cube(rib_size, center=true);
scale(1.07) arm();
}
down(2) scale(1.0) arm();
}
}
fwd(brace_pos.y) platform_rib_brace(socket=true);
back(brace_pos.y) platform_rib_brace(socket=true);
}
}
module platform_rib_brace(socket=false) {
down(rib_height - 1.2 - brace_size.z/2) scale(socket ? 1.02 : 1) cuboid(brace_size, fillet=1, edges=EDGES_X_ALL);
}
module model_rib_left(socket=false) {
left(rib_pos.x) up(rib_pos.z) platform_rib(socket=socket);
}
module model_rib_right(socket=false) {
right(rib_pos.x) up(rib_pos.z) platform_rib(socket=socket);
}
module model_brace_front() {
fwd(brace_pos.y) up(brace_pos.z) platform_rib_brace();
}
module model_brace_back() {
back(brace_pos.y) up(brace_pos.z) platform_rib_brace();
}
if (is_model(MODEL_STRAP_PLATFORM_BASE)) platform_base();
if (is_model(MODEL_STRAP_PLATFORM_RIB)) model_rib_left();
if (is_model(MODEL_STRAP_PLATFORM_RIB_BRACE)) model_brace_front();
if (is_not_export()) {
model_rib_right();
model_brace_back();
}
}
module strap_secondary() {
size=[40, 15, 10];
size_base=[size.x, size.y];
size_top=[size.x * 0.9, size.y * 0.4];
cutout_size=[size.x - 10, size.y*10, size.z - 4];
module anchor() {
difference() {
xrot(180) rounded_prismoid(size1=size_base, size2=size_top, h=size.z, r=5);
down(size.z/2) cube(cutout_size, center=true);
}
}
anchor_pos=[60, 30, 0];
module anchor_front() {
left(anchor_pos.x) fwd(anchor_pos.y) anchor();
}
module anchor_back() {
left(anchor_pos.x) back(anchor_pos.y) anchor();
}
if (is_model(MODEL_STRAP_SECONDARY)) anchor_front();
if (is_not_export()) anchor_back();
}
module model_strap_platform() {
strap_platform();
}
module model_strap_secondary() {
strap_secondary();
}
module model_arm() {
if (is_not_export()) down(3) arm();
}
model_strap_platform();
model_strap_secondary();
model_arm();
+343
View File
@@ -0,0 +1,343 @@
links_count=3; // [1..20]
include_terminal=true; // [true,false]
include <export.scad>
//validation=1;
VALIDATE_INTERSECTION=1;
//xray=1;
use <BOSL/transforms.scad>
use <BOSL/shapes.scad>
include <BOSL/constants.scad>
function get_link_segment_size() = [15, 30, 5];
function get_link_pin_diameter() = 2;
function get_link_socket_slack() = [1, 4, 1];
function get_link_joiner_arm_size() = [get_link_segment_size().x - 2, 3, segment_size.z];
function get_link_socket_size() = [get_link_segment_size().z,
get_link_segment_size().y - get_link_joiner_arm_size().y*2,
get_link_segment_size().z];
function get_link_clip_size() = [get_link_pin_diameter()*5, get_link_segment_size().y - 5, get_link_segment_size().z];
function get_link_socket_roundgap() = 2;
echo("===============================");
echo(str("Strap length: ", (links_count * get_link_segment_size().x), " mm"));
echo("===============================");
assert(get_link_segment_size().x >= 10, "Link segment is too short.");
assert(get_link_segment_size().z >= (get_link_pin_diameter() + get_link_socket_slack().z + 1), "Link segment is too thin.");
module pin() {
segment_size=get_link_segment_size();
h=segment_size.y;
d=get_link_pin_diameter();
back(h/2) xrot(90) cylinder(h=h, d=d, $fn=$preview ? 10 : 30);
}
module pin_socket_area() {
segment_size=get_link_segment_size();
h=segment_size.y-get_link_socket_slack().y;
d=segment_size.z;
back(h/2) xrot(90) cylinder(h=h, d=d, $fn=$preview ? 10 : 30);
}
module pin_socket() {
difference() {
pin_socket_area();
scaleup = [
((get_link_pin_diameter() + get_link_socket_slack().x) / get_link_pin_diameter()),
((get_link_pin_diameter() + get_link_socket_slack().y) / get_link_pin_diameter()),
((get_link_pin_diameter() + get_link_socket_slack().z) / get_link_pin_diameter())
];
scale(scaleup) pin();
}
}
module arm() {
arm_size=get_link_joiner_arm_size();
fwd(segment_size.y/2 + arm_size.y/2 - 1) right(arm_size.x/2 - 1) cuboid(arm_size, fillet=1, edges=EDGES_FRONT + EDGES_Y_ALL);
}
module armFront() {
arm();
}
module armBack() {
scale([1, -1, 1]) arm();
}
module armJoiner() {
gap=get_link_socket_roundgap();
arm_size=get_link_joiner_arm_size();
joiner_size=[arm_size.x-get_link_socket_size().x, segment_size.y, segment_size.z];
right(joiner_size.x/2 + get_link_socket_size().x/2 + gap) cuboid(joiner_size, fillet=1, edges=EDGES_Z_ALL + EDGES_BOTTOM);
}
module link_arms() {
armFront();
armBack();
armJoiner();
}
module link_connector_pin() {
pin();
link_arms();
}
module link_connector_socket() {
pin_socket();
}
module link(terminal=false) {
module link_joiner() {
gap=get_link_socket_roundgap();
arm_size=get_link_joiner_arm_size();
module pin_to_socket_joiner() {
joiner_size=[segment_size.x-get_link_socket_size().x+get_link_socket_size().x*0.2,
segment_size.y-4,
segment_size.z];
difference() {
right(joiner_size.x/2 + 4.5) cuboid(joiner_size, fillet=1, edges=EDGES_Z_ALL + EDGES_BOTTOM);
right(segment_size.x) scale([1, 2, 1]) pin_socket_area();
}
}
pin_to_socket_joiner();
}
link_connector_pin();
if (terminal) {
right(segment_size.x + 2) zrot(180) link_connector_pin();
} else {
link_joiner();
right(segment_size.x) link_connector_socket();
}
}
module clip() {
socket_size=get_link_socket_size();
clip_size=get_link_clip_size();
pin_diam=get_link_pin_diameter();
slot_slack=get_link_socket_slack();
size=[clip_size.x+socket_size.x, clip_size.y, clip_size.z];
slot_size=[clip_size.x+slot_slack.x, size.y+1, pin_diam+slot_slack.z];
entry_size=[slot_size.x, clip_size.y+1, clip_size.z];
entry_pos=[0, 0, 1.5];
module socket_area() {
$fn=$preview? 10 : 20;
xrot(90) down(size.y/2) cylinder(d=size.z, h=size.y);
}
module socket_cutout() {
$fn=$preview? 10 : 20;
xrot(90) down(slot_size.y/2) cylinder(d=slot_size.z, h=slot_size.y);
}
module cover() {
translate(entry_pos) cube(entry_size, center=true);
}
module joiner(groove) {
slack=groove?0.2:0;
joiner_size=[entry_size.x-6+slack, entry_size.y-6+slack, entry_size.z-3+slack];
joiner_pos=[entry_pos.x, entry_pos.y, entry_pos.z - entry_size.z/2 + joiner_size.z/2];
translate(joiner_pos) cube(joiner_size, center=true);
}
module model() {
difference() {
union() {
right(clip_size.x/2) socket_area();
left(clip_size.x/2) socket_area();
cube(clip_size, center=true);
}
right(clip_size.x/2) socket_cutout();
left(clip_size.x/2) socket_cutout();
}
}
right(clip_size.x/2)
if (is_model(MODEL_CLIP_A)) {
difference() {
model();
cover();
}
joiner(groove=false);
} else if (is_model(MODEL_CLIP_B)) {
difference() {
intersection() {
model();
cover();
}
joiner(groove=true);
}
}
}
module clip_ratcheting(ratchet_length=28) {
socket_size=get_link_socket_size();
clip_size=get_link_clip_size();
pin_diam=get_link_pin_diameter();
slot_slack=get_link_socket_slack();
size=[clip_size.x+socket_size.x, clip_size.y, clip_size.z];
slot_size=[clip_size.x+slot_slack.x + 0.2, size.y+1, pin_diam+slot_slack.z];
entry_size=[slot_size.x-5, clip_size.y+1, clip_size.z];
//right(clip_size.x/2)
module hook() {
intersection() {
difference() {
cuboid(size, fillet=1);
cuboid(slot_size, fillet=1);
up(entry_size.z/2) cube(entry_size, center=true);
}
translate([0, -50, -50]) cube([100, 100, 100]);
}
}
module hookRight() {
right(12.5) zrot(180) link_connector_pin();
}
module hookLeft() {
left(12.5) link_connector_pin();
}
wall=2;
tooth_size=[4, 3, 3];
module tooth() {
s=[tooth_size.x, tooth_size.z, tooth_size.y];
up(tooth_size.z/2) xrot(-90) right_triangle(s);
}
module teethFwd() {
tooth_count = ratchet_length/tooth_size.x;
fwd((clip_size.y-wall*2)/2)
right(ratchet_length/2) {
for (i=[1:tooth_count]) {
left(i*tooth_size.x) tooth();
}
cap_size=[ratchet_length, tooth_size.y, 1];
up(tooth_size.z/2 + cap_size.z/2) left(cap_size.x/2) back(tooth_size.y/2) {
difference() {
cube(cap_size, center=true);
translate([0.1, 0.1, 0]) back(tooth_size.y/2) right(ratchet_length/2) zrot(180) tooth();
}
}
}
}
module teethBack() {
scale([1, -1, 1]) teethFwd();
}
module ratchetLeft() {
right(ratchet_length/2) {
difference() {
cube([ratchet_length, clip_size.y, clip_size.z], center=true);
up(wall/2) cube([ratchet_length, clip_size.y-wall*2, clip_size.z], center=true);
right(ratchet_length/2+1) {
slideRailGuide(groove=true);
scale([1,-1,1]) slideRailGuide(groove=true);
}
}
teethFwd();
teethBack();
}
}
ratchet_tooth_count=2;
ratchet_wall=2.5;
ratchet_slack=0.3;
rail_slack=0.2;
ratchet_tooth_scale_z=0.8;
module ratchetTeethFront() {
module ratchetButton() {
size=[8,wall*4,4];
up(size.z+1) fwd(wall*2 - ratchet_wall) cuboid(size, fillet=1, edges=EDGES_FRONT);
up(2) back(ratchet_wall/2) cube([size.x, ratchet_wall, tooth_size.z*ratchet_tooth_scale_z + size.z], center=true);
}
fwd((clip_size.y-wall*2)/2 - tooth_size.y - ratchet_slack)
left(ratchet_length) {
for (i=[0:ratchet_tooth_count-1]) {
right(i*tooth_size.x) scale([-1,-1*(1-i/5),ratchet_tooth_scale_z]) tooth();
}
ratchetButton();
}
module ratchetWall() {
up(tooth_size.z/2) left(ratchet_length/2 + wall - wall/2) fwd(clip_size.y/2-wall-tooth_size.y-ratchet_wall/2 - ratchet_slack)
down(wall/2+0.5) cube([ratchet_length + wall, ratchet_wall, tooth_size.z*ratchet_tooth_scale_z], center=true);
}
ratchetWall();
}
module ratchetTeethBack() {
scale([1,-1,1]) ratchetTeethFront();
}
module ratchetRight() {
left(wall) cube([wall*2, clip_size.y + rail_slack*2, clip_size.z], center=true);
ratchetTeethFront();
ratchetTeethBack();
}
module slideRailGuide(groove) {
size=[ratchet_length, wall, wall];
fwd(clip_size.y/2 + rail_slack)
left(size.x/2) scale(groove?1.5:1) cuboid(size, fillet=0.5);
}
module slideRailLeft() {
size=[ratchet_length, clip_size.y/2 - ratchet_wall*2 - wall/2 - ratchet_slack - tooth_size.y, clip_size.z];
right(size.x/2) cube(size, center=true);
}
module slideRailRight() {
size=[ratchet_length + 3, wall*1.5, clip_size.z];
module railFront() {
fwd(clip_size.y/2 + size.y/2 + rail_slack) left(size.x/2)
cuboid(size, fillet=1, edges=EDGES_FRONT);
slideRailGuide(groove=false);
}
module railBack() {
scale([1, -1, 1]) railFront();
}
railFront();
railBack();
}
left(2) if (is_model(MODEL_CLIP_RATCHETING_A) || is_model(MODEL_CLIP_RATCHETING)) {
left(ratchet_length + wall + 1) {
hookLeft();
left(0.1) {
ratchetLeft();
slideRailLeft();
}
}
}
if (is_model(MODEL_CLIP_RATCHETING_B) || is_model(MODEL_CLIP_RATCHETING)) {
ratchetRight();
hookRight();
slideRailRight();
}
}
// Export / Demo / Validation:
segment_size=get_link_segment_size();
if (!is_undef(validation)) {
if (validation==VALIDATE_INTERSECTION) {
intersection() {
right(0*segment_size.x) link();
right(1*segment_size.x) link();
}
intersection() {
right(1*segment_size.x) link();
right(2*segment_size.x) link();
}
}
} else {
intersection () {
if (!is_undef(xray)) {
down(50) cube([100, 100, 100], center=true);
}
union() {
if (is_model(MODEL_CLIP_A) || is_model(MODEL_CLIP_B)) {
left(get_link_clip_size().x) clip();
}
if (is_model(MODEL_CLIP_RATCHETING) || is_model(MODEL_CLIP_RATCHETING_A) || is_model(MODEL_CLIP_RATCHETING_B)) {
left(get_link_clip_size().x * 2 + 3) clip_ratcheting();
}
if (is_model(MODEL_LINKS)) for (i = [0:links_count-1]) {
terminal=(i==links_count-1) && include_terminal;
right(i*segment_size.x) link(terminal=terminal);
}
}
}
}