KeyV2/libraries/skin.scad

138 lines
4.2 KiB
OpenSCAD
Raw Normal View History

2017-11-12 09:32:27 +11:00
use <scad-utils/transformations.scad>
use <scad-utils/lists.scad>
// 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 <scad-utils/transformations.scad>
use <scad-utils/trajectory_path.scad>
use <scad-utils/trajectory.scad>
use <scad-utils/shapes.scad>
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);