// title : Fingerboard Deck // author : Beau Trifiro // license : (c) 2020 // description: Fingerboard Design Tool // file : 200408-SK8CAD-FB function getParameterDefinitions() { return ([ { name: 'show_template', type: 'checkbox', checked: false, caption: 'Show Template, Only?'}, { name: 'width', type: 'slider', class: 'paramSlider', initial: 30, step: 1, min: 20, max: 40, caption: 'Width, mm'}, //30mm truck width { name: 'wheelbase', type: 'slider', class: 'paramSlider', initial: 45, step: 1, min: 40, max: 60, caption: 'Wheelbase, mm'}, { name: 'concave_drop', type: 'slider', class: 'paramSlider', initial: 3, step: 0.5, min: 1, max: 5, caption: 'Concave Drop, mm'}, { name: 'nose_length', type: 'slider', class: 'paramSlider', initial: 20, step: 1, min: 10, max: 30, caption: 'Nose Length, mm'}, { name: 'tail_length', type: 'slider', class: 'paramSlider', initial: 20, step: 1, min: 10, max: 30, caption: 'Tail Length, mm'}, { name: 'kicknose_angle', type: 'slider', class: 'paramSlider', initial: 20.0, step: 1, min: 0, max: 30, caption: 'Kicknose Angle, degrees'}, { name: 'kicktail_angle', type: 'slider', class: 'paramSlider', initial: 20.0, step: 1, min: 0, max: 30, caption: 'Kicktail Angle, degrees'}, { name: 'kick_gap', type: 'slider', class: 'paramSlider', initial: 3, step: 1, min: 2, max: 5, caption: 'Kick Gap, mm'}, { name: 'transition_length', type: 'slider', class: 'paramSlider', initial: 12, step: 1, min: 12, max: 20, caption: 'Transition Length, mm'}, { name: 'taperN', type: 'slider', class: 'paramSlider', initial: 25, step: 1, min: 15, max: 45, caption: 'Nose Taper Point, mm'}, { name: 'taperT', type: 'slider', class: 'paramSlider', initial: 25, step: 1, min: 15, max: 45, caption: 'Tail Taper Point, mm'}, { name: 'nose_flatness', type: 'slider', class: 'paramSlider', initial: 75, step: 1, max: 100, min: 50, caption: 'Nose Shape'}, { name: 'tail_flatness', type: 'slider', class: 'paramSlider', initial: 75, step: 1, max: 100, min: 50, caption: 'Tail Shape'}, { name: 'resolution', type: 'slider', class: 'paramSlider', initial: 8, step: 1, max: 20, min: 1, caption: 'Model Resolution'} ]); } /* Interactive parametric models It is possible to make certain parameters editable in the browser. This allows users not familiar with JavaScript to create customized STL files. To do so, add a function getParameterDefinitions() to your .jscad source. This function should return an array with parameter definitions. Currently 6 parameters types are supported: float, int, text, longtext, bool and choice. The user edited values of the parameters will be supplied as an object parameter to the main() function of your .jscad file. */ function main (parameters) { var width = parseFloat(parameters.width)/10; var true_width = width; var wheelbase = parseFloat(parameters.wheelbase)/10; var concave_drop = parseFloat(parameters.concave_drop)/10; var concave_radius = (Math.pow((true_width/2),2) + Math.pow(concave_drop,2))/(2*concave_drop); var tail_length = parseFloat(parameters.tail_length)/10; var nose_length = parseFloat(parameters.nose_length)/10; //var kicktail_length = parameters.kicktail_length; //var kicknose_length = parameters.kicknose_length; var kick_gap = parseFloat(parameters.kick_gap)/10 var kicktail_length = tail_length-kick_gap; var kicknose_length = nose_length-kick_gap; //var origin = parameters.origin; var kicknose_angle = parameters.kicknose_angle; var kicktail_angle = parameters.kicktail_angle; var nose_shape = parseFloat(parameters.nose_flatness)/100; var tail_shape = parseFloat(parameters.tail_flatness)/100; var taperN = parseFloat(parameters.taperN)/10; var taperT = parseFloat(parameters.taperT)/10; var thickness = 0.24; var bolt_pattern_width = 0.5; // 5mm - not to scale var bolt_pattern_length = 0.8; // 8mm - not to scale var bolt_diameter = 0.17; //not to scale var nose_transition_length = parseFloat(parameters.transition_length)/10; var tail_transition_length = nose_transition_length; var kicknose_radius = 2; var kicktail_radius = 2; var slice_thickness = parseFloat(parameters.resolution)/100; var min_radius = concave_radius; var show_template = parameters.show_template; var length = wheelbase + (bolt_pattern_length*2) + tail_length + nose_length; var concave_length = length - (kicktail_length + kicknose_length + nose_transition_length + tail_transition_length); if (show_template == true) { var skateboard = make_profile(width, wheelbase, bolt_pattern_length, nose_length, tail_length, length, taperN, taperT, nose_shape, tail_shape, 0.1); } else { //find kicknose translation parameters var kicknose_hypotenuse = 2*(kicknose_radius*sin(kicknose_angle/2)); var kicknose_radius_length = kicknose_hypotenuse*cos(kicknose_angle/2); var kicknose_radius_height = kicknose_hypotenuse*sin(kicknose_angle/2); //find kicktail translation parameters var kicktail_hypotenuse = 2*(kicktail_radius*sin(kicktail_angle/2)); var kicktail_radius_length = kicktail_hypotenuse*cos(kicktail_angle/2); var kicktail_radius_height = kicktail_hypotenuse*sin(kicktail_angle/2); var number_of_segments = 10; //for transition section resolution var skateboard = make_concave(concave_radius, thickness, concave_length, width).translate([0,0,thickness]); skateboard = skateboard.union(make_kicknose_curve(kicknose_radius, thickness, width, kicknose_angle, nose_transition_length, concave_length)); skateboard = skateboard.union(make_kicktail_curve(kicktail_radius, thickness, width, kicktail_angle, tail_transition_length, concave_length)); skateboard = skateboard.union(make_kicknose_section(wheelbase, bolt_pattern_length, nose_length, kicknose_length, kicknose_radius_length, width, kicknose_radius_height, thickness, kicknose_angle, nose_transition_length, concave_length)); skateboard = skateboard.union(make_kicktail_section(wheelbase, bolt_pattern_length, tail_length, kicktail_length, kicktail_radius_length, width, kicktail_radius_height, thickness, kicktail_angle, tail_transition_length, concave_length)); skateboard = skateboard.union( ((rotate([0,0,90], make_transition_section(nose_transition_length, thickness, slice_thickness, width, min_radius, number_of_segments)))).translate([concave_length/2+nose_transition_length,0,0])); skateboard = skateboard.union( ((rotate([0,0,-90], make_transition_section(tail_transition_length, thickness, slice_thickness, width, min_radius, number_of_segments)))).translate([-(concave_length/2+tail_transition_length),0,0])); var profile = (((make_profile(width, wheelbase, bolt_pattern_length, nose_length, tail_length, length, taperN, taperT, nose_shape, tail_shape, 5)))); skateboard = skateboard.intersect(profile); } skateboard = skateboard.subtract(make_wheelbase(bolt_pattern_length, bolt_pattern_width, wheelbase, bolt_diameter)); /*if (origin==1) { skateboard = skateboard.union(make_origin(origin)); } */ skateboard = color([0.1,0.7,1.0],skateboard); return skateboard; } function make_origin(origin) { var result = new CSG(); var height = 20; result = union( cylinder({d: 0.25, h: height, center: true}).translate([0,0,height/2]), union( rotate([-90,0,0],cylinder({d: 0.25, h: height, center: true}).translate([0,0,height/2])), rotate([0,90,0],cylinder({d: 0.25, h: height, center: true}).translate([0,0,height/2])) ) ); return result; } function make_bolt_pattern(bolt_pattern_length, bolt_pattern_width, bolt_diameter) { var result = new CSG(); result = (cylinder({d: bolt_diameter, h: 6, center: false}).translate([bolt_pattern_length/2,bolt_pattern_width/2,0])).union(cylinder({d: bolt_diameter, h: 6, center: false}).translate([bolt_pattern_length/2,-bolt_pattern_width/2,0])); result = result.union(cylinder({d: bolt_diameter, h: 6, center: false}).translate([-bolt_pattern_length/2,-bolt_pattern_width/2,0])); result = result.union(cylinder({d: bolt_diameter, h: 6, center: false}).translate([-bolt_pattern_length/2,bolt_pattern_width/2,0])); return result; } function make_wheelbase(bolt_pattern_length, bolt_pattern_width, wheelbase, bolt_diameter) { var result = new CSG(); result = (make_bolt_pattern(bolt_pattern_length,bolt_pattern_width,bolt_diameter).translate([(wheelbase/2)+(bolt_pattern_length/2),0,-1])).union(make_bolt_pattern(bolt_pattern_length,bolt_pattern_width,bolt_diameter).translate([-((wheelbase/2)+(bolt_pattern_length/2)),0,-1])); return result; } function make_concave(concave_radius, thickness, concave_length, width) { var result = new CSG(); result= difference( difference( difference( (rotate([90,0,90], difference( cylinder({r: (concave_radius + thickness), h: concave_length, center: true, fn: 100}), cylinder({r: concave_radius, h:concave_length+2, center: true, fn: 100}).translate([0,0,1]))) ).translate([-concave_length/2,0,concave_radius]), cube({size: [concave_length*2, concave_radius*4, concave_radius*4]}).translate([-concave_length, -concave_radius * 2, concave_radius]) ), cube({size: [concave_length*4, concave_radius*2, concave_radius*2], center: false}).translate([-concave_length*2, width/2, 0]) ), mirror([0,1,0], cube({size: [concave_length*4, concave_radius*2, concave_radius*2], center: false}).translate([-concave_length*2, width/2, 0])) ); return result.translate([concave_length/2,0,0]); } function make_kicknose_curve(kicknose_radius, thickness, width, kicknose_angle, nose_transition_length, concave_length) { var result = new CSG(); result = difference( difference( rotate([90,0,90], difference( cylinder({r: kicknose_radius+thickness, h: width, center: false, fn: 100}), cylinder({r: kicknose_radius, h: width+2, center: false, fn: 100}).translate([0,0,-1]) )), rotate([0,0,90], cube({size: [kicknose_radius*2, width*4, kicknose_radius*8], center: false}).translate([-kicknose_radius*2, -width*2, -kicknose_radius-2]) )), mirror([1,0,0], rotate([0, kicknose_angle, -90], cube({size: [kicknose_radius*2, width*4, kicknose_radius*4], center: false}).translate([-kicknose_radius*2, -width*2, -kicknose_radius*2]))) ).translate([0,0,kicknose_radius+thickness]); result = rotate([0,0,-90],(result.translate([-width/2,0,0]))); result = result.translate([concave_length/2+nose_transition_length,0,0]); return result; } function make_kicktail_curve(kicktail_radius, thickness, width, kicktail_angle, tail_transition_length, concave_length) { var result = new CSG(); result = mirror([0,1,0], difference( difference( rotate([90,0,90], difference( cylinder({r: kicktail_radius+thickness, h: width, center: false, fn: 100}), cylinder({r: kicktail_radius, h: width+2, center: false, fn: 100}).translate([0,0,-1]) )), rotate([0,0,90], cube({size: [kicktail_radius*2, width*4, kicktail_radius*8], center: false}).translate([-kicktail_radius*2, -width*2, -kicktail_radius-2]) )), mirror([1,0,0], rotate([0, kicktail_angle, -90], cube({size: [kicktail_radius*2, width*4, kicktail_radius*4], center: false}).translate([-kicktail_radius*2, -width*2, -kicktail_radius*2]))) ).translate([0,0,kicktail_radius+thickness]) ); result = rotate([0,0,-90],(result.translate([-width/2,0,0]))); result = result.translate([-concave_length/2-tail_transition_length,0,0]); return result; } function make_kicknose_section(wheelbase, bolt_pattern_length, nose_length, kicknose_length, kicknose_radius_length, width, kicknose_radius_height, thickness, kicknose_angle, nose_transition_length, concave_length) { var result = new CSG(); result = mirror([0,0,1], cube({size: [kicknose_length, width, thickness]})); result = rotate([0,-kicknose_angle,0],result); result = result.translate([concave_length/2+nose_transition_length+kicknose_radius_length,-width/2,kicknose_radius_height+thickness]); return result; } function make_kicktail_section(wheelbase, bolt_pattern_length, tail_length, kicktail_length, kicktail_radius_length, width, kicktail_radius_height, thickness, kicktail_angle, tail_transition_length, concave_length) { var result = new CSG(); result = mirror([0,0,1], cube({size: [kicktail_length, width, thickness]})); result = rotate([0,-kicktail_angle,0],result); result = mirror([1,0,0], result); result = result.translate([-(concave_length/2+tail_transition_length+kicktail_radius_length),-width/2,kicktail_radius_height+thickness]); return result; } function make_transition_section(transition_length, thickness, slice_thickness, width, min_radius, number_of_segments) { var result = new CSG(); var number_of_steps = transition_length/slice_thickness; var concave_depth = (2*min_radius-sqrt(pow(2*min_radius,2)-(4*1*pow(width,2)/4)))/(2*1); var mid_depth = concave_depth/2; var mid_radius = (pow(mid_depth,2)+(pow(width,2)/4))/(2*mid_depth); // var max_radius = pow(mid_radius,2); //if poor transition, uncomment the following and comment the above: var max_radius = 6*mid_radius; var correction = mid_radius; var radius_range = max_radius - min_radius; var radius_offset = min_radius; var sub_radius_range = (max_radius+thickness) - (min_radius+thickness); var sub_radius_offset = min_radius+thickness; //y values for edges of arc var normal_y = ((2*min_radius)-Math.sqrt(Math.pow(2*min_radius,2)-(4*Math.pow((width/2),2))))/(2); //concave depth var flat_y = 0; //no concave //for start and end tangency, plot hollow cylindrical arcs as a sigmoid function... y = 1/(1+e^x). Adjust for the radius size (multiply by the range), then offset for the minimum (add min_radius) var i_range = 8; //range from -2 to 2 for the x value of sigmoid var i_size = i_range/number_of_steps; //change in x value per change in step var origin_x = 0; var origin_y = 0; var a = -3; var slice_adj = 0; for (var i = a; i < a+i_range; i=i+i_size) //starting at -2, going until 2 { if (i < 0) { var y_val = normal_y+((flat_y-normal_y)/(1+Math.exp(i*1.25))); } else { var y_val = normal_y+((flat_y-normal_y)/(1+Math.exp(i))); } var reg_radius = (Math.pow((width/2),2) + Math.pow(y_val,2))/(2*y_val); var reg_half_angle = asin((width/2)/reg_radius); var reg_segment_angle = reg_half_angle/number_of_segments; var sub_radius = reg_radius+thickness; var sub_half_angle = asin((width/2)/sub_radius); var sub_segment_angle = sub_half_angle/number_of_segments; result = result.union( linear_extrude({height: slice_thickness, center: false}, polygon({ //currently set up for 20 segments per full arc: points: [ [(sub_radius*sin(sub_segment_angle*0)),(sub_radius*cos(sub_segment_angle*0))], [(sub_radius*sin(sub_segment_angle*1)),(sub_radius*cos(sub_segment_angle*1))], [(sub_radius*sin(sub_segment_angle*2)),(sub_radius*cos(sub_segment_angle*2))], [(sub_radius*sin(sub_segment_angle*3)),(sub_radius*cos(sub_segment_angle*3))], [(sub_radius*sin(sub_segment_angle*4)),(sub_radius*cos(sub_segment_angle*4))], [(sub_radius*sin(sub_segment_angle*5)),(sub_radius*cos(sub_segment_angle*5))], [(sub_radius*sin(sub_segment_angle*6)),(sub_radius*cos(sub_segment_angle*6))], [(sub_radius*sin(sub_segment_angle*7)),(sub_radius*cos(sub_segment_angle*7))], [(sub_radius*sin(sub_segment_angle*8)),(sub_radius*cos(sub_segment_angle*8))], [(sub_radius*sin(sub_segment_angle*9)),(sub_radius*cos(sub_segment_angle*9))], [(sub_radius*sin(sub_segment_angle*10)),(sub_radius*cos(sub_segment_angle*10))], [(reg_radius*sin(reg_segment_angle*10)),(reg_radius*cos(reg_segment_angle*10))], [(reg_radius*sin(reg_segment_angle*9)),(reg_radius*cos(reg_segment_angle*9))], [(reg_radius*sin(reg_segment_angle*8)),(reg_radius*cos(reg_segment_angle*8))], [(reg_radius*sin(reg_segment_angle*7)),(reg_radius*cos(reg_segment_angle*7))], [(reg_radius*sin(reg_segment_angle*6)),(reg_radius*cos(reg_segment_angle*6))], [(reg_radius*sin(reg_segment_angle*5)),(reg_radius*cos(reg_segment_angle*5))], [(reg_radius*sin(reg_segment_angle*4)),(reg_radius*cos(reg_segment_angle*4))], [(reg_radius*sin(reg_segment_angle*3)),(reg_radius*cos(reg_segment_angle*3))], [(reg_radius*sin(reg_segment_angle*2)),(reg_radius*cos(reg_segment_angle*2))], [(reg_radius*sin(reg_segment_angle*1)),(reg_radius*cos(reg_segment_angle*1))], [(reg_radius*sin(reg_segment_angle*0)),(reg_radius*cos(reg_segment_angle*0))] ] })).translate([0,-sub_radius,slice_adj]) ); slice_adj = slice_adj + slice_thickness; } result = result.union(mirror([1,0,0],result)); result = rotate([-90,0,0],result); return result; } function make_profile(width, wheelbase, boltL, nose_length, tail_length, length, taperN, taperT, nose_shape, tail_shape, depth) { var profile = new CSG.Path2D([[0,(width/2)],[(((wheelbase/2)+boltL+nose_length)-taperN),(width/2)]]); profile = profile.appendBezier([[((((wheelbase/2)+boltL+nose_length)-taperN)+(nose_shape*(taperN))),(width/2)],[((wheelbase/2)+boltL+nose_length),(nose_shape*(width/2))],[((wheelbase/2)+boltL+nose_length),0]], {resolution: 100}); profile = profile.appendBezier([[((wheelbase/2)+boltL+nose_length),(-(nose_shape*(width/2)))],[((((wheelbase/2)+boltL+nose_length)-taperN)+(nose_shape*(taperN))),(-(width/2))],[(((wheelbase/2)+boltL+nose_length)-taperN),(-(width/2))]], {resolution: 100}); profile = profile.appendPoint([0,(-(width/2))]); profile = profile.appendPoint([-(((wheelbase/2)+boltL+tail_length)-taperT),-(width/2)]); profile = profile.appendBezier([[-((((wheelbase/2)+boltL+tail_length)-taperT)+(tail_shape*(taperT))),-(width/2)],[-((wheelbase/2)+boltL+tail_length),-(tail_shape*(width/2))],[-((wheelbase/2)+boltL+tail_length),0]], {resolution: 100}); profile = profile.appendBezier([[-((wheelbase/2)+boltL+tail_length),((tail_shape*(width/2)))],[-((((wheelbase/2)+boltL+tail_length)-taperT)+(tail_shape*(taperT))),((width/2))],[-(((wheelbase/2)+boltL+tail_length)-taperT),((width/2))]], {resolution: 100}); profile = profile.appendPoint([0,(width/2)]); profile = profile.close(); var skateboard = profile.innerToCAG(); skateboard = linear_extrude({height: depth}, skateboard); return skateboard; }

...

Domestic (USA) shipping only at this time.

If you live outside of the US and would like to order, please send a message for a shipping quote.

Fingerboard Build Kit (Your Design) - 5 boards

$89.95

Your Design

The kit includes: 1 fingerboard mold set (top and bottom), 1 template, 5 sets of veneers (25 total), 5 sets of fingerboard parts (trucks, wheels, etc.), and 1 fingerboard tool.
You will need wood glue (such as Elmer's or Titebond), clamps, a drill, a 1/16" drill bit, sandpaper, and either some cutters, a power sander, or small hand saw.

Watch the tutorial here: https://youtu.be/ED9Igi55zvg.

See below for images of each part of the kit, or to purchase pieces individually.


Two-piece Fingerboard Mold

$39.95

Your specs:
*Size and color varies

Your mold will be made to produce the board you just designed. Use this to press five 1/42" veneers into a deck.


Template

$19.95

Your template:
*Size and color varies

Your template will be made to the board shape you designed. Use this to trace your board shape on the pressed veneers.


Veneers

40mm x 115mm x 0.6mm (1.57" x 4.72" x 1/42") maple veneer

Pack Size

Each set contains 3 vertical grain veneers and 2 cross grain veneers. Contact us for larger quantities.


Fingerboard Parts Kit

Each set includes 2 trucks (30mm), 4 wheels, 8 screws, and tool. *Colors vary*

Kit Size
*Colors vary

Each fingerboard parts kit comes with the parts you need to assemble a complete fingerboard. Grip tape is not included.


3D Printed Fingerboard (Deck Only)

$9.95

Your Board:
*Color varies

For bulk pricing or special requests, please contact us.