include ; use ; $fn=360; A=30; N=4; R=45; LENGTH=100; TWIST=720; STEPS=360; SLICES=max(TWIST, STEPS, LENGTH); SHEIGHT=LENGTH/STEPS; BEND_X_FACTOR=0.5; BEND_Y_FACTOR=1; COLORS=[ "#f00", "#f70", "#7f0", "#0f0", "#0f7", "#07f", "#00f", "#70f", "#f07" ]; difference() { union() for (step=[1:STEPS]) { a = A*(1-(step-1)/STEPS); b = A*(1-step/STEPS); r = TWIST/STEPS*(step-1); sh_xy = 0; sh_yx = 0; sh_xz = 1/STEPS*step*BEND_X_FACTOR; sh_yz = 1/STEPS*step*BEND_Y_FACTOR; sh_zx = 0; sh_zy = 0; t_x = sh_xz*SHEIGHT*(step-1)*0.5; t_y = sh_yz*SHEIGHT*(step-1)*0.5; t_z = LENGTH/STEPS*(step-1); sc_x = 1; sc_y = 1; sc_z = 1; mm = [ [sc_x, sh_xy, sh_xz, t_x], [sh_yx, sc_y, sh_yz, t_y], [sh_zx, sh_zy, sc_z, t_z], ]; echo(a, b, b/a, r, mm); multmatrix(mm) color(COLORS[(step-1)%9]) linear_extrude( SHEIGHT, center=false, twist=TWIST/STEPS, scale=b/a, slices=SLICES/STEPS ) rotate(R-r) circle(d=a, $fn=N); } translate([0, 0, INSERTICLE_Z/2]) inserticle(); } echo("twist angle: ", TWIST/STEPS);