typemytype / drawbot

http://www.drawbot.com
Other
408 stars 63 forks source link

Built-in interpolation functions #414

Open djrrb opened 3 years ago

djrrb commented 3 years ago

Reposting from https://forum.drawbot.com/topic/276/built-in-interpolation-functions at @typemytype’s request

I’m curious if you think there is value in adding interpolation functions to DrawBot, similar to lerp(), norm(), and map() in Processing/p5.js.

I understand it’s not good to bloat the initial state, and perhaps this is better handled by an external package. (Or maybe there is already a built-in way to deal with this that I don’t know about?)

Interpolation plays such a big part in so many of my scripts and those I create with my students, and I have cut and pasted the code below into so many of my DrawBot scripts that I felt moved to write this post and ask.

In case you are interested, I am happy to contribute the code I use. It uses the same syntax as Processing, except that remap() is used to avoid conflict with the Python map() function.

Thank you, as always

# Released by DJR under the BSD license 
def lerp(start, stop, amt):
    """
    Return the interpolation factor (between 0 and 1) of a VALUE between START and STOP.
    https://processing.org/reference/lerp_.html
    """
    return float(amt-start) / float(stop-start)

def norm(value, start, stop):
    """
    Interpolate using a value between 0 and 1
    See also: https://processing.org/reference/norm_.html
    """
    return start + (stop-start) * value

def remap(value, start1, stop1, start2, stop2, withinBounds=False):
    """
    Re-maps a number from one range to another.
    """
    factor = lerp(start1, stop1, value)
    if withinBounds:
        if factor < 0: factor = 0
        if factor > 1: factor = 1
    return norm(factor, start2, stop2)
djrrb commented 3 years ago

Just popping back in to document this recent lerpery 😉

https://gist.github.com/typemytype/b44f1d36bca180a6b542109908aee85f

typemytype commented 3 years ago

mmm I would prefer to have a library with interpolation like callbacks so users can import them

this could be embedded or could be pip installed inside DrawBot

djrrb commented 3 years ago

Can I ask what you mean by callbacks in this context? I ask because I might try to make this library.

I can live with importing these from an external library, so feel free to close this issue when you’re ready.

typemytype commented 3 years ago

sorry, a collections of functions like in your example

benkiel commented 3 years ago

It would be nice for new users to not have to import an external library. I found out this weekend that drawbot is doing things like already importing random and choice, so if this was an external package, then I'd argue it should just be imported like those.

typemytype commented 3 years ago

the main problem is where to stop, lots of handy callbacks can be added to the namespace. Im convinced these interpolation functions are super handy, but other functions for other packages could also be handy...

random and choice are imports from the standard python library, same for all math methods. This is was added in the very first versions of DrawBot, and maybe should be reconsider (that will break lots of code, so this is a bad idea)

https://github.com/typemytype/drawbot/blob/master/drawBot/drawBotDrawingTools.py#L98-L100

joachimvu commented 3 years ago

Fwiw, I systematically import a module with map, lerp and easing functions when using Drawbot for animating stuff. I wouldn’t mind having those built-in!

benkiel commented 2 years ago

Circling back to this: can we just draw the limit at these three and add them? So useful!

justvanrossum commented 2 years ago

Processing has norm and lerp defined the other way around than the above code: lerp interpolates between start and stop using amt as the interpolation factor, norm gives you the interpolation factor of value between start and stop.

I never liked the name lerp, but it seems a common name. I'm ok with adding these three as db built-ins, but as defined in Processing.

I would love to rename the withinBounds arg to "clamp".

djrrb commented 2 years ago

Haha oooooooops 😳😳😳 (guess that means I agree with you about the name lerp not being the most intuitive name...but oh well!)

Here, I think, is the corrected code. Feel free to make any further modifications or write it in a way that suits the project best.

Thank you so much!

# Released by DJR under the BSD license 
def norm(value, start, stop):
    """
    Return the interpolation factor (between 0 and 1) of a VALUE between START and STOP.
    See also: https://processing.org/reference/norm_.html
    """
    return float(value-start) / float(stop-start)

def lerp(start, stop, amt):
    """
    Interpolate using a value between 0 and 1
    https://processing.org/reference/lerp_.html
    """
    return start + (stop-start) * amt

def remap(value, start1, stop1, start2, stop2, clamp=False):
    """
    Re-maps a number from one range to another.
    """
    amt = norm(value, start1, stop1)
    if clamp:
        if factor < 0: factor = 0
        if factor > 1: factor = 1
    return lerp(start2, stop2, amt)
MauriceMeilleur commented 2 years ago

For what small amount it might be worth, I think 'lerp' is great.

typemytype commented 2 years ago

made a PR

this should also be documented...