Anyone got a nice S-shaped function?

Skip to first unread message

Malcolm McLean

Aug 5, 2022, 6:59:03 AMAug 5
I'm looking for a nice S-shaped function which is zero at x= 00, 1 at x = 1, and is montonically increasing.
I want it to be possible to make it very close to the sum of absolute derivatives of the cosine curve (this is the curve you obtain by placing marks at even spaces on the edge of a semicircle, then take the x-coordinates), and I want it to respond intuitively to two markers I'll give to the user. The mid point of the two markers should be the inflection point of the curve, the distance from the marker to the x=0 or x =1 point represents the steepness of the curve.

(What I want it for is to allow the user to specify curved surfaces without having a full 3D drawing system. Most of those surfaces will be semicircular because he'll be drawing a can or a bottle or something similar. Hence the cosine-based curve will be the default. But I want him to have a bit of control
to tweak the surface).

John Forkosh

Aug 6, 2022, 12:13:25 AMAug 6
I'm not following "S-shaped" and "monotonically increasing";
sounds contradictory. In any case, have you considered
Bezier curves,
The first and last control points become the corresponding
endpoints of the generated bezier curve, so specifying them
as (0,0),(1,1) satisfies your boundary conditions.
And you can use whatever input the user's providing to
determine as many intermediate control points as you want,
and/or let the user explicitly specify them.
Here's a short routine I use for bezier curves, where
"point" is the obvious struct, and "binky(n,k)" is the
binomial coefficient n!/k!(n-k)! ...

* Function: bezier ( n, cp, t )
* Purpose: returns x,y-coords of bezier curve
* with n control points cp, at 0.<=t<=1.
* --------------------------------------------------------------------------
* Arguments: n (I) int n>=2, number of control points
* cp (I) point* vector of control points, with
* cp[0] the initial, and cp[n-1] the final
* points of the curve, as usual.
* t (I) double 0.<=t<=1.
* Returns: (point) x,y-coords of bezier curve at t,
* or -1.,-1. for argument error, or any error.
* --------------------------------------------------------------------------
* Notes: o
*======================================================================== */
/* --- entry point --- */
point bezier ( int n, point *cp, double t ) {
/* --- allocations and declarations --- */
point bezt = { -1., -1. }; /* returned point, init for error */
int k=0, binky(); /* binomial coefficient */
/* --- check args --- */
if ( n<2 || cp==NULL /* invalid control points */
|| t<0. || t>1. ) goto end_of_job; /* invalid parameter */
/* --- explicit sum over control points --- */
n--; /* sum from 0...n rather than 0...n-1 */
bezt.x = bezt.y = 0.0; /* init sum */
for ( k=0; k<=n; k++ ) {
double coef=((double)binky(n,k))*pow(1.-t,(double)(n-k))*pow(t,(double)k);
bezt.x += coef*cp[k].x;
bezt.y += coef*cp[k].y;
} /* --- end-of-for(k) --- */
return ( bezt ); /* back to caller */
} /* --- end-of-function bezier() --- */

John Forkosh ( mailto: where j=john and f=forkosh )

Malcolm McLean

Aug 6, 2022, 7:52:29 AMAug 6
S-shaped means that it's got one point of inflection. So it increases slowly at first,
the steeply, then slowly. The curve starts off as concave (from the top) and then
switches to convex. Alternatively it starts off steeply, becomes shallow, and
then becomes steep again. So the curve starts off convex and becomes concave.

A cubic (?) Bezier is a good idea. That satisfies the boundary conditions. Whilst it's easy
to get the inflection point of a Bezier, the problem is going backwards, to create a Bezier
with an inflection point at the midpoint of the markers, and with extra constraints
to make it monotonic, and to make steepness relate to the markers in some intuitive


Aug 6, 2022, 12:58:56 PMAug 6
Why don't you just do something along the lines of:

f(x) = (x-a)^(2*k+1) - b

...where k is a constant natural number, and a, b, help you manipulate the "origin" of the curve?

If you want to stretch it out vertically or horizontally, just multiply (f(x)+b) or (x-a) by a constant.

-Philip White (


Aug 6, 2022, 1:00:45 PMAug 6
Also, if you want it to look more like a cosine curve, examine the Taylor series expansion based on f(x) = cos (x) .

-Philip White


Aug 6, 2022, 1:01:52 PMAug 6
Btw, check out if you want to experiment with a good graphing calculator.

-Philip White

Keith Thompson

Aug 6, 2022, 5:35:16 PMAug 6
Malcolm McLean <> writes:
> I'm looking for a nice S-shaped function which is zero at x= 00, 1 at
> x = 1, and is montonically increasing.

4*arctan(x)/pi ?

Keith Thompson (The_Other_Keith)
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
Reply all
Reply to author
0 new messages