J
janek
Tue, Jun 23, 2020 9:57 PM
Hello,
is there a way to solve this problem without classic variables?
The setup is (simplified for this example): In a vector I have a number of
vectors that define the dimesions of boxes (length, height). The width for
all boxes is fixed, and all these boxes should be placed one immedialety
after another, however, when the total length exceeds a given maxWidth, the
starting x-position should be reset to zero and y should be increased by
width.
It is a similar problem to e.g. typesetting words aligned to left
In a "normal" scripting language I'd do something like
width = 10;maxWidth = 50;boxes = [ [10,10], [25,5], [5,15], [20, 5], … ];//
this should produce first "line" from the boxes long 10 + 25 + 5// and then,
the fourth box should "jump" to second linecurrentX = 0;currentY = 0;for
(box = boxes) { if (currentX + box[0] > maxWidth) { currentX = 0;
currentY = currentY + width; } translate([currentX, currentY, 0])
cube([box[0], width, box[1]); currentX = currentX + box[0];}
But because of the weird behaviour of the non-variable variables in OpenSCAD
I'm stuck.
Any hint for me? Many thanks.
--
Sent from: http://forum.openscad.org/
Hello,
is there a way to solve this problem without classic variables?
The setup is (simplified for this example): In a vector I have a number of
vectors that define the dimesions of boxes (length, height). The width for
all boxes is fixed, and all these boxes should be placed one immedialety
after another, however, when the total length exceeds a given maxWidth, the
starting x-position should be reset to zero and y should be increased by
width.
It is a similar problem to e.g. typesetting words aligned to left
In a "normal" scripting language I'd do something like
width = 10;maxWidth = 50;boxes = [ [10,10], [25,5], [5,15], [20, 5], … ];//
this should produce first "line" from the boxes long 10 + 25 + 5// and then,
the fourth box should "jump" to second linecurrentX = 0;currentY = 0;for
(box = boxes) { if (currentX + box[0] > maxWidth) { currentX = 0;
currentY = currentY + width; } translate([currentX, currentY, 0])
cube([box[0], width, box[1]); currentX = currentX + box[0];}
But because of the weird behaviour of the non-variable variables in OpenSCAD
I'm stuck.
Any hint for me? Many thanks.
--
Sent from: http://forum.openscad.org/
HJ
Hugo Jackson
Tue, Jun 23, 2020 10:22 PM
Personally, i’d probably uses a recursive function like this:
width = 10;
maxWidth = 50;
boxes = [ [10,10], [25,5], [5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5]];
function justify(width = 0, index = 0, boxesInLine = []) =
(index >= len(boxes)) || (width + boxes[index].x > maxWidth)
? [boxesInLine, width]
: justify( concat(boxesInLine, index), width + boxes[index].x, index + 1)
;
echo(justify());
On Jun 23, 2020, at 2:57 PM, janek jan.koupil@gmail.com wrote:
Hello,
is there a way to solve this problem without classic variables?
The setup is (simplified for this example): In a vector I have a number of vectors that define the dimesions of boxes (length, height). The width for all boxes is fixed, and all these boxes should be placed one immedialety after another, however, when the total length exceeds a given maxWidth, the starting x-position should be reset to zero and y should be increased by width.
It is a similar problem to e.g. typesetting words aligned to left
In a "normal" scripting language I'd do something like
width = 10;
maxWidth = 50;
boxes = [ [10,10], [25,5], [5,15], [20, 5], … ];
// this should produce first "line" from the boxes long 10 + 25 + 5
// and then, the fourth box should "jump" to second line
currentX = 0;
currentY = 0;
for (box = boxes) {
if (currentX + box[0] > maxWidth) {
currentX = 0;
currentY = currentY + width;
}
translate([currentX, currentY, 0])
cube([box[0], width, box[1]);
currentX = currentX + box[0];
}
But because of the weird behaviour of the non-variable variables in OpenSCAD I'm stuck.
Any hint for me? Many thanks.
Sent from the OpenSCAD mailing list archive http://forum.openscad.org/ at Nabble.com.
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Personally, i’d probably uses a recursive function like this:
width = 10;
maxWidth = 50;
boxes = [ [10,10], [25,5], [5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5]];
function justify(width = 0, index = 0, boxesInLine = []) =
(index >= len(boxes)) || (width + boxes[index].x > maxWidth)
? [boxesInLine, width]
: justify( concat(boxesInLine, index), width + boxes[index].x, index + 1)
;
echo(justify());
> On Jun 23, 2020, at 2:57 PM, janek <jan.koupil@gmail.com> wrote:
>
> Hello,
>
> is there a way to solve this problem without classic variables?
>
> The setup is (simplified for this example): In a vector I have a number of vectors that define the dimesions of boxes (length, height). The width for all boxes is fixed, and all these boxes should be placed one immedialety after another, however, when the total length exceeds a given maxWidth, the starting x-position should be reset to zero and y should be increased by width.
>
> It is a similar problem to e.g. typesetting words aligned to left
>
> In a "normal" scripting language I'd do something like
>
>
> width = 10;
> maxWidth = 50;
> boxes = [ [10,10], [25,5], [5,15], [20, 5], … ];
>
> // this should produce first "line" from the boxes long 10 + 25 + 5
> // and then, the fourth box should "jump" to second line
>
> currentX = 0;
> currentY = 0;
> for (box = boxes) {
> if (currentX + box[0] > maxWidth) {
> currentX = 0;
> currentY = currentY + width;
> }
>
> translate([currentX, currentY, 0])
> cube([box[0], width, box[1]);
>
> currentX = currentX + box[0];
> }
> But because of the weird behaviour of the non-variable variables in OpenSCAD I'm stuck.
>
> Any hint for me? Many thanks.
>
>
> Sent from the OpenSCAD mailing list archive <http://forum.openscad.org/> at Nabble.com.
> _______________________________________________
> OpenSCAD mailing list
> Discuss@lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
T
trygve@totallytrygve.com
Tue, Jun 23, 2020 10:50 PM
I had a similar issue recently...
What you're trying is to fit a 1 dimensional problem into a 2 dimensional map.
The currentX and CurrentY may look like a good idea, but... You only need ONE of them.
CurrentX
Just add up the CurrentX, then divide by Maxwidth, an multiply the integer result by the width to et 'CurrentY.
The proper CurrentX position is the modulo of CurrentX and Maxwidth.
translate([CurrentX%maxwidth, floor(CurrentX/Maxwidth, 0])
Something like that, at least...
Why do things complicated?
;-)
Trygve
On 23 June 2020 at 23:57:33 +02:00, janek jan.koupil@gmail.com wrote:
Hello,
is there a way to solve this problem without classic variables?
The setup is (simplified for this example): In a vector I have a number of vectors that define the dimesions of boxes (length, height). The width for all boxes is fixed, and all these boxes should be placed one immedialety after another, however, when the total length exceeds a given maxWidth, the starting x-position should be reset to zero and y should be increased by width.
It is a similar problem to e.g. typesetting words aligned to left
In a "normal" scripting language I'd do something like
width = 10;
maxWidth = 50;
boxes = [ [10,10], [25,5], [5,15], [20, 5], … ];
// this should produce first "line" from the boxes long 10 + 25 + 5
// and then, the fourth box should "jump" to second line
currentX = 0;
currentY = 0;
for (box = boxes) {
if (currentX + box[0] > maxWidth) {
currentX = 0;
currentY = currentY + width;
}
translate([currentX, currentY, 0])
cube([box[0], width, box[1]);
currentX = currentX + box[0];
}
But because of the weird behaviour of the non-variable variables in OpenSCAD I'm stuck.
Any hint for me? Many thanks.
Sent from theOpenSCAD mailing list archive http://forum.openscad.org/ at Nabble.com.
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
I had a similar issue recently...
What you're trying is to fit a 1 dimensional problem into a 2 dimensional map.
The currentX and CurrentY may look like a good idea, but... You only need ONE of them.
CurrentX
Just add up the CurrentX, then divide by Maxwidth, an multiply the integer result by the width to et 'CurrentY.
The proper CurrentX position is the modulo of CurrentX and Maxwidth.
translate([CurrentX%maxwidth, floor(CurrentX/Maxwidth, 0])
Something like that, at least...
Why do things complicated?
;-)
Trygve
On 23 June 2020 at 23:57:33 +02:00, janek <jan.koupil@gmail.com> wrote:
> Hello,
> is there a way to solve this problem without classic variables?
> The setup is (simplified for this example): In a vector I have a number of vectors that define the dimesions of boxes (length, height). The width for all boxes is fixed, and all these boxes should be placed one immedialety after another, however, when the total length exceeds a given maxWidth, the starting x-position should be reset to zero and y should be increased by width.
> It is a similar problem to e.g. typesetting words aligned to left
> In a "normal" scripting language I'd do something like
> width = 10;
> maxWidth = 50;
> boxes = [ [10,10], [25,5], [5,15], [20, 5], … ];
>
> // this should produce first "line" from the boxes long 10 + 25 + 5
> // and then, the fourth box should "jump" to second line
>
> currentX = 0;
> currentY = 0;
> for (box = boxes) {
> if (currentX + box[0] > maxWidth) {
> currentX = 0;
> currentY = currentY + width;
> }
>
> translate([currentX, currentY, 0])
> cube([box[0], width, box[1]);
>
> currentX = currentX + box[0];
> }
> But because of the weird behaviour of the non-variable variables in OpenSCAD I'm stuck.
> Any hint for me? Many thanks.
>
> Sent from theOpenSCAD mailing list archive <http://forum.openscad.org/> at Nabble.com.
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss@lists.openscad.org
> <http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org>
>
JK
Jan Koupil
Thu, Jun 25, 2020 5:21 AM
Thanks,
I must confess, I came to a similar solution. However, since my
programming experience tells me that recursion is a powerful tool with
huge costs (typically memory and performance killer), suffering also
from call stack size limitation (even though it is not my case yet,
would I be able to process something, that would produce a matrix of ca.
100 x 200 elements using recursion?), I was wondering if there is a
better method.
Jan
Dne 24.06.2020 v 0:22 Hugo Jackson napsal(a):
Personally, i’d probably uses a recursive function like this:
width = 10;
maxWidth = 50;
boxes = [ [10,10], [25,5], [5,15], [20, 5], [10,10], [25,5], [5,15],
[20, 5], [10,10], [25,5], [5,15], [20, 5]];
function justify(width = 0, index = 0, boxesInLine = []) =
(index >= len(boxes)) || (width + boxes[index].x > maxWidth)
? [boxesInLine, width]
: justify( concat(boxesInLine, index), width + boxes[index].x, index + 1)
;
echo(justify());
On Jun 23, 2020, at 2:57 PM, janek <jan.koupil@gmail.com
mailto:jan.koupil@gmail.com> wrote:
Hello,
is there a way to solve this problem without classic variables?
The setup is (simplified for this example): In a vector I have a
number of vectors that define the dimesions of boxes (length,
height). The width for all boxes is fixed, and all these boxes should
be placed one immedialety after another, however, when the total
length exceeds a given maxWidth, the starting x-position should be
reset to zero and y should be increased by width.
It is a similar problem to e.g. typesetting words aligned to left
In a "normal" scripting language I'd do something like
|width = 10; maxWidth = 50; boxes = [ [10,10], [25,5], [5,15], [20,
5], … ]; // this should produce first "line" from the boxes long 10 +
25 + 5 // and then, the fourth box should "jump" to second line
currentX = 0; currentY = 0; for (box = boxes) { if (currentX + box[0]
maxWidth) { currentX = 0; currentY = currentY + width; }
Thanks,
I must confess, I came to a similar solution. However, since my
programming experience tells me that recursion is a powerful tool with
huge costs (typically memory and performance killer), suffering also
from call stack size limitation (even though it is not my case yet,
would I be able to process something, that would produce a matrix of ca.
100 x 200 elements using recursion?), I was wondering if there is a
better method.
Jan
Dne 24.06.2020 v 0:22 Hugo Jackson napsal(a):
> Personally, i’d probably uses a recursive function like this:
>
> width = 10;
> maxWidth = 50;
> boxes = [ [10,10], [25,5], [5,15], [20, 5], [10,10], [25,5], [5,15],
> [20, 5], [10,10], [25,5], [5,15], [20, 5]];
>
> function justify(width = 0, index = 0, boxesInLine = []) =
> (index >= len(boxes)) || (width + boxes[index].x > maxWidth)
> ? [boxesInLine, width]
> : justify( concat(boxesInLine, index), width + boxes[index].x, index + 1)
> ;
> echo(justify());
>
>
>> On Jun 23, 2020, at 2:57 PM, janek <jan.koupil@gmail.com
>> <mailto:jan.koupil@gmail.com>> wrote:
>>
>> Hello,
>>
>> is there a way to solve this problem without classic variables?
>>
>> The setup is (simplified for this example): In a vector I have a
>> number of vectors that define the dimesions of boxes (length,
>> height). The width for all boxes is fixed, and all these boxes should
>> be placed one immedialety after another, however, when the total
>> length exceeds a given maxWidth, the starting x-position should be
>> reset to zero and y should be increased by width.
>>
>> It is a similar problem to e.g. typesetting words aligned to left
>>
>> In a "normal" scripting language I'd do something like
>>
>> |width = 10; maxWidth = 50; boxes = [ [10,10], [25,5], [5,15], [20,
>> 5], … ]; // this should produce first "line" from the boxes long 10 +
>> 25 + 5 // and then, the fourth box should "jump" to second line
>> currentX = 0; currentY = 0; for (box = boxes) { if (currentX + box[0]
>> > maxWidth) { currentX = 0; currentY = currentY + width; }
>> translate([currentX, currentY, 0]) cube([box[0], width, box[1]);
>> currentX = currentX + box[0]; } |
>>
>> But because of the weird behaviour of the non-variable variables in
>> OpenSCAD I'm stuck.
>>
>> Any hint for me? Many thanks.
>>
>>
>> ------------------------------------------------------------------------
>> Sent from the OpenSCAD mailing list archive
>> <http://forum.openscad.org/> at Nabble.com <http://Nabble.com>.
>> _______________________________________________
>> OpenSCAD mailing list
>> Discuss@lists.openscad.org <mailto:Discuss@lists.openscad.org>
>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss@lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
JK
Jan Koupil
Thu, Jun 25, 2020 5:51 AM
What you're trying is to fit a 1 dimensional problem into a 2
dimensional map.
That's exactly my problem
The currentX and CurrentY may look like a good idea, but... You only
need ONE of them.
CurrentX
Just add up the CurrentX, then divide by Maxwidth, an multiply the
integer result by the width to et 'CurrentY.
The proper CurrentX position is the modulo of CurrentX and Maxwidth.
|translate([CurrentX%maxwidth, floor(CurrentX/Maxwidth, 0])|
Something like that, at least...
This is what I do for fixed-size boxes (I started with those). I can
simply loop through the vector and calculate current position using
method similar to described. However, here, I cannot calculate
"statically" currentX and I cannot find the way to repeatedly add to the
currentX inside the loop - at least without recursion.
Also, using this method, would boxes be aligned properly? If I
understand it, then not. It is not given that the sum of lengths on
first line would be divisible by MaxWidth and then all further rows
would be shifted, wouldn't they?
But yes, that could have been solved by temporal calculation of
"remaining space" and another addition to currentX - in case I had a
method of summing/incrementing a variable inside a loop.
Why do things complicated?
My words. I love the idea of OpenScad. I bang my forehead to the closest
wall almost every time I try to do something in a normal (for a person
with some experience with common programming languages), readable or
elegant way and call out a loud WHY! :)
Jan
Hello,
is there a way to solve this problem without classic variables?
The setup is (simplified for this example): In a vector I have a
number of vectors that define the dimesions of boxes (length,
height). The width for all boxes is fixed, and all these boxes should
be placed one immedialety after another, however, when the total
length exceeds a given maxWidth, the starting x-position should be
reset to zero and y should be increased by width.
It is a similar problem to e.g. typesetting words aligned to left
In a "normal" scripting language I'd do something like
|width = 10; maxWidth = 50; boxes = [ [10,10], [25,5], [5,15], [20,
5], … ]; // this should produce first "line" from the boxes long 10 +
25 + 5 // and then, the fourth box should "jump" to second line
currentX = 0; currentY = 0; for (box = boxes) { if (currentX + box[0]
maxWidth) { currentX = 0; currentY = currentY + width; }
Thank you,
Dne 24.06.2020 v 0:50 trygve@totallytrygve.com napsal(a):
>
> What you're trying is to fit a 1 dimensional problem into a 2
> dimensional map.
>
That's exactly my problem
> The currentX and CurrentY may look like a good idea, but... You only
> need ONE of them.
> CurrentX
>
> Just add up the CurrentX, then divide by Maxwidth, an multiply the
> integer result by the width to et 'CurrentY.
> The proper CurrentX position is the modulo of CurrentX and Maxwidth.
>
> |translate([CurrentX%maxwidth, floor(CurrentX/Maxwidth, 0])|
>
> Something like that, at least...
This is what I do for fixed-size boxes (I started with those). I can
simply loop through the vector and calculate current position using
method similar to described. However, here, I cannot calculate
"statically" currentX and I cannot find the way to repeatedly add to the
currentX inside the loop - at least without recursion.
Also, using this method, would boxes be aligned properly? If I
understand it, then not. It is not given that the sum of lengths on
first line would be divisible by MaxWidth and then all further rows
would be shifted, wouldn't they?
But yes, that could have been solved by temporal calculation of
"remaining space" and another addition to currentX - in case I had a
method of summing/incrementing a variable inside a loop.
>
> Why do things complicated?
My words. I love the idea of OpenScad. I bang my forehead to the closest
wall almost every time I try to do something in a normal (for a person
with some experience with common programming languages), readable or
elegant way and call out a loud WHY! :)
Jan
>
> ;-)
> Trygve
>
> On 23 June 2020 at 23:57:33 +02:00, janek <jan.koupil@gmail.com> wrote:
>>
>> Hello,
>>
>> is there a way to solve this problem without classic variables?
>>
>> The setup is (simplified for this example): In a vector I have a
>> number of vectors that define the dimesions of boxes (length,
>> height). The width for all boxes is fixed, and all these boxes should
>> be placed one immedialety after another, however, when the total
>> length exceeds a given maxWidth, the starting x-position should be
>> reset to zero and y should be increased by width.
>>
>> It is a similar problem to e.g. typesetting words aligned to left
>>
>> In a "normal" scripting language I'd do something like
>>
>> |width = 10; maxWidth = 50; boxes = [ [10,10], [25,5], [5,15], [20,
>> 5], … ]; // this should produce first "line" from the boxes long 10 +
>> 25 + 5 // and then, the fourth box should "jump" to second line
>> currentX = 0; currentY = 0; for (box = boxes) { if (currentX + box[0]
>> > maxWidth) { currentX = 0; currentY = currentY + width; }
>> translate([currentX, currentY, 0]) cube([box[0], width, box[1]);
>> currentX = currentX + box[0]; } |
>>
>> But because of the weird behaviour of the non-variable variables in
>> OpenSCAD I'm stuck.
>>
>> Any hint for me? Many thanks.
>>
>>
>> ------------------------------------------------------------------------
>> Sent from theOpenSCAD mailing list archive
>> <http://forum.openscad.org/> at Nabble.com.
>> _______________________________________________
>> OpenSCAD mailing list
>> Discuss@lists.openscad.org
>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss@lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
T
trygve@totallytrygve.com
Thu, Jun 25, 2020 10:24 AM
Hi!
Also, using this method, would boxes be aligned properly? If I understand it, then not. It is not given that the sum of lengths on first line would be divisible by MaxWidth and then all further rows would be shifted, wouldn't they?
But yes, that could have been solved by temporal calculation of "remaining space" and another addition to currentX - in case I had a method of summing/incrementing a variable inside a loop.
You're right. That was a mistake on my part.
I believe it can be solved by adding an IF clause and an addition, but yeah, I'm on vacation right now, it's midday and I haven't even had breakfast yet. My brain probably won't work properly for at least a couple of weeks more....
Trygve, or possibly a multiplication
Hi!
Also, using this method, would boxes be aligned properly? If I understand it, then not. It is not given that the sum of lengths on first line would be divisible by MaxWidth and then all further rows would be shifted, wouldn't they?
>
> But yes, that could have been solved by temporal calculation of "remaining space" and another addition to currentX - in case I had a method of summing/incrementing a variable inside a loop.
>
You're right. That was a mistake on my part.
I believe it can be solved by adding an IF clause and an addition, but yeah, I'm on vacation right now, it's midday and I haven't even had breakfast yet. My brain probably won't work properly for at least a couple of weeks more....
Trygve, or possibly a multiplication
TP
Torsten Paul
Thu, Jun 25, 2020 11:42 AM
This seems to work. Doing the calculation before starting
to generate geometry makes it easier to debug and also
there's not really a problem regarding the recursion as
pretty much any list that's too long at this point will
likely be impossible to render later anyway due to number
of vertices generated.
The commented out generator will make 10001 objects which
takes about a second to preview on my notebook.
maxWidth = 9;
o = [
[3, "gray"],
[1, "lightblue"],
[4, "orange"],
[2, "indigo"],
[2, "violet"],
[3, "yellow"],
[5, "green"]
];
/*
maxWidth = 300;
r = rands(1, 10, pow(maxWidth / 3, 2) + 3);
o = [ for (i = [0 : len(r) - 3]) [ r[i], [ r[i + 1], r[i + 2], r[i + 3] ] / 10] ];
*/
function wadd(w, list, idx, cnt = 0) = cnt < 0
? w
: w + wadd(idx < len(list) ? list[idx][0] : 0, list, idx + 1, cnt - 1);
function map(list, w) = [
for (
idx = 0, w = 0, y = 0;
idx < len(list);
w0 = wadd(w, list, idx),
w1 = wadd(w, list, idx, 1),
w = w1 > maxWidth ? 0 : w0,
y = y + (w1 > maxWidth ? 1 : 0),
idx = idx + 1
)
[each list[idx], w, y]
];
echo(Number_of_objects = len(o));
%linear_extrude(1) offset(delta = 1) square(maxWidth);
for (a = map(o)) {
color(a[1]) translate([a[2], a[3], 0]) cube([a.x, 1, rands(2,5,1)[0]]);
}
This seems to work. Doing the calculation before starting
to generate geometry makes it easier to debug and also
there's not really a problem regarding the recursion as
pretty much any list that's too long at this point will
likely be impossible to render later anyway due to number
of vertices generated.
The commented out generator will make 10001 objects which
takes about a second to preview on my notebook.
maxWidth = 9;
o = [
[3, "gray"],
[1, "lightblue"],
[4, "orange"],
[2, "indigo"],
[2, "violet"],
[3, "yellow"],
[5, "green"]
];
/*
maxWidth = 300;
r = rands(1, 10, pow(maxWidth / 3, 2) + 3);
o = [ for (i = [0 : len(r) - 3]) [ r[i], [ r[i + 1], r[i + 2], r[i + 3] ] / 10] ];
*/
function wadd(w, list, idx, cnt = 0) = cnt < 0
? w
: w + wadd(idx < len(list) ? list[idx][0] : 0, list, idx + 1, cnt - 1);
function map(list, w) = [
for (
idx = 0, w = 0, y = 0;
idx < len(list);
w0 = wadd(w, list, idx),
w1 = wadd(w, list, idx, 1),
w = w1 > maxWidth ? 0 : w0,
y = y + (w1 > maxWidth ? 1 : 0),
idx = idx + 1
)
[each list[idx], w, y]
];
echo(Number_of_objects = len(o));
%linear_extrude(1) offset(delta = 1) square(maxWidth);
for (a = map(o)) {
color(a[1]) translate([a[2], a[3], 0]) cube([a.x, 1, rands(2,5,1)[0]]);
}
RP
Ronaldo Persiano
Thu, Jun 25, 2020 11:44 AM
I must confess, I came to a similar solution. However, since my
programming experience tells me that recursion is a powerful tool with huge
costs (typically memory and performance killer), suffering also from call
stack size limitation (even though it is not my case yet, would I be able
to process something, that would produce a matrix of ca. 100 x 200 elements
using recursion?), I was wondering if there is a better method.
Recursion is an invaluable resource you should try to master to easily use
OpenSCAD . You don't need recursion to sum up a list of numbers or get its
accumulated sum but you can't avoid some functions and list comprehension:
// total sum of a list of numbers (or of the rows of a matrix)
function sum(l) = [for(i=[0:len(l)-1]) (i<len(l))? 1: 0]*l;
// the accumulate sum of a list of numbers
function accumSum(l) = [for(i=[0:len(l)-1]) sum([for(j=[0:i]) l[j] ]) ];
To solve your problem we may use recursion to find the break points of the
box rows from the box widths l and maximum width wmax:
function breakPoints(l, wmax, i=0, S=0, breakp=[]) =
i>=len(l)-1
? breakp
: breakPoints( l=l, wmax = wmax ,i=i+1,
S = S+l[i]> wmax ? l[i]:S+l[i],
breakp = concat(breakp,S+l[i]> wmax ? [i]: [] ) );
That is not an easy way for a beginner but it is a tail recursion
elimination solution that doesn't overload stacks.
Luckly, an equivalent non-recursive solution may be written using C-like
for:
function breakPoints(l, wmax) =
[for( i=0, break=false, S=l[0];
i<len(l);
i=i+1, break=S+l[i]> wmax , S=break? l[i]: S+l[i]
) if(break) i];
That might be easier to understand by a beginner used to list comprehension
and imperative programming.
As soon as you have the break points bp of the length list l, the row
lengths may be computed by:
function row_lengths(l,bp) =
[ sum([for(j=[0:1:bp[0]-1]) l[j] ]),
for(i=[1:len(bp)-1]) sum([for(j=[bp[i-1]:1:bp[i]-1]) l[j] ]),
sum([for(j=[bp[len(bp)-1]:1:len(l)-1]) l[j] ])
];
A simple final check of everything:
maxWidth = 50;
boxes = [ [10,10], [5,5], [45,5], [45,15], [45, 5], [10,10], [25,5],
[5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5]];
lens = [for(bi=boxes) bi.x];
echo(lens=lens);
accS = accumSum(lens);
echo(accumSum=accS);
bp = breakPoints(lens,maxWidth);
echo(break_points=bp);
echo(row_lengths=row_lengths(lens,bp));
/*
ECHO: lens = [10, 5, 45, 45, 45, 10, 25, 5, 20, 10, 25, 5, 20]
ECHO: accumSum = [10, 15, 60, 105, 150, 160, 185, 190, 210, 220, 245, 250,
270]
ECHO: break_points = [2, 3, 4, 5, 8, 10]
ECHO: row_lengths = [15, 45, 45, 45, 40, 30, 50]
*/
Using the break points how to find the Y displacement of the rows?
( list comprehension =>
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/List_Comprehensions )
>
> I must confess, I came to a similar solution. However, since my
> programming experience tells me that recursion is a powerful tool with huge
> costs (typically memory and performance killer), suffering also from call
> stack size limitation (even though it is not my case yet, would I be able
> to process something, that would produce a matrix of ca. 100 x 200 elements
> using recursion?), I was wondering if there is a better method.
>
Recursion is an invaluable resource you should try to master to easily use
OpenSCAD . You don't need recursion to sum up a list of numbers or get its
accumulated sum but you can't avoid some functions and list comprehension:
// total sum of a list of numbers (or of the rows of a matrix)
function sum(l) = [for(i=[0:len(l)-1]) (i<len(l))? 1: 0]*l;
// the accumulate sum of a list of numbers
function accumSum(l) = [for(i=[0:len(l)-1]) sum([for(j=[0:i]) l[j] ]) ];
To solve your problem we may use recursion to find the break points of the
box rows from the box widths l and maximum width wmax:
function breakPoints(l, wmax, i=0, S=0, breakp=[]) =
i>=len(l)-1
? breakp
: breakPoints( l=l, wmax = wmax ,i=i+1,
S = S+l[i]> wmax ? l[i]:S+l[i],
breakp = concat(breakp,S+l[i]> wmax ? [i]: [] ) );
That is not an easy way for a beginner but it is a tail recursion
elimination solution that doesn't overload stacks.
Luckly, an equivalent non-recursive solution may be written using C-like
for:
function breakPoints(l, wmax) =
[for( i=0, break=false, S=l[0];
i<len(l);
i=i+1, break=S+l[i]> wmax , S=break? l[i]: S+l[i]
) if(break) i];
That might be easier to understand by a beginner used to list comprehension
and imperative programming.
As soon as you have the break points bp of the length list l, the row
lengths may be computed by:
function row_lengths(l,bp) =
[ sum([for(j=[0:1:bp[0]-1]) l[j] ]),
for(i=[1:len(bp)-1]) sum([for(j=[bp[i-1]:1:bp[i]-1]) l[j] ]),
sum([for(j=[bp[len(bp)-1]:1:len(l)-1]) l[j] ])
];
A simple final check of everything:
maxWidth = 50;
boxes = [ [10,10], [5,5], [45,5], [45,15], [45, 5], [10,10], [25,5],
[5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5]];
lens = [for(bi=boxes) bi.x];
echo(lens=lens);
accS = accumSum(lens);
echo(accumSum=accS);
bp = breakPoints(lens,maxWidth);
echo(break_points=bp);
echo(row_lengths=row_lengths(lens,bp));
/*
ECHO: lens = [10, 5, 45, 45, 45, 10, 25, 5, 20, 10, 25, 5, 20]
ECHO: accumSum = [10, 15, 60, 105, 150, 160, 185, 190, 210, 220, 245, 250,
270]
ECHO: break_points = [2, 3, 4, 5, 8, 10]
ECHO: row_lengths = [15, 45, 45, 45, 40, 30, 50]
*/
Using the break points how to find the Y displacement of the rows?
( list comprehension =>
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/List_Comprehensions )
NH
nop head
Thu, Jun 25, 2020 11:53 AM
In sum() why do you test for i < len(l) when the loop terminates at len(l)
- 1 ? And why would you want a zero in the vector of ones?
On Thu, 25 Jun 2020 at 12:45, Ronaldo Persiano rcmpersiano@gmail.com
wrote:
I must confess, I came to a similar solution. However, since my
programming experience tells me that recursion is a powerful tool with huge
costs (typically memory and performance killer), suffering also from call
stack size limitation (even though it is not my case yet, would I be able
to process something, that would produce a matrix of ca. 100 x 200 elements
using recursion?), I was wondering if there is a better method.
Recursion is an invaluable resource you should try to master to easily use
OpenSCAD . You don't need recursion to sum up a list of numbers or get its
accumulated sum but you can't avoid some functions and list comprehension:
// total sum of a list of numbers (or of the rows of a matrix)
function sum(l) = [for(i=[0:len(l)-1]) (i<len(l))? 1: 0]*l;
// the accumulate sum of a list of numbers
function accumSum(l) = [for(i=[0:len(l)-1]) sum([for(j=[0:i]) l[j] ]) ];
To solve your problem we may use recursion to find the break points of the
box rows from the box widths l and maximum width wmax:
function breakPoints(l, wmax, i=0, S=0, breakp=[]) =
i>=len(l)-1
? breakp
: breakPoints( l=l, wmax = wmax ,i=i+1,
S = S+l[i]> wmax ? l[i]:S+l[i],
breakp = concat(breakp,S+l[i]> wmax ? [i]: [] ) );
That is not an easy way for a beginner but it is a tail recursion
elimination solution that doesn't overload stacks.
Luckly, an equivalent non-recursive solution may be written using C-like
for:
function breakPoints(l, wmax) =
[for( i=0, break=false, S=l[0];
i<len(l);
i=i+1, break=S+l[i]> wmax , S=break? l[i]: S+l[i]
) if(break) i];
That might be easier to understand by a beginner used to list
comprehension and imperative programming.
As soon as you have the break points bp of the length list l, the row
lengths may be computed by:
function row_lengths(l,bp) =
[ sum([for(j=[0:1:bp[0]-1]) l[j] ]),
for(i=[1:len(bp)-1]) sum([for(j=[bp[i-1]:1:bp[i]-1]) l[j] ]),
sum([for(j=[bp[len(bp)-1]:1:len(l)-1]) l[j] ])
];
A simple final check of everything:
maxWidth = 50;
boxes = [ [10,10], [5,5], [45,5], [45,15], [45, 5], [10,10], [25,5],
[5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5]];
lens = [for(bi=boxes) bi.x];
echo(lens=lens);
accS = accumSum(lens);
echo(accumSum=accS);
bp = breakPoints(lens,maxWidth);
echo(break_points=bp);
echo(row_lengths=row_lengths(lens,bp));
/*
ECHO: lens = [10, 5, 45, 45, 45, 10, 25, 5, 20, 10, 25, 5, 20]
ECHO: accumSum = [10, 15, 60, 105, 150, 160, 185, 190, 210, 220, 245, 250,
270]
ECHO: break_points = [2, 3, 4, 5, 8, 10]
ECHO: row_lengths = [15, 45, 45, 45, 40, 30, 50]
*/
Using the break points how to find the Y displacement of the rows?
( list comprehension =>
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/List_Comprehensions )
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
In sum() why do you test for i < len(l) when the loop terminates at len(l)
- 1 ? And why would you want a zero in the vector of ones?
On Thu, 25 Jun 2020 at 12:45, Ronaldo Persiano <rcmpersiano@gmail.com>
wrote:
> I must confess, I came to a similar solution. However, since my
>> programming experience tells me that recursion is a powerful tool with huge
>> costs (typically memory and performance killer), suffering also from call
>> stack size limitation (even though it is not my case yet, would I be able
>> to process something, that would produce a matrix of ca. 100 x 200 elements
>> using recursion?), I was wondering if there is a better method.
>>
> Recursion is an invaluable resource you should try to master to easily use
> OpenSCAD . You don't need recursion to sum up a list of numbers or get its
> accumulated sum but you can't avoid some functions and list comprehension:
>
> // total sum of a list of numbers (or of the rows of a matrix)
> function sum(l) = [for(i=[0:len(l)-1]) (i<len(l))? 1: 0]*l;
>
> // the accumulate sum of a list of numbers
> function accumSum(l) = [for(i=[0:len(l)-1]) sum([for(j=[0:i]) l[j] ]) ];
>
>
> To solve your problem we may use recursion to find the break points of the
> box rows from the box widths l and maximum width wmax:
>
>
> function breakPoints(l, wmax, i=0, S=0, breakp=[]) =
> i>=len(l)-1
> ? breakp
> : breakPoints( l=l, wmax = wmax ,i=i+1,
> S = S+l[i]> wmax ? l[i]:S+l[i],
> breakp = concat(breakp,S+l[i]> wmax ? [i]: [] ) );
>
>
> That is not an easy way for a beginner but it is a tail recursion
> elimination solution that doesn't overload stacks.
>
> Luckly, an equivalent non-recursive solution may be written using C-like
> for:
>
> function breakPoints(l, wmax) =
> [for( i=0, break=false, S=l[0];
> i<len(l);
> i=i+1, break=S+l[i]> wmax , S=break? l[i]: S+l[i]
> ) if(break) i];
>
>
> That might be easier to understand by a beginner used to list
> comprehension and imperative programming.
> As soon as you have the break points bp of the length list l, the row
> lengths may be computed by:
>
> function row_lengths(l,bp) =
> [ sum([for(j=[0:1:bp[0]-1]) l[j] ]),
> for(i=[1:len(bp)-1]) sum([for(j=[bp[i-1]:1:bp[i]-1]) l[j] ]),
> sum([for(j=[bp[len(bp)-1]:1:len(l)-1]) l[j] ])
> ];
>
>
> A simple final check of everything:
>
> maxWidth = 50;
> boxes = [ [10,10], [5,5], [45,5], [45,15], [45, 5], [10,10], [25,5],
> [5,15], [20, 5], [10,10], [25,5], [5,15], [20, 5]];
> lens = [for(bi=boxes) bi.x];
> echo(lens=lens);
> accS = accumSum(lens);
> echo(accumSum=accS);
> bp = breakPoints(lens,maxWidth);
> echo(break_points=bp);
> echo(row_lengths=row_lengths(lens,bp));
> /*
>
> ECHO: lens = [10, 5, 45, 45, 45, 10, 25, 5, 20, 10, 25, 5, 20]
>
> ECHO: accumSum = [10, 15, 60, 105, 150, 160, 185, 190, 210, 220, 245, 250,
> 270]
>
> ECHO: break_points = [2, 3, 4, 5, 8, 10]
>
> ECHO: row_lengths = [15, 45, 45, 45, 40, 30, 50]
>
> */
>
>
> Using the break points how to find the Y displacement of the rows?
>
> ( list comprehension =>
> https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/List_Comprehensions )
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss@lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
RP
Ronaldo Persiano
Thu, Jun 25, 2020 12:03 PM
In sum() why do you test for i < len(l) when the loop terminates at len(l)
- 1 ? And why would you want a zero in the vector of ones?
You are right, the if is unnecessary. I just have done a lazy change in a
more general version of it:
// total sum of the first n elements a list of numbers (or of the rows of a
matrix)
function sum(l,n) = [for(i=[0:len(l)-1]) (i<n)? 1: 0]*l;
>
> In sum() why do you test for i < len(l) when the loop terminates at len(l)
> - 1 ? And why would you want a zero in the vector of ones?
You are right, the if is unnecessary. I just have done a lazy change in a
more general version of it:
// total sum of the first n elements a list of numbers (or of the rows of a
matrix)
function sum(l,n) = [for(i=[0:len(l)-1]) (i<n)? 1: 0]*l;