[OpenSCAD] Twisted Torus

Ronaldo Persiano rcmpersiano at gmail.com
Fri Oct 5 18:09:22 EDT 2018


Pakinbot,

Your sweep.scad alleviates all the burden of defining the faces of the
polyhedron enveloping the section vertices. It is very general and allows
that lofts may be build provided that the user computes all the section
positions and orientation in the space. For simple cases of tubular forms -
that is, all sections are equal - as the present case of twisted torus, the
user computation of the section positions could be avoided by a generic
process good enough for most cases. The strategy of that generic process is
to define the section positions in the planes "orthogonal to the sweep
path" translated to each path point. That is the strategy behind Oskar
Linde sweep.scad found in the list-comprehension-demos.

I guess that a code that computes the section positions for this case would
answer the needs of lots of modeling cases. As an example, the twisted
torus model might have the following simple expression:

use <Naca_sweep.scad> // https://www.thingiverse.com/thing:900137/files

twistedTorus( 25, 50 );
translate( [-50, 0, 0] ) rotate( [90, 180, 0] ) twistedTorus( 25, 50 );

module twistedTorus(r1,r2,N=30)
{
  path1 = halfcirc(r2, N);
  path2 = Rz_(180, path1);
  sect  = Rz_(-90, halfcirc(r1));
  half1 = sweep_sections(path1, sect, 180);
  half2 = sweep_sections(path2, sect, 180);
  sweep(half1);
  sweep(half2);
}

function halfcirc(r=50, N=30) =
  [for(i=[0:N]) let(w=180/N*i) r*[sin(w),cos(w), 0]];


where sweep_sections is the generic function that generates the list of
sections in position.

Loosely based on the Linde's sweep ideas, I have coded sweep_sections as:

// list of total rotations from p[0] to each p[i]
function totRots(n,lrot, Rz=identity(), M=[identity()]) =
  len(M)>n ?
    M :
    totRots( n, lrot, Rz, concat(M, [lrot[len(M)-1]*M[len(M)-1]*Rz] ));

function sweep_sections(path, section, twist) =
  let(p  = path,
      np = len(p),
      Rz = rotZ(twist/(np-1)), // matriz of twist rotation between steps
      // tangents to the path p
      tgts = [[0,0,1],
              -3*p[0]    + 4*p[1]    - p[2],
              for(i=[1:np-2]) p[i+1]-p[i-1],
              3*p[np-1] - 4*p[np-2] + p[np-3]
             ],
      // rotation between two steps
      lrot = [for(i=[0:np-1])frotFromTo(tgts[i], tgts[i+1])],
      // list of total rotations from p[0] to each p[i]
      rots = [for(i=0, Mi=identity(); i<=len(lrot); Mi= lrot[i]*Mi*Rz,
i=i+1) Mi] ) // same as totRots(len(p), lrot, Rz)
  [for(i=[0:len(p)-1]) transl(transf(section,rots[i+1]),p[i])];


I have resorted to the "C-like for" in its code for simplicity but the
recursive function totRots may be used instead.

The definition above requires a number of useful helper functions I have in
my libraries:

// reflection matrix of direction v
function fmirror(v) =
    norm(v)==0 ? [[1,0,0],[0,1,0],[0,0,1]] :
    let(u = v/norm(v))
    [ [1,0,0] - 2*u[0]*u, [0,1,0] - 2*u[1]*u, [0,0,1] - 2*u[2]*u ];

// rotation matrix of the minimum rotation
// bringing di to do
function frotFromTo(di,do) =
    norm(di-do)==0 || norm(di)==0 || norm(do)==0 ?
        [[1,0,0],[0,1,0],[0,0,1]] :
        fmirror(do/norm(do)+di/norm(di)) * fmirror(di);

function identity() = [[1,0,0],[0,1,0],[0,0,1]];

// translation of a sequence of points
function transl(pts, d) = [for(pt=pts) pt+d];

// Z rotation matrix
function rotZ(ang) = let(c=cos(ang), s=sin(ang))
  [[c,s,0],[-s,c,0],[0,0,1]];

// transform of a list of points by a 3x3 matrix
function transf(pts,M)  = [for(pt=pts) M*pt];


>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openscad.org/pipermail/discuss_lists.openscad.org/attachments/20181005/2b63b3f1/attachment.html>


More information about the Discuss mailing list