discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

extending MCAD with an example for rotation

PF
Peter Falke
Wed, Apr 1, 2015 5:52 PM

Rotating something into the direction of a vector is a common problem.
It only requires high school math.
But to get the rotation into the right order is often tricky.
I feel this would be a good addition to the MCAD library.

Please have a look at the following code:

​// rotation.scad - Basic example of rotation to draw a vector as an arrow

vect1=[2,3,4];

%cube(vect1);
vector(vect1);

chain=[
[0,0,0],
[0,1,0],
[4,2,3],
[5,2,1],
[7,8,9],
[6,5,2],
];

vector_chain();

//
// Draw an arrow from the origin to the position of the vector v.
// To do this draw an arrow with the length of the length of the vector v.
// Then rotate this arrow into the correct direction.
//
module vector(v){
// radius of the arrow
r=.05;
// number of sides of the arrow
fn_vector=16; //change this to: 3, 4, 16, 32, or 100 (set to 4 makes it
square, set to higher number to make it rounder. But be aware: high numbers
lead to (excessively) long render times.
// length of the arrow
l=norm(v);
// rotate the projection of the vector onto the x-y-plane around the z-axis
// rotate(scalar)=rotate(scalar*[0,0,1])=rotation around the z-axis
rotate(atan2(v[1],v[0]))
// rotate from out of the x-y-plane into the z-direction
rotate([0,-atan2(v[2],norm([v[0],v[1]])),0])
// rotate the cylinder into the plus x-direction
rotate([0,90,0]){
// make an arrow, the tip is 20% of the total length
// shaft
cylinder(h=l*.8,r1=r,r2=r,$fn=fn_vector);
// tip

translate([0,0,l*.8])cylinder(h=l*.2,r1=3*r,r2=0,$fn=fn_vector);
}
}

// Draw a chain of vectors along an array of points
module vector_chain(){
// iterate over all elements of the chain
// ( len(array) gives the number of elements in the array )
for(i=[0:len(chain)-2]){
// translate to the starting point of the vector
translate(chain[i])
// change the color [r,g,b] of the vector
// The first one is blue:[0,0,1], the last one is red:[1,0,0].
color([i/(len(chain)-2),0,1-i/(len(chain)-2)])
// draw the vector from point chain[i] to chain[i+1]
vector(chain[i+1]-chain[i]);
}
}

echo(version=version());
//    Written by: TakeItAndRun
//    2015
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to the
// public domain worldwide. This software is distributed without any
// warranty.
//
// You should have received a copy of the CC0 Public Domain
// Dedication along with this software.
// If not, see http://creativecommons.org/publicdomain/zero/1.0/.

Rotating something into the direction of a vector is a common problem. It only requires high school math. But to get the rotation into the right order is often tricky. I feel this would be a good addition to the MCAD library. Please have a look at the following code: ​// rotation.scad - Basic example of rotation to draw a vector as an arrow vect1=[2,3,4]; %cube(vect1); vector(vect1); chain=[ [0,0,0], [0,1,0], [4,2,3], [5,2,1], [7,8,9], [6,5,2], ]; vector_chain(); // // Draw an arrow from the origin to the position of the vector v. // To do this draw an arrow with the length of the length of the vector v. // Then rotate this arrow into the correct direction. // module vector(v){ // radius of the arrow r=.05; // number of sides of the arrow fn_vector=16; //change this to: 3, 4, 16, 32, or 100 (set to 4 makes it square, set to higher number to make it rounder. But be aware: high numbers lead to (excessively) long render times. // length of the arrow l=norm(v); // rotate the projection of the vector onto the x-y-plane around the z-axis // rotate(scalar)=rotate(scalar*[0,0,1])=rotation around the z-axis rotate(atan2(v[1],v[0])) // rotate from out of the x-y-plane into the z-direction rotate([0,-atan2(v[2],norm([v[0],v[1]])),0]) // rotate the cylinder into the plus x-direction rotate([0,90,0]){ // make an arrow, the tip is 20% of the total length // shaft cylinder(h=l*.8,r1=r,r2=r,$fn=fn_vector); // tip translate([0,0,l*.8])cylinder(h=l*.2,r1=3*r,r2=0,$fn=fn_vector); } } // Draw a chain of vectors along an array of points module vector_chain(){ // iterate over all elements of the chain // ( len(array) gives the number of elements in the array ) for(i=[0:len(chain)-2]){ // translate to the starting point of the vector translate(chain[i]) // change the color [r,g,b] of the vector // The first one is blue:[0,0,1], the last one is red:[1,0,0]. color([i/(len(chain)-2),0,1-i/(len(chain)-2)]) // draw the vector from point chain[i] to chain[i+1] vector(chain[i+1]-chain[i]); } } echo(version=version()); // Written by: TakeItAndRun // 2015 // // To the extent possible under law, the author(s) have dedicated all // copyright and related and neighboring rights to this software to the // public domain worldwide. This software is distributed without any // warranty. // // You should have received a copy of the CC0 Public Domain // Dedication along with this software. // If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
M
mitch
Thu, Apr 2, 2015 12:28 AM

Hey Peter this is really nice.
-I agree, rotations are very useful and tricky to get right. A function to
do this would be very helpful.
-I like how you show the steps with vectors. I'm not sure if frameworks like
this have been implemented/distributed already, but reference features like
these really help the design process.
-I didn't realize it was so easy to make a transparency ('%' prefix) - I'm
going to start using this all the time. It's helpful to see what is going on
inside complex shapes and what primitives compose them.

This reminds me of David's MOCAD kit -
http://forum.openscad.org/Introduction-and-presentation-of-the-Mocad-Library-for-comment-td12175.html

Further, I'd like to see implementation of multiple callable coordinate
frames. (does this exist?)

Mitch

--
View this message in context: http://forum.openscad.org/extending-MCAD-with-an-example-for-rotation-tp12290p12291.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Hey Peter this is really nice. -I agree, rotations are very useful and tricky to get right. A function to do this would be very helpful. -I like how you show the steps with vectors. I'm not sure if frameworks like this have been implemented/distributed already, but reference features like these really help the design process. -I didn't realize it was so easy to make a transparency ('%' prefix) - I'm going to start using this all the time. It's helpful to see what is going on inside complex shapes and what primitives compose them. This reminds me of David's MOCAD kit - http://forum.openscad.org/Introduction-and-presentation-of-the-Mocad-Library-for-comment-td12175.html Further, I'd like to see implementation of multiple callable coordinate frames. (does this exist?) Mitch -- View this message in context: http://forum.openscad.org/extending-MCAD-with-an-example-for-rotation-tp12290p12291.html Sent from the OpenSCAD mailing list archive at Nabble.com.
M
mitch
Thu, Apr 9, 2015 2:10 AM

I made a variant of your code to create coordinate systems relative to one
another, drawing axes at each origin. Check it out below, maybe you will
find it useful, or be able to point to similar work.

Thanks,
Mitch

http://forum.openscad.org/file/n12335/DemoLeg.demoleg
http://forum.openscad.org/file/n12335/BranchingDemo.branchingdemo

//ex_leg();
ex_branching();

//example: multiple "branches"
module ex_branching(){
v0=[0,0,0,0,0,0];
v1=[10,-15,5,0,30,0];
v2=[0,-40,15,0,160,0];
v3=[30,30,30,0,0,45];

axes(v1) {cube(4);
    axes(v1){
    axes(v3){
        translate([4,4,4]) sphere(4,center=true);
    }
        axes(v2){
            axes(v2);
            axes(v1){
                difference(){
                    cube(10);
                    cube(10,center=true);
                }
            }
        }
    };
}

}

//example: leg
module ex_leg(){
v0=[0,0,0,0,0,0];
foot_width=6;foot_length=20;foot_height=4;
joint_radius=3;
leg_width=4;leg_length=60;
a_ankle_x=10;
a_ankle_y=0;
a_ankle_z=0;
a_knee_x=-15;
a_knee_y=0;
a_knee_z=0;
thigh_length=40;
thigh_width=6;

v_foot_leg=[foot_width/2,foot_length+joint_radius,foot_height/2,a_ankle_x,a_ankle_y,a_ankle_z];
v_leg_thigh=[0,0,leg_length+2*joint_radius,a_knee_x,a_knee_y,a_knee_z];

axes(v0){
    %cube([foot_width,foot_length,foot_height]);
    axes(v_foot_leg){
        sphere(joint_radius,center=true);
        translate([0,0,leg_length/2+joint_radius])
        %cube([leg_width,leg_width,leg_length],center=true);
        axes(v_leg_thigh){
            sphere(joint_radius,center=true);
            translate([0,0,thigh_length/2+joint_radius]) 
            %cube([thigh_width,thigh_width,thigh_length],center=true);
        
        }
    }
}

}

//axes reference geometry
module axes(coords){

//represent axes in a particular position and orientation.
x=coords[0];
y=coords[1];
z=coords[2];
rx=coords[3];
ry=coords[4];
rz=coords[5];
h=10;
w=1;
length=sqrt(pow(x,2)+pow(y,2)+pow(z,2));
echo(length);
b=sqrt(pow(x,2)+pow(y,2));

color([0,0,0,1]) rotate(atan2(y,x)) rotate([0,-atan2(z,norm([x,y])),0])

translate([length/2,0,0]) cube([length,.2,.2],center=true);
translate([x,y,z]) rotate([rx,ry,rz]) {
color([1,0,0,1]) translate([h/2,0,0]) cube([h,w,w],center=true);
color([0,1,0,1]) translate([0,h/2,0]) cube([w,h,w],center=true);
color([0,0,1,1]) translate([0,0,h/2]) cube([w,w,h],center=true);
color([0,0,0,1]) cube(2*w,center=true);
children();
}

}

--
View this message in context: http://forum.openscad.org/extending-MCAD-with-an-example-for-rotation-tp12290p12335.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

I made a variant of your code to create coordinate systems relative to one another, drawing axes at each origin. Check it out below, maybe you will find it useful, or be able to point to similar work. Thanks, Mitch <http://forum.openscad.org/file/n12335/DemoLeg.demoleg> <http://forum.openscad.org/file/n12335/BranchingDemo.branchingdemo> //ex_leg(); ex_branching(); //example: multiple "branches" module ex_branching(){ v0=[0,0,0,0,0,0]; v1=[10,-15,5,0,30,0]; v2=[0,-40,15,0,160,0]; v3=[30,30,30,0,0,45]; axes(v1) {cube(4); axes(v1){ axes(v3){ translate([4,4,4]) sphere(4,center=true); } axes(v2){ axes(v2); axes(v1){ difference(){ cube(10); cube(10,center=true); } } } }; } } //example: leg module ex_leg(){ v0=[0,0,0,0,0,0]; foot_width=6;foot_length=20;foot_height=4; joint_radius=3; leg_width=4;leg_length=60; a_ankle_x=10; a_ankle_y=0; a_ankle_z=0; a_knee_x=-15; a_knee_y=0; a_knee_z=0; thigh_length=40; thigh_width=6; v_foot_leg=[foot_width/2,foot_length+joint_radius,foot_height/2,a_ankle_x,a_ankle_y,a_ankle_z]; v_leg_thigh=[0,0,leg_length+2*joint_radius,a_knee_x,a_knee_y,a_knee_z]; axes(v0){ %cube([foot_width,foot_length,foot_height]); axes(v_foot_leg){ sphere(joint_radius,center=true); translate([0,0,leg_length/2+joint_radius]) %cube([leg_width,leg_width,leg_length],center=true); axes(v_leg_thigh){ sphere(joint_radius,center=true); translate([0,0,thigh_length/2+joint_radius]) %cube([thigh_width,thigh_width,thigh_length],center=true); } } } } //axes reference geometry module axes(coords){ //represent axes in a particular position and orientation. x=coords[0]; y=coords[1]; z=coords[2]; rx=coords[3]; ry=coords[4]; rz=coords[5]; h=10; w=1; length=sqrt(pow(x,2)+pow(y,2)+pow(z,2)); echo(length); b=sqrt(pow(x,2)+pow(y,2)); color([0,0,0,1]) rotate(atan2(y,x)) rotate([0,-atan2(z,norm([x,y])),0]) translate([length/2,0,0]) cube([length,.2,.2],center=true); translate([x,y,z]) rotate([rx,ry,rz]) { color([1,0,0,1]) translate([h/2,0,0]) cube([h,w,w],center=true); color([0,1,0,1]) translate([0,h/2,0]) cube([w,h,w],center=true); color([0,0,1,1]) translate([0,0,h/2]) cube([w,w,h],center=true); color([0,0,0,1]) cube(2*w,center=true); children(); } } -- View this message in context: http://forum.openscad.org/extending-MCAD-with-an-example-for-rotation-tp12290p12335.html Sent from the OpenSCAD mailing list archive at Nabble.com.