Discussion:
[OpenSCAD] Wanted: rotate function on vectors
Joymaker
2015-01-25 05:50:48 UTC
Permalink
I wish OpenSCAD had a rotation function which operates on a vector, mimicking
the existing rotate operator which operates on 3-D model material. Like
this:

rotatev(deg_a, [x, y, z], v)

It would transform v into another vector which is rotated around the given
axis by the given number of degrees, as we are accustomed to. Even better if
it could take a list of vectors and rotate them all in the same manner.

This can be written as user code. But before I go and figure out the math
for myself, has anyone out there written it already?




--
View this message in context: http://forum.openscad.org/Wanted-rotate-function-on-vectors-tp11218.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Marius Kintel
2015-01-25 06:32:09 UTC
Permalink
Post by Joymaker
This can be written as user code. But before I go and figure out the math
for myself, has anyone out there written it already?
https://github.com/openscad/scad-utils/blob/master/transformations.scad

-Marius
adrian
2015-01-25 07:51:15 UTC
Permalink
Should be quite simple. To do individual rotations on each axis would be
like this:
http://en.wikipedia.org/wiki/Rotation_matrix#In_three_dimensions
<http://en.wikipedia.org/wiki/Rotation_matrix#In_three_dimensions>
function rotate(rv) =
[[1,0,0],[0,cos(rv[0]),-sin(rv[0])],[0,sin(rv[0]),cos(rv[0])]] *
[[cos(rv[1]),0,sin(rv[1])],[0,1,0],[-sin(rv[1]),0,cos(rv[1])]] *
[[cos(rv[2]),-sin(rv[2]),0],[sin(rv[2]),cos(rv[2]),0],[0,0,1]];
So to do arbitrary, you'd do this:
http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
<http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle>
identity = [[1,0,0],[0,1,0],[0,0,1]];function length(v) =
sqrt(pow(v[0],2)+pow(v[1],2)+pow(v[2],2));function unit_vector(v) =
[v[0]/length(v), v[1]/length(v), v[2]/length(v)];function uv(v) =
unit_vector(v);function rotate(a, v) = cos(a)*identity +
sin(a)*unit_vector(v) + cross((1 - cos(a))*unit_vector(v), unit_vector(v));
To join these together, you'd need a way to determine if a is an array.
There are a few ways to do this, but there's no built in function that does
this definitively that I've found. So I wrote my own that should work in
all cases:
// FUNCTION: is_String(x)// Returns true if x is a string, false
otherwise.function is_string(x) = x == undef || len(x) == undef ? false //
if undef, a boolean or a number : len(str(x,x)) == len(x)*2; // if an
array, this is false// FUNCTION: is_array(x)// Returns true if x is an
array, false otherwise.function is_array(x) = is_string(x) ? false : len(x)
!= undef;
With that you can join the two rotation functions like this:
function rotate(a, v) = is_vector(a) ?
[[1,0,0],[0,cos(a[0]),-sin(a[0])],[0,sin(a[0]),cos(a[0])]] *
[[cos(a[1]),0,sin(a[1])],[0,1,0],[-sin(a[1]),0,cos(a[1])]] *
[[cos(a[2]),-sin(a[2]),0],[sin(a[2]),cos(a[2]),0],[0,0,1]] : cos(a)*identity
+ sin(a)*unit_vector(v) + cross((1 - cos(a))*unit_vector(v),
unit_vector(v));
To do this on a list of vectors, you'd use a for loop
<http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#For_Loop>
.
Hope that helps.A



--
View this message in context: http://forum.openscad.org/Wanted-rotate-function-on-vectors-tp11218p11223.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
adrian
2015-01-25 08:11:40 UTC
Permalink
Sorry, I meant:
function rotate(a, v) = is_array(a) ?
[[1,0,0],[0,cos(a[0]),-sin(a[0])],[0,sin(a[0]),cos(a[0])]] *
[[cos(a[1]),0,sin(a[1])],[0,1,0],[-sin(a[1]),0,cos(a[1])]] *
[[cos(a[2]),-sin(a[2]),0],[sin(a[2]),cos(a[2]),0],[0,0,1]] : cos(a)*identity
+ sin(a)*unit_vector(v) + cross((1 - cos(a))*unit_vector(v),
unit_vector(v));
A




--
View this message in context: http://forum.openscad.org/Wanted-rotate-function-on-vectors-tp11218p11224.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
MichaelAtOz
2015-01-25 08:56:14 UTC
Permalink
This sort of response is why the OpenSCAD community is so
[great/fantastic/cooperative/friendly/intelligent/supportive/etc].



-----
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. This work is published globally via the internet. :) 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/
--
View this message in context: http://forum.openscad.org/Wanted-rotate-function-on-vectors-tp11218p11226.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
adrian
2015-01-25 10:17:19 UTC
Permalink
Oh, looks like I've not done vector algebra is a looooooooong time as I
didn't understand the notation. For getting the arbitrary rotation, it
would look like this:
function identity(d) = d == 0 ? 1 : [for(y=[1:d]) [for(x=[1:d]) x ==
y ? 1 : 0] ];function length(v) = let(x=v[0], y=v[1], z=v[2])
sqrt(x*x + y*y + z*z);function unit_vector(v) = let(x=v[0], y=v[1],
z=v[2]) [x/length(v), y/length(v), z/length(v)];function skew_symmetric(v)
= let(x=v[0], y=v[1], z=v[2]) [[0, -z, y], [z, 0, -x], [-y, x, 0]];function
tensor_product1(u) = let(x=u[0], y=u[1], z=u[2]) [[x*x, x*y, x*z], [x*y,
y*y, y*z], [x*z, y*z, z*z]];function rotate(a, v) = is_array(a) ?
let(rx=a[0], ry=a[1], rz=a[2]) [[1, 0, 0], [0, cos(rx),
-sin(rx)], [0, sin(rx), cos(rx)]] * [[cos(ry), 0, sin(ry)], [0, 1, 0],
[-sin(ry), 0, cos(ry)]] * [[cos(rz), -sin(rz), 0], [sin(rz), cos(rz), 0],
[0, 0, 1]] : let(uv=unit_vector(v)) cos(a)*identity(3) +
sin(a)*skew_symmetric(uv) + (1 - cos(a))*tensor_product1(uv);
If you'll note, I've updated my notation to the new one as it is more
flexible and I find clearer. Make sure you download 2015.01.23 from the
development snapshots. I didn't and didn't understand why some of the newer
features weren't working.
Also, you wanted:
rotatev(deg_a, [x, y, z], v)
but I gave you
rotate(a, v)
To use the rotate function I stated, you would multiply the vector that
comes out of the rotate function. I.e.
echo(rotate(90, [1,0,0]) * [1, 0, 0]);echo(rotate(90, [1,0,0]) * [0, 1,
0]);echo(rotate(90, [1,0,0]) * [0, 0, 1]);
would give you:
ECHO: [1, 0, 0]ECHO: [0, 0, 1]ECHO: [0, -1, 0]
If you want to do against a list of vectors, you'd do this:
echo([for(i=[[1,0,0],[0,1,0],[0,0,1]]) rotate(90, [1,0,0]) * i ]);
which happens to be the same as:
echo([for(i=identity(3)) rotate(90, [1,0,0]) * i ]);
which would give you a similar result as before:
ECHO: [[1, 0, 0], [0, 0, 1], [0, -1, 0]]
This language is new to me and I've learned quite a bit from answering this
question. Hopefully I've not totally confused you in the process. o.O :)
&nbsp;
A




--
View this message in context: http://forum.openscad.org/Wanted-rotate-function-on-vectors-tp11218p11227.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
MichaelAtOz
2015-01-25 12:40:50 UTC
Permalink
Post by adrian
Oh, looks like I've not done vector algebra is a looooooooong time
I suspect not as long as I... at least the seeds are still there until
Alzheimers kicks in...

But your post just reinforces my above post. ;)



-----
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. This work is published globally via the internet. :) 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/
--
View this message in context: http://forum.openscad.org/Wanted-rotate-function-on-vectors-tp11218p11231.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Andrew Plumb
2015-01-25 13:15:23 UTC
Permalink
Note: norm(v) is a built-in function for vectors of any dimension, so you can replace your length(v) function with it.

https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#norm <https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#norm>

For a pair of 3D vectors, cross(v) is also built in:

https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#cross <https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#cross>

Andrew.
function identity(d) = d == 0 ? 1 : [for(y=[1:d]) [for(x=[1:d]) x == y ? 1 : 0] ];
function length(v) = let(x=v[0], y=v[1], z=v[2]) sqrt(x*x + y*y + z*z);
function unit_vector(v) = let(x=v[0], y=v[1], z=v[2]) [x/length(v), y/length(v), z/length(v)];
function skew_symmetric(v) = let(x=v[0], y=v[1], z=v[2]) [[0, -z, y], [z, 0, -x], [-y, x, 0]];
function tensor_product1(u) = let(x=u[0], y=u[1], z=u[2]) [[x*x, x*y, x*z], [x*y, y*y, y*z], [x*z, y*z, z*z]];
function rotate(a, v)
= is_array(a)
? let(rx=a[0], ry=a[1], rz=a[2])
[[1, 0, 0], [0, cos(rx), -sin(rx)], [0, sin(rx), cos(rx)]]
* [[cos(ry), 0, sin(ry)], [0, 1, 0], [-sin(ry), 0, cos(ry)]]
* [[cos(rz), -sin(rz), 0], [sin(rz), cos(rz), 0], [0, 0, 1]]
: let(uv=unit_vector(v))
cos(a)*identity(3) + sin(a)*skew_symmetric(uv) + (1 - cos(a))*tensor_product1(uv);
If you'll note, I've updated my notation to the new one as it is more flexible and I find clearer. Make sure you download 2015.01.23 from the development snapshots. I didn't and didn't understand why some of the newer features weren't working.
rotatev(deg_a, [x, y, z], v)
but I gave you
rotate(a, v)
To use the rotate function I stated, you would multiply the vector that comes out of the rotate function. I.e.
echo(rotate(90, [1,0,0]) * [1, 0, 0]);
echo(rotate(90, [1,0,0]) * [0, 1, 0]);
echo(rotate(90, [1,0,0]) * [0, 0, 1]);
ECHO: [1, 0, 0]
ECHO: [0, 0, 1]
ECHO: [0, -1, 0]
echo([for(i=[[1,0,0],[0,1,0],[0,0,1]]) rotate(90, [1,0,0]) * i ]);
echo([for(i=identity(3)) rotate(90, [1,0,0]) * i ]);
ECHO: [[1, 0, 0], [0, 0, 1], [0, -1, 0]]
This language is new to me and I've learned quite a bit from answering this question. Hopefully I've not totally confused you in the process. o.O :)
A
View this message in context: Re: Wanted: rotate function on vectors <http://forum.openscad.org/Wanted-rotate-function-on-vectors-tp11218p11227.html>
Sent from the OpenSCAD mailing list archive <http://forum.openscad.org/> at Nabble.com.
_______________________________________________
OpenSCAD mailing list
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
--

"The future is already here. It's just not very evenly distributed" -- William Gibson

Me: http://clothbot.com/wiki/ <http://clothbot.com/wiki/>
adrian
2015-01-25 15:25:04 UTC
Permalink
Post by Andrew Plumb
Note: norm(v) is a built-in function for vectors of any dimension, so you
can replace your length(v) function with it.
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#norm
<https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#norm
Cool. And here I had figured out another way to compute the unit vector:
function length(v) = sqrt(([v]*v)[0]);function unit_vector(v) =
v/length(v);
:) I'll swap out my length(v) function for norm(v). Thanks. Though I am a
little surprised that there's no unit(v) function.
Post by Andrew Plumb
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#cross
<https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#cross>
As for cross(v), I know about it. I used it in my first implementation
above when I thought that the x with a circle around it (
<Loading Image...>
) meant cross product. Did I miss a cross product in my functions somewhere?
They appear to be working...
&nbsp
A




--
View this message in context: http://forum.openscad.org/Wanted-rotate-function-on-vectors-tp11218p11233.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
Michele
2015-01-25 16:59:35 UTC
Permalink
I like the way you spaced the text to clearly show the rotation matrix.



--
View this message in context: http://forum.openscad.org/Wanted-rotate-function-on-vectors-tp11218p11236.html
Sent from the OpenSCAD mailing list archive at Nabble.com.
adrian
2015-01-25 18:04:41 UTC
Permalink
Post by Michele
I like the way you spaced the text to clearly show the rotation matrix.
Remember that each line is a rotation matrix, one for each axis, multiplied
together to make the final matrix. But thanks. :)

A



--
View this message in context: http://forum.openscad.org/Wanted-rotate-function-on-vectors-tp11218p11239.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Continue reading on narkive:
Loading...