Given an image:
and a set of dimensions:
10x100? Nice and round! and a beam-to beam of 40.
how does one work out a solution in OpenSCAD?
Given an image:
and a set of dimensions:
10x100? Nice and round! and a beam-to beam of 40.
how does one work out a solution in OpenSCAD?
The basics are pretty obvious:
//!OpenSCAD
beamwidth = 10;
beamheight = 100;
beamthickness = 1;
beamspacing = 40;
module beam(bw, bh, bt) {
cube([bw, bh, bt], center=false);
}
union(){
beam(beamwidth, beamheight, beamthickness);
translate([(beamspacing + beamwidth), 0, 0]){
beam(beamwidth, beamheight, beamthickness);
}
}
If we then draw up a rough approximation:
It becomes obvious that we need to solve for:
and that there are three triangles involved, two of which are duplicates:
A workable sequence of calculations should be:
for a given rotation determine the length of the base of the right triangle for the hypotenuse of the beamwidth (10)
given that length, determine the hypotenuse of the large triangle (which will be the length of the rotated beam) based on the base length being:
beamspacing - small triangle base
basically one would loop through rotation values performing these calculations until the solution is reached â€” next up, writing that code.
The first triangle we would need to solve for, at a rotation of 1 degree would be:
so we need the cosine of the rotation multiplied by the beamwidth as the first calculation:
Then, we add in the second:
which gives us a hypotenuse equal to
beamspacing - cos(angle) * beamwidth
though, what we really want is the height of the two triangles â€” add those together, and iterate until they are approximately equal to the beamheightâ€¦
For the height of the first triangle, we of course need the sine of the angle times the hypotenuse, then for the other we need:
//!OpenSCAD
beamwidth = 10;
beamheight = 100;
beamthickness = 1;
beamspacing = 40;
module beam(bw, bh, bt) {
cube([bw, bh, bt], center=false);
}
union(){
beam(beamwidth, beamheight, beamthickness);
translate([(beamspacing + beamwidth), 0, 0]){
beam(beamwidth, beamheight, beamthickness);
}
for (i = [1 : abs(1) : 90]) {
if (beamheight >= sin(i) * beamwidth + (beamspacing - cos(i) * beamwidth) / tan(i)) {
translate([((beamspacing + beamwidth) - cos(i) * beamwidth), 0, i]){
rotate([0, 0, i]){
beam(beamwidth, beamheight, beamthickness);
}
}
}
}
}
and the problem is of course, getting the loop to only output one iterationâ€¦
Fudging that a bit by comparing the next iteration:
//!OpenSCAD
beamwidth = 10;
beamheight = 100;
beamthickness = 1;
beamspacing = 40;
module beam(bw, bh, bt) {
cube([bw, bh, bt], center=false);
}
union(){
beam(beamwidth, beamheight, beamthickness);
translate([(beamspacing + beamwidth), 0, 0]){
beam(beamwidth, beamheight, beamthickness);
}
for (i = [1 : abs(1) : 90]) {
if (beamheight >= sin(i) * beamwidth + (beamspacing - cos(i) * beamwidth) / tan(i) && beamheight * 0.9 <= sin((i + 1)) * beamwidth + (beamspacing - cos((i + 1)) * beamwidth) / tan((i + 1))) {
translate([((beamspacing + beamwidth) - cos(i) * beamwidth), 0, i]){
rotate([0, 0, i]){
beam(beamwidth, ((beamspacing - cos(i) * beamwidth) / tan(i)) / cos(i), beamthickness);
}
}
}
}
}
Put in a query on the OpenSCAD mailing list to see if thereâ€™s a more elegant way to get only one iterationâ€¦
and the answer when I asked after doing this in an elegant fashion on the OpenSCAD mailing list the suggestion was to use recursion.
I had visualized the solution being around 2 right triangles formed by the line between inner corners of 10x100 rectangles then stepping the shorter edge smaller and smaller until their hypotenuses were 10 units apart. But itâ€™s far easier to visualize than actually do it. Thanks for showing your proof.
Couldnâ€™t resist up-dating it to use recursion: