Domanda

I am really lacking terminology here, so any help with that appreciate. Even it doesn't answer the question it can hopefully get me closer to an answer.

How can I get y from a function of p where the curviness is also a variable (possible between 0 and 1? Or whatever is best?).

badly drawn sketch

I am presuming p is always between 1 and 0, as is the output y.
The graphic is just an illustration, I don't need that exact curve but something close to this idea.

Pseudo code is good enough as an answer or something c-style (c, javascript, etc).

To give a little context, I have a mapping function where one parameter can be the – what I have called – easing function. There are based on the penner equations. So, for example if I wanted to do a easeIn I would provide:

 function (p) { return p * p; };

But I would love to be able to do what is in the images: varying the ease dynamically. With a function like:

function (p, curviness) { return /* something */; }
È stato utile?

Soluzione

You might try messing around with a Superellipse, it seems to have the shape malleability you're looking for. (Special case: Squircle)

Update

Ok, so the equation for the superellipse is as follows:

abs(x/a)^n + abs(y/b)^n = 1

You're going to be working in the range from [0,1] in both so we can discard the absolute values.

The a and b are for the major and minor ellipse axes; we're going to set those to 1 (so that the superellipse only stretches to +/-1 in either direction) and only look at the first quadrant ([0, 1], again).

This leaves us with:

x^n + y^n = 1

You want your end function to look something like:

y = f(p, n)

so we need to get things into that form (solve for y).

Your initial thought on what to do next was correct (but the variables were switched):

y^n = 1 - p^n

substituting your variable p for x.

Now, initially I'd thought of trying to use a log to isolate y, but that would mean we'd have to take log_y on both sides which would not isolate it. Instead, we can take the nth root to cancel the n, thus isolating y:

y = nthRoot(n, 1 - p^n)

If this is confusing, then this might help: square rooting is just raising to a power of 1/2, so if you took a square root of x you'd have:

sqrt(x) == x^(1/2)

and what we did was take the nth root, meaning that we raised things to the 1/n power, which cancels the nth power the y had since you'd be multiplying them:

(y^n)^(1/n) == y^(n * 1/n) == y^1 == y

Thus we can write things as

y = (1 - p^n)^(1/n)

to make things look better.

So, now we have an equation in the form

y = f(p, n)

but we're not done yet: this equation was working with values in the first quadrant of the superellipse; this quadrant's graph looks different from what you wanted -- you wanted what appeared in the second quadrant, only shifted over.

We can rectify this by inverting the graph in the first quadrant. We'll do this by subtracting it from 1. Thus, the final equation will be:

y = 1 - (1 - p^n)^(1/n)

which works just fine by my TI-83's reckoning.

Note: In the Wikipedia article, they mention that when n is between 0 and 1 then the curve will be bowed down/in, when n is equal to 1 you get a straight line, and when n is greater than 1 then it will be bowed out. However, since we're subtracting things from 1, this behavior is reversed! (So 0 thru 1 means it's bowed out, and greater than 1 means it's bowed in).

And there you have it -- I hope that's what you were looking for :)

Altri suggerimenti

Your curviness property is the exponent.

function(p, exp) { return Math.pow(p, exp); }
  • exp = 1 gives you the straight line
  • exp > 1 gives you the exponential lines (bottom two)
  • 0 < exp < 1 gives you the logarithmic lines (top two)

To get "matching" curviness above and below, an exp = 2 would match an exp = 1/2 across the linear dividing line, so you could define a "curviness" function that makes it more intuitive for you.

function curvyInterpolator(p, curviness) {
    curviness = curviness > 0 ? curviness : 1/(-curviness);
    return Math.pow(p, curviness);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top