loft.scad
1 /** 2 * loft.scad 3 * 4 * @copyright Justin Lin, 2020 5 * @license https://opensource.org/licenses/lgpl-3.0.html 6 * 7 * @see https://openhome.cc/eGossip/OpenSCAD/lib3x-loft.html 8 * 9 **/ 10 11 use <sweep.scad> 12 use <util/lerp.scad> 13 14 module loft(sections, slices = 1) { 15 function gcd(m, n) = n == 0 ? m : gcd(n, m % n); 16 function lcm(m, n) = m * n / gcd(m, n); 17 18 function interpolate(sect, leng, n) = 19 n <= 1 ? sect : 20 let(amts = [each [1:n-1]] / n) 21 [ 22 for(i = 0; i < leng; i = i + 1) 23 let( 24 p1 = sect[i], 25 p2 = sect[(i + 1) % leng] 26 ) 27 each [p1, each [for(amt = amts) lerp(p1, p2, amt)]] 28 ]; 29 30 module _loft(sect1, sect2, slices) { 31 function inter_sects(s1, s2, s_leng, slices) = 32 slices == 1 ? [] : 33 let( 34 dps = [ 35 for(i = [0:lcm_n - 1]) 36 (s2[i] - s1[i]) / slices 37 ] 38 ) 39 [for(i = [1:slices - 1]) s1 + dps * i]; 40 41 leng_sect1 = len(sect1); 42 leng_sect2 = len(sect2); 43 lcm_n = lcm(leng_sect1, leng_sect2); 44 new_sect1 = interpolate(sect1, leng_sect1, lcm_n / leng_sect1); 45 new_sect2 = interpolate(sect2, leng_sect2, lcm_n / leng_sect2); 46 47 sweep([new_sect1, each inter_sects(new_sect1, new_sect2, lcm_n, slices), new_sect2]); 48 } 49 50 for(i = [0:len(sections) - 2]) { 51 _loft(sections[i], sections[i + 1], slices); 52 } 53 }