/ src / loft.scad
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  }