discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Re: [OpenSCAD] Minimizing torsion sweep for closed paths

M
MichaelAtOz
Mon, Jan 25, 2016 3:00 AM

Bump - didn't make it to the list.

Ronaldo wrote

I have been playing with sweep.scad to render some simple torus knots:

use <scad-utils/transformations.scad>
use <scad-utils/shapes.scad>
use <scad-utils/linalg.scad>
use <scad-utils/transformations.scad>
use <scad-utils/lists.scad>
use
<sweep.scad>

// geometric data
n = 10;  // cord section discretization
d = 20;  // cord section radius
m = 30 ;  // torus discretization
R = 400;  // torus major radius
r = 150;  // torus minor radius

torus_knot(1,9);

module torus_knot(p, q) {
function knot(phi) = [ (rcos(qphi) + R)cos(pphi),
(rcos(qphi) + R)sin(pphi),
rsin(qphi) ];
function section() = [ for(i=[0: 360/n: 360]) [dcos(i), dsin(i)] ];
k = max(p,q)m;
path = [ for (i=[0:k]) knot(360
(i/k)) ];
path_transforms = construct_transform_path(path, closed);
sweep(section(), path_transforms,true);
}

At first, for some values of p and q, there was some very wild torsions
in the shape of the cord. I happily found a nice patch to sweep.scad
posted by Oskar that constructs torsion minimizing sweep rotations
(see
http://forum.openscad.org/Twisty-problem-with-scad-utils-quot-sweep-quot-td9775.html)
With that patch, the horrible torsions had gone.

However, a small but noticeable torsion remained at the junction between
the start and end
of the cord. I had dug into the sweep.scad code and found that there is a
relative rotation
between the end and start sections which is not compensated by the
minimizing torsion
function. Besides, the closed path solution of the sweep library leaves a
"knee" in
the end-start point due to the difference between the starting and ending
tangents.
So, I recoded the patch Oskar posted trying to overcome both flaws.

function construct_torsion_minimizing_rotations(tangents) =
[ for (i = [0:len(tangents)-2])
rotate_from_to(tangents[i],tangents[i+1])
];

function accumulate_rotations(rotations,acc_=[]) = let(i = len(acc_))
i ==  len(rotations) ? acc_ :
accumulate_rotations(rotations,
i == 0 ? [rotations[0]] : concat(acc_, [ rotations[i] *
acc_[i-1] ])
);

function rotationZ(ang) =
[[  cos(ang), sin(ang), 0],
[ -sin(ang), cos(ang), 0],
[        0,        0, 1]];

function tangent_path(path, i, closed) =
i == 0 ?
closed ?
unit(path[1]-path[len(path)-2]):
unit(path[1] - path[0]) :
(i == len(path)-1 ?
closed ?
unit(path[1]-path[len(path)-2]):
unit(path[i] - path[i-1]) :
// 0 < i < len(path)-1
unit(path[i+1]-path[i-1]));

function construct_transform_path(path,closed=false) =
let(
l              = len(path),
tangents        = [ for (i=[0:l-1]) tangent_path(path, i, closed)],
local_rotations =

construct_torsion_minimizing_rotations(concat([[0,0,1]],tangents)),
rotations      = accumulate_rotations(concat(local_rotations)),
v1 = rotations[0][1,0,0],
v2 = rotations[l-1]
[1,0,0],
ang = acos(v1v2) ((v1[1]-v2[1]) > 0? -1: 1), // torsion angle at
the end
rots = [ if (closed) for(j=[1:l]) rotationZ(ang*j/(l-1)) ]
)
closed?
[ for (i = [0:l-1]) construct_rt(rotations[i] * rots[i], path[i]) ]:
[ for (i = [0:l-1]) construct_rt(rotations[i], path[i]) ];

The code is far from efficient but serves to test a concept.

Its main changes are:

  1. tangent_path() has a third parameter to treat adequately closed paths.
  2. construct_transform_path() has also a closed parameter, calculates
    the total rotation at the end of the path and compensates that rotation
    in small steps at each path point for closed paths.

Newly minted Admin - PM me if you need anything, or if I've done something stupid...

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it! http://www.ourfairdeal.org/  time is running out!

View this message in context: http://forum.openscad.org/Minimizing-torsion-sweep-for-closed-paths-tp15813p15880.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Bump - didn't make it to the list. Ronaldo wrote > I have been playing with sweep.scad to render some simple torus knots: > > use &lt;scad-utils/transformations.scad&gt; > use &lt;scad-utils/shapes.scad&gt; > use &lt;scad-utils/linalg.scad&gt; > use &lt;scad-utils/transformations.scad&gt; > use &lt;scad-utils/lists.scad&gt; > use > <sweep.scad> > > > // geometric data > n = 10; // cord section discretization > d = 20; // cord section radius > m = 30 ; // torus discretization > R = 400; // torus major radius > r = 150; // torus minor radius > > torus_knot(1,9); > > module torus_knot(p, q) { > function knot(phi) = [ (r*cos(q*phi) + R)*cos(p*phi), > (r*cos(q*phi) + R)*sin(p*phi), > r*sin(q*phi) ]; > function section() = [ for(i=[0: 360/n: 360]) [d*cos(i), d*sin(i)] ]; > k = max(p,q)*m; > path = [ for (i=[0:k]) knot(360*(i/k)) ]; > path_transforms = construct_transform_path(path, closed); > sweep(section(), path_transforms,true); > } > > At first, for some values of p and q, there was some very wild torsions > in the shape of the cord. I happily found a nice patch to sweep.scad > posted by Oskar that constructs torsion minimizing sweep rotations > (see > http://forum.openscad.org/Twisty-problem-with-scad-utils-quot-sweep-quot-td9775.html) > With that patch, the horrible torsions had gone. > > However, a small but noticeable torsion remained at the junction between > the start and end > of the cord. I had dug into the sweep.scad code and found that there is a > relative rotation > between the end and start sections which is not compensated by the > minimizing torsion > function. Besides, the closed path solution of the sweep library leaves a > "knee" in > the end-start point due to the difference between the starting and ending > tangents. > So, I recoded the patch Oskar posted trying to overcome both flaws. > > function construct_torsion_minimizing_rotations(tangents) = > [ for (i = [0:len(tangents)-2]) > rotate_from_to(tangents[i],tangents[i+1]) > ]; > > function accumulate_rotations(rotations,acc_=[]) = let(i = len(acc_)) > i == len(rotations) ? acc_ : > accumulate_rotations(rotations, > i == 0 ? [rotations[0]] : concat(acc_, [ rotations[i] * > acc_[i-1] ]) > ); > > function rotationZ(ang) = > [[ cos(ang), sin(ang), 0], > [ -sin(ang), cos(ang), 0], > [ 0, 0, 1]]; > > function tangent_path(path, i, closed) = > i == 0 ? > closed ? > unit(path[1]-path[len(path)-2]): > unit(path[1] - path[0]) : > (i == len(path)-1 ? > closed ? > unit(path[1]-path[len(path)-2]): > unit(path[i] - path[i-1]) : > // 0 < i < len(path)-1 > unit(path[i+1]-path[i-1])); > > function construct_transform_path(path,closed=false) = > let( > l = len(path), > tangents = [ for (i=[0:l-1]) tangent_path(path, i, closed)], > local_rotations = > > construct_torsion_minimizing_rotations(concat([[0,0,1]],tangents)), > rotations = accumulate_rotations(concat(local_rotations)), > v1 = rotations[0]*[1,0,0], > v2 = rotations[l-1]*[1,0,0], > ang = acos(v1*v2)* ((v1[1]-v2[1]) > 0? -1: 1), // torsion angle at > the end > rots = [ if (closed) for(j=[1:l]) rotationZ(ang*j/(l-1)) ] > ) > closed? > [ for (i = [0:l-1]) construct_rt(rotations[i] * rots[i], path[i]) ]: > [ for (i = [0:l-1]) construct_rt(rotations[i], path[i]) ]; > > The code is far from efficient but serves to test a concept. > > Its main changes are: > 1. tangent_path() has a third parameter to treat adequately closed paths. > 2. construct_transform_path() has also a closed parameter, calculates > the total rotation at the end of the path and compensates that rotation > in small steps at each path point for closed paths. ----- Newly minted Admin - PM me if you need anything, or if I've done something stupid... Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above. The TPP is no simple “trade agreement.” Fight it! http://www.ourfairdeal.org/ time is running out! -- View this message in context: http://forum.openscad.org/Minimizing-torsion-sweep-for-closed-paths-tp15813p15880.html Sent from the OpenSCAD mailing list archive at Nabble.com.