Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
OpenSCAD demo of transformation using complex numbers
// Demo of using complex numbers to map one 2D point to another.
// Performs rotate and/or scale transform in one operation, without any
// transcendental (trigonometric) functions nor irrational numbers*.
// *please ignore the circular input data
// Enable animation for demo!
// multiply complex numbers
function cmul(c1,c2) = let(a=c1[0],b=c1[1],c=c2[0],d=c2[1])
[a*c-b*d, a*d+b*c];
// divide complex numbers
function cdiv(c1,c2) = let(a=c1[0],b=c1[1],c=c2[0],d=c2[1])
// scale and rotate list of points such that p1 maps to p2
function complex_transform(v,p1,p2) = let(t=cdiv(p2,p1))
[for(p=v) cmul(t,p)];
// Demo
c1 = [5,-5];
c2 = [1,5];
points = [c1, each circle(10,c1)];
demo(points, c1, c2);
module demo(points,p1,p2) {
l = len(points);
// show start and endpoints
color("red") translate(p1) sphere(1/2);
color("green") translate(p2) sphere(1/2);
// initial points
for(i=[0:l-1]) color(hsv(i/l)) translate(points[i]) sphere(1/2,$fn=8);
// animated transform
pv2 = complex_transform(points, p1, lerp(p1,p2,$t));
for(i=[0:l-1]) color(hsv(i/l)) translate(pv2[i]) sphere(1/2,$fn=8);
// Demo-supporting functions
function lerp(a,b,t) = (1-t)*a+b*t;
function fragments(r=1) = ($fn > 0) ?
($fn >= 3 ? $fn : 3) :
ceil(max(min(360.0 / $fa, r*2*PI / $fs), 5));
function circle(r=1, c=[0,0], d) = let(
R = d==undef ? r : d/2,
frags = fragments(R)
) [ for (i = [0:frags-1] ) let(a=360*i/frags) c+R*[cos(a), sin(a)] ];
// HSV function by Hypher:
function doHsvMatrix(h,s,v,p,q,t,a=1)=[h<1?v:h<2?q:h<3?p:h<4?p:h<5?t:v,h<1?t:h<2?v:h<3?v:h<4?q:h<5?p:p,h<1?p:h<2?p:h<3?t:h<4?v:h<5?v:q,a];
function hsv(h, s=1, v=1,a=1)=doHsvMatrix((h%1)*6,s<0?0:s>1?1:s,v<0?0:v>1?1:v,v*(1-s),v*(1-s*((h%1)*6-floor((h%1)*6))),v*(1-s*(1-((h%1)*6-floor((h%1)*6)))),a);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.