discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

More efficient use of lookup for animations?

CS
Chris Spencer
Fri, Mar 6, 2020 10:46 PM

Hi,

I'm new to OpenSCAD's animation feature, and I'm playing around with
some simple animation scripts. Generally, it's very useful, however,
I'm running into a fairly annoying problem.

I started with this guide
(https://www.instructables.com/id/Animating-with-OpenSCAD/) which
recommended wrapping your use of lookup() in a function like:

loc = [
    [0,0,0], // initial position
    [0,0,0], // top body shifts over slightly
    [0,0,10], // lifts leg up
    [0,5,10], // moves leg forward
    [0,5,0], // puts leg down
    [0,5,0], // puts leg down
    [0,5,0], // puts leg down
    [0,5,0], // puts leg down
    [0,5,0], // puts leg down
    [0,5,0], // puts leg down
];

function xyz(t,i) = lookup(t, [
    [0/len(loc),loc[0][i]],
    [1/len(loc),loc[1][i]],
    [2/len(loc),loc[2][i]],
    [3/len(loc),loc[3][i]],
    [4/len(loc),loc[4][i]],
    [5/len(loc),loc[5][i]],
    [6/len(loc),loc[6][i]],
    [7/len(loc),loc[7][i]],
    [8/len(loc),loc[8][i]],
    [9/len(loc),loc[9][i]],
    [10/len(loc),loc[10][i]],
]);

Then you can animate something by simply plugging in a call to
xyz($t, <0|1|2>) inside a translate or rotate statement.

Yet, as you can see, this violates the DRY rule, and makes for some
very tedious and unnecessary code. For every new step added to my
loc array, I need to add an entry to the array inside my xyz()
function as well.

Is there any way to rewrite my xyz() function to generate the array
on demand so I don't have to maintain what are effectively duplicate
arrays? Is a more efficient way to do this that I'm not seeing?

Hi, I'm new to OpenSCAD's animation feature, and I'm playing around with some simple animation scripts. Generally, it's very useful, however, I'm running into a fairly annoying problem. I started with this guide (https://www.instructables.com/id/Animating-with-OpenSCAD/) which recommended wrapping your use of lookup() in a function like: loc = [ [0,0,0], // initial position [0,0,0], // top body shifts over slightly [0,0,10], // lifts leg up [0,5,10], // moves leg forward [0,5,0], // puts leg down [0,5,0], // puts leg down [0,5,0], // puts leg down [0,5,0], // puts leg down [0,5,0], // puts leg down [0,5,0], // puts leg down ]; function xyz(t,i) = lookup(t, [ [0/len(loc),loc[0][i]], [1/len(loc),loc[1][i]], [2/len(loc),loc[2][i]], [3/len(loc),loc[3][i]], [4/len(loc),loc[4][i]], [5/len(loc),loc[5][i]], [6/len(loc),loc[6][i]], [7/len(loc),loc[7][i]], [8/len(loc),loc[8][i]], [9/len(loc),loc[9][i]], [10/len(loc),loc[10][i]], ]); Then you can animate something by simply plugging in a call to `xyz($t, <0|1|2>)` inside a translate or rotate statement. Yet, as you can see, this violates the DRY rule, and makes for some very tedious and unnecessary code. For every new step added to my `loc` array, I need to add an entry to the array inside my `xyz()` function as well. Is there any way to rewrite my `xyz()` function to generate the array on demand so I don't have to maintain what are effectively duplicate arrays? Is a more efficient way to do this that I'm not seeing?
NH
nop head
Fri, Mar 6, 2020 11:25 PM

You don't need to use lookup at all. Just work out the two indices of loc
that t will select a point  between and then use linear
interpolation between those two points. That is what lookup does.

Or you could use list comprehension for loop to make the list to pass to
lookup.

I don't think you need to pass i because lookup should be able to
interpolate vectors.

On Fri, 6 Mar 2020 at 22:47, Chris Spencer chrisspen@gmail.com wrote:

Hi,

I'm new to OpenSCAD's animation feature, and I'm playing around with
some simple animation scripts. Generally, it's very useful, however,
I'm running into a fairly annoying problem.

I started with this guide
(https://www.instructables.com/id/Animating-with-OpenSCAD/) which
recommended wrapping your use of lookup() in a function like:

 loc = [
     [0,0,0], // initial position
     [0,0,0], // top body shifts over slightly
     [0,0,10], // lifts leg up
     [0,5,10], // moves leg forward
     [0,5,0], // puts leg down
     [0,5,0], // puts leg down
     [0,5,0], // puts leg down
     [0,5,0], // puts leg down
     [0,5,0], // puts leg down
     [0,5,0], // puts leg down
 ];

 function xyz(t,i) = lookup(t, [
     [0/len(loc),loc[0][i]],
     [1/len(loc),loc[1][i]],
     [2/len(loc),loc[2][i]],
     [3/len(loc),loc[3][i]],
     [4/len(loc),loc[4][i]],
     [5/len(loc),loc[5][i]],
     [6/len(loc),loc[6][i]],
     [7/len(loc),loc[7][i]],
     [8/len(loc),loc[8][i]],
     [9/len(loc),loc[9][i]],
     [10/len(loc),loc[10][i]],
 ]);

Then you can animate something by simply plugging in a call to
xyz($t, <0|1|2>) inside a translate or rotate statement.

Yet, as you can see, this violates the DRY rule, and makes for some
very tedious and unnecessary code. For every new step added to my
loc array, I need to add an entry to the array inside my xyz()
function as well.

Is there any way to rewrite my xyz() function to generate the array
on demand so I don't have to maintain what are effectively duplicate
arrays? Is a more efficient way to do this that I'm not seeing?


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

You don't need to use lookup at all. Just work out the two indices of loc that t will select a point between and then use linear interpolation between those two points. That is what lookup does. Or you could use list comprehension for loop to make the list to pass to lookup. I don't think you need to pass i because lookup should be able to interpolate vectors. On Fri, 6 Mar 2020 at 22:47, Chris Spencer <chrisspen@gmail.com> wrote: > Hi, > > I'm new to OpenSCAD's animation feature, and I'm playing around with > some simple animation scripts. Generally, it's very useful, however, > I'm running into a fairly annoying problem. > > I started with this guide > (https://www.instructables.com/id/Animating-with-OpenSCAD/) which > recommended wrapping your use of lookup() in a function like: > > loc = [ > [0,0,0], // initial position > [0,0,0], // top body shifts over slightly > [0,0,10], // lifts leg up > [0,5,10], // moves leg forward > [0,5,0], // puts leg down > [0,5,0], // puts leg down > [0,5,0], // puts leg down > [0,5,0], // puts leg down > [0,5,0], // puts leg down > [0,5,0], // puts leg down > ]; > > function xyz(t,i) = lookup(t, [ > [0/len(loc),loc[0][i]], > [1/len(loc),loc[1][i]], > [2/len(loc),loc[2][i]], > [3/len(loc),loc[3][i]], > [4/len(loc),loc[4][i]], > [5/len(loc),loc[5][i]], > [6/len(loc),loc[6][i]], > [7/len(loc),loc[7][i]], > [8/len(loc),loc[8][i]], > [9/len(loc),loc[9][i]], > [10/len(loc),loc[10][i]], > ]); > > Then you can animate something by simply plugging in a call to > `xyz($t, <0|1|2>)` inside a translate or rotate statement. > > Yet, as you can see, this violates the DRY rule, and makes for some > very tedious and unnecessary code. For every new step added to my > `loc` array, I need to add an entry to the array inside my `xyz()` > function as well. > > Is there any way to rewrite my `xyz()` function to generate the array > on demand so I don't have to maintain what are effectively duplicate > arrays? Is a more efficient way to do this that I'm not seeing? > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
RP
Ronaldo Persiano
Mon, Mar 9, 2020 4:22 PM

I don't think you need to pass i because lookup should be able to
interpolate vectors.

It would be nice but lookup only accepts numbers in the table.

Is there any way to rewrite my xyz() function to generate the array

on demand so I don't have to maintain what are effectively duplicate
arrays? Is a more efficient way to do this that I'm not seeing?

You may try this:

function xyz(loc,t) =
t<0 || t>1 ? echo("xyz: t out of range") undef
:
let( s = t*(len(loc)-1),
k = floor(s) )
(1-s+k)*loc[k] + (s-k)*loc[k+1];

that returns the interpolated position from table loc.

> > I don't think you need to pass i because lookup should be able to > interpolate vectors. > It would be nice but lookup only accepts numbers in the table. Is there any way to rewrite my `xyz()` function to generate the array > on demand so I don't have to maintain what are effectively duplicate > arrays? Is a more efficient way to do this that I'm not seeing? You may try this: function xyz(loc,t) = t<0 || t>1 ? echo("xyz: t out of range") undef : let( s = t*(len(loc)-1), k = floor(s) ) (1-s+k)*loc[k] + (s-k)*loc[k+1]; that returns the interpolated position from table loc.
RP
Ronaldo Persiano
Mon, Mar 9, 2020 4:56 PM

My previous code of xyz() has a bug: it returns undef when t=1. Here is a
correction:

function xyz(loc,t) =
t<0 || t>1 ? echo("xyz: t out of range") undef
:
let( s = t*(len(loc)-1),
k = floor(s) )
k<len(loc)-1? (1-s+k)*loc[k] + (s-k)*loc[k+1]: loc[k];

Em seg., 9 de mar. de 2020 às 16:22, Ronaldo Persiano rcmpersiano@gmail.com
escreveu:

I don't think you need to pass i because lookup should be able to

interpolate vectors.

It would be nice but lookup only accepts numbers in the table.

Is there any way to rewrite my xyz() function to generate the array

on demand so I don't have to maintain what are effectively duplicate
arrays? Is a more efficient way to do this that I'm not seeing?

You may try this:

function xyz(loc,t) =
t<0 || t>1 ? echo("xyz: t out of range") undef
:
let( s = t*(len(loc)-1),
k = floor(s) )
(1-s+k)*loc[k] + (s-k)*loc[k+1];

that returns the interpolated position from table loc.

My previous code of xyz() has a bug: it returns undef when t=1. Here is a correction: function xyz(loc,t) = t<0 || t>1 ? echo("xyz: t out of range") undef : let( s = t*(len(loc)-1), k = floor(s) ) k<len(loc)-1? (1-s+k)*loc[k] + (s-k)*loc[k+1]: loc[k]; Em seg., 9 de mar. de 2020 às 16:22, Ronaldo Persiano <rcmpersiano@gmail.com> escreveu: > I don't think you need to pass i because lookup should be able to >> interpolate vectors. >> > > It would be nice but lookup only accepts numbers in the table. > > Is there any way to rewrite my `xyz()` function to generate the array >> on demand so I don't have to maintain what are effectively duplicate >> arrays? Is a more efficient way to do this that I'm not seeing? > > > You may try this: > > > function xyz(loc,t) = > t<0 || t>1 ? echo("xyz: t out of range") undef > : > let( s = t*(len(loc)-1), > k = floor(s) ) > (1-s+k)*loc[k] + (s-k)*loc[k+1]; > > > that returns the interpolated position from table loc. >