Not logged in, Join Here! or Log In Below:  
News Articles Search    

 Home / 3D Theory & Graphics / I need a special kind of curve! Account Manager
Archive Notice: This thread is old and no longer active. It is here for reference purposes. This thread was created on an older version of the flipcode forums, before the site closed in 2005. Please keep that in mind as you view this thread, as many of the topics and opinions may be outdated.
Shawn Swift

April 11, 2005, 11:57 PM

I've been researching curves all day but I can't find info on how to do the kind of curve I want to do.

Here we have a set of curves.

The first is a linear interpolation between A and B, through C.
The next is a half-cosine interpolation through C.
The next is halfway between the half-cosine and a square wave,
And the last is a square-wave interpolation through C.

As you can see, C remains in a fixed location.

I would like to be able to move smoothly between these curves by adjusting a value from 0..1, where 0 is linear, and 1 is the square wave interpolation.

Also, note that the line does not break in the middle until the full square wave is achieved.

I'm thinking that that is where some value reaches infinity, and that at 0.999 it will almost look like a square wave, but not quite.

I'm also thinking that maybe it is possible that exponential numbers might allow me to achieve this sort of curve, but I'm not sure how. I do know that you can produce curves of varing "sharpness" by increasing an exponent.


April 12, 2005, 12:43 AM

You want y = - x ^ (1 / C)

Where C is 1, 3, 5, 7 etc (odd numbers only!)

Shawn Swift

April 12, 2005, 01:50 AM

Actually, I was experimenting with exponents myself and came up with a similar idea.

But with that equation you give there, I keep getting NAN for negative values of X... 1.0 / 3.0 maybe isn't being represented accurately enough with floating point?

^3 instead produces a nice curve between X of -1 and 1 and Y of 1 and -1, but the flat bit is in the middle of the graph, and I want the flat bits on the ends.

I could flip portions of the graph as needed by using conditionals, but I'd rather not have to resort to that.

Shawn Swift

April 12, 2005, 02:42 AM

I get the kind of curve I want with this, but there's an ABS and an IF statement in it. I'd really like to get rid of those.

This plots the curve I want between X 0..1 and Y 0..1:

  2.         Z = 16.0
  4.         Repeat
  6.                 ; Convert X from 0..1 to -1..1
  7.                 X2 = (X - 0.5) * 2.0
  9.                 ; Convert X from -1..1 to 0..1..0
  10.                 X3 = 1.0 - Abs(X2)
  12.                 Y = X3^Z
  14.                 Y = Y / 2.0
  15.                 If X2 > 0 Then Y = 1.0 - Y
  17.                 Plot 200 + X*100, 200 - Y*100
  19.                 X = X + 0.01
  21.         Until X > 1.0

Shawn Swift

April 12, 2005, 02:48 AM

Here is the graph of the above code, with ^2 for the exponent.

Rui Martins

April 12, 2005, 05:27 AM

Why don't you just make a function which is an interpolation of your functions. For two functions for example you could get something like:

  1. result(x, t) = F1(x)*t + F2(x)*(t-1)

The main problem I see you may have is that you are actually using 3 functions: a linear interpolation, a cosine interpolation and a square interpolation (if that exists).

So basicly you need something of the form
  1. result(x, t) = F1(x)*k1 + F2(x)*(k2) + F3(x)*(k3)

Where k1, k2 and k3 are values (functions) determined by the parameter t, with the following restriction:
k1+k2+k3 = 1
k1(t)+k2(t)+k3(t) = 1

It's up to you to decide how to weight each of the functions.

Depending on what you want to do, and what is your input, you could check on NURBS or B-Splines (a simpler form of NURBS = Non Uniform Rational B-Splines).


April 12, 2005, 06:50 AM

Why don't you just do a bezier?

Rui Martins

April 12, 2005, 08:30 AM

Why don't you just do a bezier?

Bezier is another particular case of the more general NURBS.

Shawn Swift

April 12, 2005, 10:32 AM

Well a linear function and a cosine function are easy. But a square wave function? I don't know how to do that without if statements. Also, if I simply interpolated naively between a sine wave and a square wave, wouldn't I end up with a sharp cliff at the middle point which gradually moves up until I have the full square wave? That isn't what I want.

Those exponents I gave are just the sort of thing I need, if only someone can explain how to simplify all that stuff I have in the code into a nice equation.


April 12, 2005, 12:05 PM

Ok, well here's the function you need, I learned it in Calculus 2 last year.

y = 1 / (1 + C^-x)

where C < 1

The smaller that C gets, the sharper your curve will be, and the closer to 1 C is, the more it will resemble a standard S-Curve (sort of like a cosine). Seriously, this works and is defined over the entire real line.

Shawn Swift

April 12, 2005, 02:48 PM

That equation doesn't work. With a value like 0.9 for C I get something that is almost a horizontal line. With a value like 0.001 I get something which kind of resembles the curves I want, but has the same problem as the expontential functions where the flat bit seems to be in the middle.

Here's the latest method I came up with. This produces the results I want, but obviously I would prefer not to have the if statement, and replacing it with abs() wouldn't be ideal either.

  2. If X < 0.5
  3.    Y = (X * 2)^Z / 2
  4. Else
  5.    Y = 1 - (((1-X) * 2)^Z / 2)
  6. EndIf

Shawn Swift

April 12, 2005, 02:52 PM

Because bezier curves require control points and I don't know how to set one up to get this sort of case where I have one control variable, and I'm going to be using this for image processing and doing one bazier curve calculation per pixel is probably not going to be fast.

Plus I've always thought Bezier produced rather ugly curves and were annoying to use in 2D and 3D packages, so I have an aversion to them. :-)


April 12, 2005, 03:47 PM

You CANNOT define a square wave function without using ABS, SIGNUM or IF/THEN.
I don't know why you want to avoid it. Doing a ^Z is much more expensive.

Also there's no continuous function that would produce a square wave for some finite exponent. It's always the limit for C-->oo that is the square wave.

I don't see what's wrong with y = 1 / (1 + C^-x), it works fine save for the fact that the interpolation of course doesn't "look linear" in C. But this is exactly the exponential function you referred to in your initial request.

I think you need to better define the properties of the function you're looking for. Could you give some reasons for

- why no IF/THEN ?
- why no ABS ?
- why no linear interpolation between
the straight line, sine wave, and square wave ?


April 12, 2005, 04:52 PM

Well, it depends on how many degrees you use :)
The "common" bezier is 4 degrees (i think, haven't done this in a long time), just use 3 degrees instead to have a single control-point.
How the curves look depends entirely on where you set the control-points...


April 12, 2005, 04:52 PM

Isn't it the other way around? That NURBS is an extension of bezier-splines?

John Schultz

April 12, 2005, 07:27 PM

Sounds similar to a neural network activation function (sigmoid): 1/(1 + e^-x).

See the graphs for various methods here:

This thread contains 16 messages.
Hosting by Solid Eight Studios, maker of PhotoTangler Collage Maker.