use use // Skin a set of profiles with a polyhedral mesh module skin(profiles, loop=false /* unimplemented */) { P = max_len(profiles); N = len(profiles); profiles = [ for (p = profiles) for (pp = augment_profile(to_3d(p),P)) pp ]; function quad(i,P,o) = [[o+i, o+i+P, o+i%P+P+1], [o+i, o+i%P+P+1, o+i%P+1]]; function profile_triangles(tindex) = [ for (index = [0:P-1]) let (qs = quad(index+1, P, P*(tindex-1)-1)) for (q = qs) q ]; triangles = [ for(index = [1:N-1]) for(t = profile_triangles(index)) t ]; start_cap = [range([0:P-1])]; end_cap = [range([P*N-1 : -1 : P*(N-1)])]; polyhedron(convexity=2, points=profiles, faces=concat(start_cap, triangles, end_cap)); } // Augments the profile with steiner points making the total number of vertices n function augment_profile(profile, n) = subdivide(profile,insert_extra_vertices_0([profile_lengths(profile),dup(0,len(profile))],n-len(profile))[1]); function subdivide(profile,subdivisions) = let (N=len(profile)) [ for (i = [0:N-1]) let(n = len(subdivisions)>0 ? subdivisions[i] : subdivisions) for (p = interpolate(profile[i],profile[(i+1)%N],n+1)) p ]; function interpolate(a,b,subdivisions) = [ for (index = [0:subdivisions-1]) let(t = index/subdivisions) a*(1-t)+b*t ]; function distribute_extra_vertex(lengths_count,ma_=-1) = ma_<0 ? distribute_extra_vertex(lengths_count, max_element(lengths_count[0])) : concat([set(lengths_count[0],ma_,lengths_count[0][ma_] * (lengths_count[1][ma_]+1) / (lengths_count[1][ma_]+2))], [increment(lengths_count[1],max_element(lengths_count[0]),1)]); function insert_extra_vertices_0(lengths_count,n_extra) = n_extra <= 0 ? lengths_count : insert_extra_vertices_0(distribute_extra_vertex(lengths_count),n_extra-1); // Find the index of the maximum element of arr function max_element(arr,ma_,ma_i_=-1,i_=0) = i_ >= len(arr) ? ma_i_ : i_ == 0 || arr[i_] > ma_ ? max_element(arr,arr[i_],i_,i_+1) : max_element(arr,ma_,ma_i_,i_+1); function max_len(arr) = max([for (i=arr) len(i)]); function increment(arr,i,x=1) = set(arr,i,arr[i]+x); function profile_lengths(profile) = [ for (i = [0:len(profile)-1]) profile_segment_length(profile,i) ]; function profile_segment_length(profile,i) = norm(profile[(i+1)%len(profile)] - profile[i]); // Generates an array with n copies of value (default 0) function dup(value=0,n) = [for (i = [1:n]) value]; use use use use module fakeISOEnter(thickness_difference = 0){ // 1u is the space taken upy by a 1u keycap. // unit is the space taken up by a unit space for a keycap. // formula is 1u + unit *(length - 1) // t is all modifications to the polygon array t = thickness_difference/2 - (19.02 - 18.16); function unit(length) = 19.02 * length; pointArray = [ [19.05 * (-.5) + t, 19.05 * (-1) + t], [19.05 * (0.5) - t, 19.05 * (-1) + t], [19.05 * (0.5) - t, 19.05 * (1) - t], [19.05 * (-0.75) + t, 19.05 * (1) - t], [19.05 * (-0.75) + t, 19.05 * (0) + t], [19.05 * (-0.5) + t, 19.05 * (0) + t] ]; /*translate([unit(-.5), unit(-1) + 0.86]){*/ minkowski() { circle($corner_radius, $fn=20); offset(r=-$corner_radius * 2, $fn=20) polygon(points=pointArray); } /*}*/ } function isoEnter() = [ [19.05 * (-.5) + (19.02 - 18.16), 19.05 * (-1) + (19.02 - 18.16)], [19.05 * (0.5) - (19.02 - 18.16), 19.05 * (-1) + (19.02 - 18.16)], [19.05 * (0.5) - (19.02 - 18.16), 19.05 * (1) - (19.02 - 18.16)], [19.05 * (-0.75) + (19.02 - 18.16), 19.05 * (1) - (19.02 - 18.16)], [19.05 * (-0.75) + (19.02 - 18.16), 19.05 * (0) + (19.02 - 18.16)], [19.05 * (-0.5) + (19.02 - 18.16), 19.05 * (0) + (19.02 - 18.16)] ]; path_definition = [ trajectory(forward = 10, roll = 0), ]; // sweep path = quantize_trajectories(path_definition, steps=100); // skin myLen = len(path)-1; trans = [ for (i=[0:len(path)-1]) transform(path[i], isoEnter()) ]; translate([0,10,0]) skin(trans);