926 lines
23 KiB
OpenSCAD
926 lines
23 KiB
OpenSCAD
//Seats, lights, Bike wheel and fenders modelisation are extracted from Velassi simulation (Velassi not published)
|
|
// Copyright 2018-2020 Pierre ROUZEAU AKA PRZ
|
|
// Program license GPL 4.0
|
|
// documentation licence cc BY-SA 3 and GFDL 1.2
|
|
// First version: 0.0 - November 2018
|
|
//Feb 2020: Add ICE mesh seat, Hardshell seat, corrected Rans seat frame width
|
|
//Dec 2020: Corrected hardshell viewing artifacts
|
|
// To work, this module requires my OpenSCAD library, attached, but you can find details here:
|
|
// https://github.com/PRouzeau/OpenScad-Library
|
|
|
|
//dcheck = false;
|
|
|
|
include <Z_library.scad>
|
|
|
|
//== Test of the accessories ============
|
|
//Testing seat
|
|
test_seat = 0; //[0:no seat view, 1:Rans mesh, 2:ICE mesh, 3: Hardshell, 9:Saddle]
|
|
//Seat angle
|
|
seat_a = 50; // [15:85]
|
|
//Flag attached to seat
|
|
seat_f=true;
|
|
//Rear light attached to seat
|
|
seat_l=true;
|
|
|
|
//Testing wheel
|
|
test_wheel = 0; //[0:no wheel, 1:Symetrical wheel, 2:Wheel hub offset, 3:Radial spokes, 4:Disc wheel, 5:Wheel with fender]
|
|
spoke_test = 32; // [0,3,4,5,6,8,20,24,28,32,36,42]
|
|
|
|
//Testing fork
|
|
test_fork = 0; //[0:No fork, 1:Rigid fork, 2:Suspended fork, 3:Experimental Lefty, 4:User fork]
|
|
//test viewing handlebar
|
|
|
|
//Testing handlebar
|
|
test_hdl = 0; // [0:none, 1:Trike direct, 2:Cruiser 400mm long, 6:Cruiser flat 80 mm, 3:Hamster, 4:U Bar, 5:Underseat U bar with center bend]
|
|
|
|
if (test_seat)
|
|
b_seat(test_seat,seat_a,0,seat_f?1000:0, seat_l?"black":"");
|
|
|
|
if (test_wheel==1)
|
|
wheel(spoke_nbr=spoke_test);
|
|
else if (test_wheel==2)
|
|
wheel(hub_offset=10, hubdia=28, spa=10);
|
|
else if (test_wheel==3)
|
|
wheel(hub_offset=0, hubdia=28, spa=0, spoke_nbr=28, tire=25);
|
|
else if (test_wheel==4)
|
|
wheel(spoke_nbr=0);
|
|
else if (test_wheel==5) {
|
|
wheel(hub_offset=0, hubdia=60, spa=10.6, spoke_nbr=32);
|
|
fender(wire_space=110, rear_angle=195, front_angle=75);
|
|
}
|
|
|
|
//test viewing wheel
|
|
if(test_fork) {
|
|
caster_angle=12;
|
|
perp_axis_offset=40;
|
|
fwheel_hdia=320;
|
|
steerer_tube_length=200;
|
|
|
|
fork(test_fork-1,0,400,fwheel_hdia,caster_angle,perp_axis_offset,100,steerer_tube_length,clrf="#404040");
|
|
}
|
|
//Test handlebar
|
|
hdla = test_hdl==5?-110:test_hdl==4?40:test_hdl==1?10:50;
|
|
hdl_typ = test_hdl==6?1:test_hdl==5?3:test_hdl-1;
|
|
if(test_hdl)
|
|
handlebar(hdl_typ, stem_length=test_hdl==1?90:test_hdl==4?-80:40,stem_ang=test_hdl==4?-15:15, hdl_ang=hdla, hdl_lg=test_hdl==6?80:400, hdl_centbend=test_hdl==5?30:0,hdl_centor=test_hdl==5?60:0);
|
|
|
|
//Transparent color
|
|
glass_color = [128,128,128,32]/256;
|
|
|
|
|
|
flag_img = "Library/flag_image.dxf";
|
|
flag_scale = 3.2;
|
|
|
|
function tire_diam (rim=559, tire=40) = rim+2*tire+4;
|
|
//-- spoked wheel ---------------------
|
|
//add parameter to simulate single and double spoke crossing for small wheels
|
|
module wheel (rim=559, tire=40, hubdia=60, hubwidth=60, spa=7.5, spoke_nbr=36, shaft_width = 140, clr_rim= [0.8,0.8,0.8], clr_tire=[0.4,0.4,0.4], hub_offset=0) {
|
|
wh_d=rim+2*tire+4;
|
|
//becho("wheel diam",wh_d);
|
|
spd = 2.2; // spoke diameter
|
|
//spokes faces
|
|
spf = 6;
|
|
spr = hubdia/2+5; // spoke radius
|
|
//becho("spoke_nbr", spoke_nbr);
|
|
rpt_spoke = spoke_nbr/4;
|
|
spoke_ang = 360/rpt_spoke;
|
|
radial = (spa==0) || (spoke_nbr<20);
|
|
check()
|
|
diff() {
|
|
cyly(-(rim-65),78, 0,0,0,48);
|
|
cyly(-(rim-66),122,0,0,0,48);
|
|
}
|
|
//tire
|
|
color(clr_tire)
|
|
r(90)
|
|
rotate_extrude(convexity = 10, $fn=48)
|
|
t(wh_d/2-tire/2, 0, 0)
|
|
circle(r = tire/2, $fn=24);
|
|
//rim
|
|
color(clr_rim) {
|
|
//rim
|
|
diff(){
|
|
cyly(-(wh_d-tire*2+10),0.6*tire,0,0,0, 48);
|
|
cyly(-(wh_d-tire*2-25),60, 0,0,0, 48);
|
|
}
|
|
// shaft
|
|
cyly(-9,shaft_width);
|
|
if(spoke_nbr) {
|
|
//hub
|
|
cyly(-hubdia,hubwidth, 0,hub_offset);
|
|
t(0,hub_offset)
|
|
//flanges
|
|
if(spoke_nbr>=20)
|
|
dmirrory()
|
|
cyly(hubdia+20,3, 0,hubwidth/2-3);
|
|
//spokes
|
|
lgspoke = rim/2-(spa?10:hubdia/2+15);
|
|
spangle = atan((hubwidth/2+2+hub_offset)/lgspoke);
|
|
spangle2 = atan((hubwidth/2-5+hub_offset)/lgspoke);
|
|
spangle3= atan((hubwidth/2+2-hub_offset)/lgspoke);
|
|
spangle4 = atan((hubwidth/2-5-hub_offset)/lgspoke);
|
|
t(0,hub_offset)
|
|
if(!radial)
|
|
droty(spoke_ang,rpt_spoke-1){
|
|
// first side
|
|
r(0,-spa) rotz(-spangle)
|
|
cylx(spd, lgspoke, 0,hubwidth/2+1,spr,spf);
|
|
r(0,spa+30) rotz(-spangle2)
|
|
cylx(spd, lgspoke, 0,hubwidth/2-5,-spr,spf);
|
|
// other side
|
|
r(0,360/spoke_nbr) {
|
|
r(0,-spa) rotz(spangle3)
|
|
cylx(spd, lgspoke, 0,-hubwidth/2-1,spr,spf);
|
|
r(0,spa+30) rotz(spangle4)
|
|
cylx(spd, lgspoke, 0,-hubwidth/2+5,-spr,spf);
|
|
}
|
|
}
|
|
else //radial spokes
|
|
if(spoke_nbr>=20)
|
|
droty(spoke_ang*0.5,rpt_spoke*2-1){
|
|
t(0,hubwidth/2+1,spr)
|
|
rot(spangle)
|
|
cylz(spd, lgspoke, 0,0,0, spf);
|
|
r(0,360/spoke_nbr)
|
|
t(0,-hubwidth/2-1,spr)
|
|
rot(-spangle)
|
|
cylz(spd, lgspoke, 0,0,0, spf);
|
|
}
|
|
else
|
|
droty(spoke_ang*0.25,spoke_nbr-1)
|
|
hull() {
|
|
cylz(45,0.01);
|
|
scale([1,0.3,1])
|
|
cylz(60*pow(0.9,spoke_nbr),0.01, 0,0,lgspoke+spr);
|
|
}
|
|
}
|
|
else
|
|
// no spoke gives plain wheel
|
|
hull() {
|
|
cyly(-hubdia-35,hubwidth+12, 0,hub_offset,0, 48);
|
|
cyly(-rim-30,35, 0,0,0, 48);
|
|
}
|
|
}
|
|
} //wheel
|
|
|
|
//- Fenders / Mudguards ------
|
|
//if front_angle = 0, no mudguard
|
|
//angle 0 = horizontal
|
|
//w_width is width of attach point of wire supports, if 0, there is no support, which is located on rear, at 8 deg from start
|
|
module fender (wheel_rim = 559, tire_w = 47, front_angle=8, rear_angle=170, wire_space=110, clr_fender="black") {
|
|
fender_dia = tire_w+26;
|
|
angtot = rear_angle-front_angle;
|
|
//becho("fender angtot",angtot);
|
|
wheel_dia = tire_diam (wheel_rim, tire_w);
|
|
if(front_angle!=0) {
|
|
color(clr_fender)
|
|
r(90, -front_angle)
|
|
rotate_extrude(angle=angtot, convexity = 10, $fn=48)
|
|
diff() {
|
|
t(wheel_rim/2+tire_w/2, 0, 0)
|
|
circle(r=fender_dia/2, $fn=48);
|
|
//::::::::::
|
|
t(wheel_rim/2+tire_w/2, 0, 0)
|
|
circle(r=(fender_dia/2-1), $fn=16);
|
|
square ([wheel_rim+tire_w,100], center=true);
|
|
//side cut, width 10mm more than tire
|
|
dmirrory()
|
|
t(0,tire_w/2+5)
|
|
square ([wheel_rim+tire_w+100,100]);
|
|
}
|
|
// wire supports
|
|
supy = wire_space/2;
|
|
ags = -atan((supy-tire_w/2-3)/(wheel_dia/2-20));
|
|
if(wire_space)
|
|
silver()
|
|
r(0,-rear_angle+20)
|
|
dmirrory()
|
|
t(15,supy,-4)
|
|
rotz(ags)
|
|
cylx(4,wheel_dia/2-16, 0,0,0, 6);
|
|
}
|
|
}
|
|
|
|
module seat_light (x=-70,z=515,s_ang, light_color, vert_ext = 80) {
|
|
if(light_color)
|
|
mirrorx()
|
|
t(x,0,z+42) {
|
|
if(light_color)
|
|
t(-75)
|
|
r(0,79-s_ang) t(-10,0,vert_ext){
|
|
rear_light(light_color);
|
|
dmirrory()
|
|
silver()
|
|
cubez(3,15,-20-vert_ext, 10,25,20);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*/-- seat tests
|
|
b_seat(1);
|
|
b_seat(2);
|
|
b_seat(3);
|
|
*projection() r(90) b_seat(2,55,0,false,"");
|
|
cyly (-50,380,350,0,400); // width test
|
|
//*/
|
|
|
|
//== Rans recumbent mesh seat ======
|
|
module rans_seat (s_ang=45, fold=0, width=400, sflag=true, light_color="black"){
|
|
//Width at base, top of seat have less width than the base (~ 30mm)
|
|
prec = 12;
|
|
dt = 22; // frame tube diameter
|
|
//cubez (500,500,1,0,0,700);
|
|
//check height
|
|
cx=-6; cz=112; // rotation centre at hip
|
|
//---------------------------
|
|
t(cx,0,cz) {
|
|
//cyly(-5,600);
|
|
//nominal width of 380 will give bottom width of 400
|
|
mirrorx()
|
|
r(0,s_ang)
|
|
t(cz,0,-cx)
|
|
t(30,0,10) r(0,-79) {
|
|
|
|
scale ([1,width/400,1]) {
|
|
black()
|
|
hull() {
|
|
cylz (20,1, 85,0,0, prec);
|
|
cylz (30,1, 85,0,-10, prec);
|
|
dmirrory()
|
|
cylz (20,10, 0,28,0, prec);
|
|
}
|
|
t(-174,0,155) {
|
|
red()
|
|
cyly(-3,420, 0,0,0, prec);
|
|
r(0,-fold) {
|
|
mirrorx()
|
|
seat_light(-60,455,s_ang,light_color, 60);
|
|
//flag
|
|
if(sflag) t(-110,-175,540)
|
|
r(0,50-s_ang) flag();
|
|
// width check
|
|
//cyly(-20,372,-106,0,535, 6);
|
|
//cyly(-20,400,10,0,-40, 4);
|
|
}
|
|
}
|
|
gray()
|
|
dmirrory()
|
|
tb_yx(dt,-75,48, prec)
|
|
cyly(dt,84, 0,0,0, prec)
|
|
r(0,-90)
|
|
tb_yx(dt,75,45, prec)
|
|
cyly(dt,57.6, 0,0,0,prec) {
|
|
r(28,26)
|
|
cylz(15,150, 0,0,0, prec)
|
|
tb_zx(15,250,6, prec);
|
|
tb_yx(dt,75,45, prec)
|
|
cyly(dt,40, 0,0,0, prec)
|
|
r(0,41.8)
|
|
rotz(fold) r(1.5){
|
|
//back
|
|
cyly(dt,40, 0,0,0, prec) {
|
|
tb_yx(dt,-500,20, prec)
|
|
cyly(dt,30, 0,0,0, prec)
|
|
tb_yx(dt,500,3, prec) {
|
|
//medium transversal bar
|
|
r(-5,69.5)
|
|
t(0,0,-4)
|
|
tb_xz(12,500,21.6, prec);
|
|
tb_yx(dt,500,17, prec)
|
|
cyly(dt,30, 0,0,0, prec)
|
|
tb_yx(dt,-120,30, prec)
|
|
cyly(dt,20, 0,0,0, prec){
|
|
cyly(dt,20, 0,0,0, prec);
|
|
//top transversal bar
|
|
r(-5,70)
|
|
t(0,0,-4)
|
|
tb_xz(12,500,20.9, prec);
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
module flag (lg=1000, imgfile=flag_img, imgscale=flag_scale, fclr = ["orangered","lime"]) {
|
|
|
|
module imp_img(imgfile) {
|
|
linear_extrude(height=2, center=true)
|
|
import(file=imgfile);
|
|
}
|
|
//pole
|
|
silver() {
|
|
cyly(-22,10, 0,0,0, 12);
|
|
cylz(6,lg, 0,0,0, 6);
|
|
}
|
|
//flag
|
|
t(12,0,lg){
|
|
color(fclr[0])
|
|
hull() {
|
|
cylz(2,-160, -12,0,0,4);
|
|
cylz(2,2, -250,0,0, 4);
|
|
}
|
|
//Image set on flag
|
|
t(-108,2, -88)
|
|
r(90) color(fclr)
|
|
scale([imgscale,imgscale,1]) {
|
|
imp_img(imgfile);
|
|
t(0,0,4)
|
|
imp_img(imgfile);
|
|
}
|
|
}
|
|
}
|
|
|
|
//== ICE recumbent mesh seat ======
|
|
//ICE frame designed from photo, so accuracy may be limited
|
|
module ICE_seat (seat_angle=45,width=380, sflag=true, light_color="black") {
|
|
prec= 12;
|
|
dt = 25.4;
|
|
wd = width-dt;
|
|
module cxl(d,l) {
|
|
cylx (d,l,0,0,0,prec)
|
|
children();
|
|
}
|
|
module transv(dx=0) {
|
|
t(dx)
|
|
//render()
|
|
r(45)
|
|
cyly(dt-1,-60, 0,0,0, prec)
|
|
tb_yz(dt,-50,-45, prec)
|
|
//t(0,0.1) // stop CGAL error
|
|
cyly(dt,-wd/2+50, 0,0,0, prec)
|
|
children();
|
|
}
|
|
cx=-6; //cx, cz rotation center coord
|
|
cz=112;
|
|
t(cx,0,cz) {
|
|
//red()cyly(-5,600);
|
|
r(0,-seat_angle+52.8,0)
|
|
t(-cx,0,-cz) {
|
|
//-- rear light ---------------
|
|
seat_light(-370,375,seat_angle+26,light_color, 60);
|
|
//-- seat -------------------
|
|
color("gray")
|
|
mirrorx()
|
|
//render()
|
|
dmirrory()
|
|
t(185,wd/2,10)
|
|
r(0,24)
|
|
tb_xz(dt,-200,40, prec)
|
|
cxl(dt,-50){
|
|
transv(15);
|
|
//back bend
|
|
tb_xz(dt,100,78, prec)
|
|
cxl(dt,-100){
|
|
transv(65);
|
|
tb_xz(dt,-200,14, prec)
|
|
cxl(dt,-190){
|
|
transv(60);
|
|
tb_xz(dt,200,20, prec)
|
|
cxl(dt,-150)
|
|
transv(80);
|
|
}
|
|
}
|
|
}
|
|
//flag
|
|
if(sflag) t(410,-wd/2,525)
|
|
r(0,-25+seat_angle,0) rotz(180) flag();
|
|
} //r, t
|
|
} // -t
|
|
}
|
|
|
|
module hardshell_seat (seat_angle=45,wd=300, sflag=true, light_color="black", thk = 16) {
|
|
$wd = wd;
|
|
$prec=64;
|
|
reinf_dist = 80;
|
|
|
|
module shape (wd=$wd,mirr=true) {
|
|
u() {
|
|
hull() {
|
|
dmirrory(mirr)
|
|
t(0,wd/2-thk/2)
|
|
circle (d=thk, $fn=12);
|
|
if(!mirr)
|
|
square([thk,thk],center=true);
|
|
}
|
|
dmirrory(mirr)
|
|
hull() {
|
|
t(25,reinf_dist)
|
|
circle (d=25, $fn=12);
|
|
t(5,reinf_dist)
|
|
square ([25,25],center=true);
|
|
}
|
|
}
|
|
}
|
|
|
|
module rshp (radius=100,ang=90, wd=$wd,mirr=true) {
|
|
sang = radius<0?ang:-ang;
|
|
dx = (1-cos(sang))*radius;
|
|
dy = sin(sang)*-radius;
|
|
t(radius)
|
|
rotate_extrude(angle=sang, $fn=$prec, convexity=4)
|
|
translate([-radius,0,0])
|
|
shape(wd,mirr);
|
|
t(dx,dy-0.1)
|
|
rotz(sang)
|
|
mirrorz()children();
|
|
}
|
|
|
|
module srt (a=-25,wd=$wd) {
|
|
diff() {
|
|
tslz(-sign(a)*wd/2)
|
|
r(a)
|
|
tslz(sign(a)*wd/2)
|
|
children();
|
|
//::::::::::::
|
|
cubey(99,-199,999);
|
|
cubez(99,399,sign(a)*399, 0,99);
|
|
}
|
|
}
|
|
//Convexity 4 required to eliminate viewing artifacts
|
|
module tshp (lg,wd=$wd,mirr=true) {
|
|
r(-90)
|
|
linear_extrude(height=lg,center=false, convexity=4)
|
|
shape(wd,mirr);
|
|
t(0,lg-0.1)
|
|
children();
|
|
}
|
|
//------------------
|
|
cx=-6; cz=112; // rotation centre at hip
|
|
//---------------------------
|
|
|
|
t(cx,0,cz) {
|
|
//red() cyly(-5,600);
|
|
|
|
r(0,-seat_angle+60)
|
|
t(-cx,0,-cz)
|
|
t(-130,0,-10) {
|
|
//-- rear light ---------------
|
|
seat_light(-415,540,seat_angle+19,light_color, 25);
|
|
//-- flag ----
|
|
if(sflag)
|
|
mirrorx()
|
|
t(-492,-97,590)
|
|
r(0,-seat_angle+32) flag();
|
|
// shell
|
|
gray()
|
|
r(90,90)
|
|
rotz(32+5) diff() {
|
|
rshp(100,40)
|
|
tshp(55)
|
|
rshp(-150,70)
|
|
tshp(100)
|
|
rshp(200,14)
|
|
tshp(100)
|
|
rshp(-400,42)
|
|
;
|
|
//:::::::::::
|
|
//headrest cut
|
|
dmirrorz()
|
|
t(-200,680,100)
|
|
rotz(60)
|
|
r(-21)
|
|
cubez(199,399,399);
|
|
//Base nose cut
|
|
dmirrorz()
|
|
t(40,60,90)
|
|
rotz(-30)
|
|
r(40)
|
|
cubez(88,255,99, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
module b_seat (type=2,s_ang=55,fold=0, sflag=1000, light_color="black", wd=380){
|
|
if(type==1) //rans mesh
|
|
rans_seat(s_ang, fold, wd, sflag, light_color);
|
|
else if(type==2) //ICE mesh
|
|
ICE_seat(s_ang, wd, sflag, light_color);
|
|
else if(type==3) //Hard shell
|
|
hardshell_seat(s_ang, 300, sflag,light_color);
|
|
else if (type==9) //saddle
|
|
tslz(15)
|
|
mirrorx()
|
|
saddle("saddlebrown", light_color);
|
|
}
|
|
//-- Saddle ------------------------
|
|
|
|
module saddle(seat_color="saddlebrown", light_color="black") {
|
|
color(seat_color)
|
|
hull() {
|
|
dmirrory()
|
|
t(-80,60)
|
|
sphere (r=25, $fn=24);
|
|
t(115,0,3)
|
|
sphere (r=20, $fn=24);
|
|
}
|
|
if(light_color)
|
|
t(-100,0,-60) {
|
|
rear_light(light_color);
|
|
black()
|
|
dmirrory() {
|
|
cubez(2.5,15,25, 9,25,10);
|
|
cubex(20,15,2.5, 9,25,34);
|
|
}
|
|
}
|
|
}
|
|
|
|
//== SHOCK with eyes ==============
|
|
//Dist = length eye to eye without compression, travel = compression travel, sag = compression at nominal load {~20% of travel)
|
|
module shock (dist = 190, travel=50, sag=10) {
|
|
gray() {
|
|
duplx(dist-sag) {
|
|
diff() {
|
|
u(){
|
|
cyly(-23,14);
|
|
cyly(-18,24);
|
|
}//::::::::::
|
|
cyly(-8,99);
|
|
}
|
|
cyly(-8,55);
|
|
}
|
|
cylx(15,dist-sag-16, 8);
|
|
cylx(28,dist-sag-30, 15);
|
|
cylx(48,20, 20);
|
|
cylx(47,dist*0.5, 18);
|
|
}
|
|
}
|
|
|
|
//== FORK ===========================
|
|
//Fork parameters:style= fork type, stro = steering rotation angle, flg = perpendicular distance between bearing bottom and wheel axis, casta = caster_angle, pao = perpendicular axis offset, fwhd = wheel hald diameter, stl= steerer tube length, stb = steering bottom bearing height space, htb = header tube height, clrf= fork color
|
|
|
|
module fork (style=0, stro=0, flg=380, fwhd=325, casta=18, pao=47, OLD=100, stl = 180, stb=5, htb=115, clrf = "black") {
|
|
steerdia = 28.6;
|
|
rad = 125; //dropout bend radius
|
|
toprad = 100; //top bend radius
|
|
//pao = perp_axis_offset;
|
|
sgn = sign(pao);
|
|
fang = acos((rad-abs(pao))/rad);
|
|
//fwhd = fwheel_hdia;
|
|
//move to wheel center and tilt of caster_angle value
|
|
t(0,0,fwhd)
|
|
r(0,casta)
|
|
t(pao) rotz(stro) t(-pao){
|
|
if (style==3) //User programmed fork
|
|
user_fork1();
|
|
else if (style==2) //Experimental lefty
|
|
xlefty();
|
|
else if (style==1) //suspended fork
|
|
stsusp();
|
|
else
|
|
st();
|
|
//steerer tube
|
|
gray()
|
|
cylz(steerdia,stl, pao,0,flg);
|
|
}
|
|
//rigid fork - bent dropout style
|
|
module st () {
|
|
lgstr = flg-88-rad*sin(fang);
|
|
hhang = atan((8+OLD/2-50)/lgstr);
|
|
color(clrf)
|
|
mirrorx(pao<0)
|
|
dmirrory() {
|
|
t(0,OLD/2+4,0)
|
|
diff() {
|
|
r(hhang)
|
|
r(0,fang-90)
|
|
tb_xz(24,rad,-fang)
|
|
cylx(24,lgstr)
|
|
tb_xy(24,-toprad,-60);
|
|
//:::::::::::::
|
|
cyly(-24,66);
|
|
}
|
|
cyly(-32,8, 0,OLD/2+4);
|
|
}
|
|
color(clrf)
|
|
cylz(steerdia+5,-40, pao,0,flg);
|
|
}
|
|
//suspended fork
|
|
module stsusp () {
|
|
tubsp = 106;
|
|
tubdia = 28;
|
|
postube = pao-sign(pao)*20;
|
|
dmirrory() {
|
|
color(clrf) {
|
|
cylz(tubdia+15,250, postube,tubsp/2,5);
|
|
hull() {
|
|
cylz(steerdia+15,-40, pao,0,flg);
|
|
cylz(tubdia+12,-40, postube,tubsp/2,flg-20);
|
|
}
|
|
hull() {
|
|
cyly(-32,8, 0,OLD/2+4);
|
|
cylz (12,50, postube,tubsp/2,5);
|
|
}
|
|
}
|
|
silver()
|
|
cylz(tubdia,flg-60, postube,tubsp/2,20);
|
|
}
|
|
}
|
|
// Experimental 'lefty' fork
|
|
module xlefty (sideoff=-60, shock_ang=-38) {
|
|
//stb = steer_bbht==undef?5:steer_bbht;
|
|
//htb = head_tube_height==undef?stl-50:head_tube_height;
|
|
harm_ang = 15; // articulated arm angle from horizontal
|
|
hang = -casta+harm_ang;
|
|
bang=32;
|
|
armlg = -220; // axis to axis arm length
|
|
sa = sign(armlg);
|
|
vrad = 200;
|
|
vdia=50;
|
|
// first length segment calc
|
|
xar = armlg*cos(hang);
|
|
xb=(1-cos(bang))*vrad*sa;
|
|
stlg = (xar-xb-pao)/sin(bang);
|
|
//top segment
|
|
yar = armlg*sin(hang);
|
|
yb = sin(bang)*vrad;
|
|
vlgb = flg+yar-yb-sa*stlg*cos(bang);
|
|
vlg = vlgb+2*stb+htb+20;
|
|
//Attach to pivot
|
|
module side_plate () {
|
|
hull() {
|
|
cylz(vdia+12,-8, pao);
|
|
cylz(40,-8, pao,-sideoff);
|
|
}
|
|
}
|
|
|
|
//Bottom tube segment
|
|
silver()
|
|
cylz(28.6,-10, pao,0,flg-8);
|
|
// fork
|
|
t(0, sideoff) {
|
|
color(clrf) {
|
|
cyly(-18,60);
|
|
r(0,hang) {
|
|
//arm
|
|
cylx(50,armlg+sa*40,-sa*20)
|
|
cyly(-18,60,-sa*20);
|
|
//support tube
|
|
t(armlg) {
|
|
diff() {
|
|
r(0,-sa*bang-hang-90)
|
|
cylx(vdia,sa*stlg-30,30)
|
|
tb_xz(vdia,-sa*vrad,-bang)
|
|
cylx(vdia,vlg)
|
|
;
|
|
//:::::::::::::::
|
|
r(0,sa*15)
|
|
cylx(-80,166);
|
|
}
|
|
//arm axis fork
|
|
mirrorx (sa<0)
|
|
hull() {
|
|
cyly(-30,80);
|
|
r(0,15)
|
|
diff() {
|
|
cylx(-80,87, -35);
|
|
//::::::::::::
|
|
cubez(222,111,-111, 0,0,10);
|
|
r(0,40)
|
|
cubez(222,111,-111, 0,0,-20);
|
|
cylx(-70,222);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//shafts
|
|
gray() {
|
|
cyly(-14,70);
|
|
r(0,hang)
|
|
cyly(-14,90, armlg);
|
|
}
|
|
// Attach plates
|
|
color(clrf) {
|
|
tslz(flg)
|
|
side_plate();
|
|
tslz(flg+2*stb+htb)
|
|
mirrorz()
|
|
side_plate();
|
|
}
|
|
//shock
|
|
r(0,hang)
|
|
t(armlg*0.6,0,40) {
|
|
r(0,-90+sa*harm_ang+sa*shock_ang) {
|
|
shock(190,50,15);
|
|
color(clrf)
|
|
mirrorz(sa<0)
|
|
dmirrory()
|
|
t(190-15)
|
|
hull() {
|
|
cyly(28,5, 0,12);
|
|
cubey(60,5,1, 16,12,-45);
|
|
}
|
|
}
|
|
color(clrf)
|
|
dmirrory()
|
|
hull() {
|
|
cyly(28,5, 0,12);
|
|
cubey(60,5,1, 0,12,-30);
|
|
}
|
|
}
|
|
} // sideoff
|
|
} //xlefty
|
|
} //fork
|
|
|
|
//== Handlebar ======================
|
|
module handlebar (hdl_type=0, stem_length=40,stem_height=40,stem_ang=15,hdl_ang=60,hdl_lg=400,hdl_bend=37.5, hdl_width_central_extent=0,
|
|
hdl_centbend=0,hdl_centor=0,hdl_lg2=200, dcheck=false, d_line=1) {
|
|
//sgo = sign(stem_length);
|
|
sgo = stem_length>0?1:-1;
|
|
//stem_ang = OSS_handlebar?20:0;
|
|
sto = sign(stem_height)*27; // stem shaft axis offset
|
|
//depending its length 'cruiser' handlebar go from chopper type to near flat mountain bike bar through town type.
|
|
crui_a = hdl_lg>150?90:20+(hdl_lg-50)*0.70;
|
|
if (dcheck)
|
|
red()
|
|
cubez(d_line,666,555);
|
|
silver() {
|
|
//stem pivot shaft
|
|
cylz(25,-stem_height-sto, 0,0,sto);
|
|
cylz(-36,40);
|
|
r(0,-stem_ang) {
|
|
//stem
|
|
cylx(32,sgo*(abs(stem_length)+40),-sgo*20);
|
|
//handlebar
|
|
t(stem_length)
|
|
r(0,hdl_ang+stem_ang)
|
|
dmirrory()
|
|
if(hdl_type==0){ //trike direct
|
|
cylz(22,10)
|
|
cylz(30,120);
|
|
}
|
|
else if(hdl_type==1){ //cruiser
|
|
cyly(22,40)
|
|
tb_yz(22,-70,crui_a)
|
|
r(0,-20)
|
|
cyly(22,abs(hdl_lg-140))
|
|
tb_yz(22,70,crui_a)
|
|
cyly(22,10)
|
|
cyly(32,120);
|
|
}
|
|
else if(hdl_type==2) { // Hamster
|
|
cylz(22,hdl_lg)
|
|
tb_yx(22,80,18)
|
|
cyly(22,40)
|
|
cyly(30,120);
|
|
}
|
|
else if(hdl_type==3) { //U Bar
|
|
// if handlebar length = 420, this is a metabike Ubar
|
|
centpart = hdl_width_central_extent>0||hdl_centbend; // if true, central bent part
|
|
cyly(25,30)
|
|
cyly(25,hdl_width_central_extent/2)
|
|
r(0,hdl_centor)
|
|
tb_yx(25,50,hdl_centbend/2)
|
|
r(0,-hdl_centor)
|
|
cyly(25,centpart?120:0)
|
|
cyly(22,centpart?27:147)
|
|
tb_yx(22,50,80)
|
|
cyly(22,hdl_lg-270)
|
|
r(0,90)
|
|
tb_yx(22,50,hdl_bend)
|
|
cyly(22,(hdl_lg2-120)/2)
|
|
cyly(30,120)
|
|
cyly(22,(hdl_lg2-120)/2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//== Lighting ======================
|
|
module rear_light (clr="black", z=15) {
|
|
//light
|
|
tslz(z) {
|
|
color(clr)
|
|
hull() dmirrory() {
|
|
cylx(45,-10, 0,30);
|
|
cylx(30,8, 0,30);
|
|
}
|
|
red()
|
|
hull() dmirrory()
|
|
cylx(44,10, -20,30);
|
|
color(glass_color)
|
|
hull() dmirrory()
|
|
cylx(44,2, -22,30);
|
|
}
|
|
}
|
|
|
|
//front_light (-20, false);
|
|
|
|
module front_light (st_ang=0, steer_bracket=0, clr = "black"){
|
|
//support (normal type on fork)
|
|
if(steer_bracket==1) {
|
|
t(25)
|
|
r(0,st_ang)
|
|
flight();
|
|
//steering bracket
|
|
silver() {
|
|
hull(){
|
|
cylz(34,2.5, 0,0,-1);
|
|
cyly(-2.5,26, 25);
|
|
}
|
|
t(25)
|
|
r(0,st_ang)
|
|
hull() {
|
|
cyly(-2.5,26);
|
|
cylx (-12,2.5, 0,0, 10);
|
|
}
|
|
}
|
|
}
|
|
//on top of fork
|
|
else if(steer_bracket==2) {
|
|
tslz (-10-20)
|
|
flight(st_ang);
|
|
}
|
|
//above boom
|
|
else if(steer_bracket==3) {
|
|
silver() {
|
|
cubez(3,20,60, 22);
|
|
dmirrory()
|
|
cubez(10,3,60, 22-5,8.5);
|
|
}
|
|
t(22,0,42) flight();
|
|
}
|
|
else // simple light
|
|
flight();
|
|
//-- light with own bracket --------
|
|
module flight(an=0) {
|
|
//light bracket
|
|
silver()
|
|
hull() {
|
|
cyly(-14,10, 20,0,35);
|
|
cylx(-12,2.5, 3,0, 10);
|
|
}
|
|
//light
|
|
t(33,0,40) r(0,an) {
|
|
color(clr)
|
|
hull() {
|
|
cylx(50,20,0,0,15);
|
|
cylx(30,-20,0,0,15);
|
|
}
|
|
silver()
|
|
cylx(48,1, 20,0,15);
|
|
color (glass_color)
|
|
cylx(48,2, 22,0,15);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=== Miscellaneous utilities ===
|
|
//tube bend AND displacement
|
|
module tb_yx (dtube=25,radius=100,ang=90, prec=24) {
|
|
sang = radius<0?ang:-ang;
|
|
dx=-(1-cos(sang))*-radius;
|
|
dy=sin(sang)*-radius;
|
|
t(radius)
|
|
rotate_extrude(angle=sang, $fn=64, convexity=10)
|
|
t(-radius)
|
|
circle(d=dtube, $fn=prec);
|
|
t(dx,dy)
|
|
rotz(sang)
|
|
children();
|
|
}
|
|
|
|
module tb_xy (dtube=25,radius=100,ang=90, prec=24) {
|
|
rotate([0,0,90])
|
|
tb_yx(dtube,radius,ang, prec)
|
|
rotate([0,0,-90]) children();
|
|
}
|
|
|
|
module tb_xz (dtube=25,radius=100,ang=90, prec=24) {
|
|
r(90) rotz(90)
|
|
tb_yx(dtube,radius,ang, prec)
|
|
r(-90,0,-90) children();
|
|
}
|
|
|
|
module tb_yz (dtube=25,radius=100,ang=90, prec=24) {
|
|
rotate([0,90,0])
|
|
tb_yx(dtube,radius,ang, prec)
|
|
rotate([0,-90,0])
|
|
children();
|
|
}
|
|
|
|
module tb_zx (dtube=25,radius=100,ang=90, prec=24) {
|
|
r(90)
|
|
tb_yx(dtube,radius,ang, prec)
|
|
rotate([-90,0,0]) children();
|
|
}
|
|
|
|
module tb_zy (dtube=25,radius=100,ang=90, prec=24) {
|
|
r(0,90) rotz(90)
|
|
tb_yx(dtube,radius,ang, prec)
|
|
rotate ([0,0,-90])
|
|
rotate([0,-90,0])
|
|
children();
|
|
}
|
|
|
|
//------------------------------
|
|
module check () {
|
|
if(dcheck)
|
|
red()
|
|
children();
|
|
} |