We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › interpolating curves
Page Index Toggle Pages: 1
interpolating curves (Read 2251 times)
interpolating curves
May 30th, 2008, 7:05am
 
does anyone have any good leads of interpolating curves, preferably the bezier curve?

i need to join a number of points using bezier curves so they are continuous and smooth.  it would also be great if there was some way of controlling how much the beziers curve around the points.

please let me know if u got any leads at all.

thx.
Re: interpolating curves
Reply #1 - Jun 3rd, 2008, 2:17pm
 
It would be interesting to have a sample of the kind of points you need to join. Should the curves pass exactly by the points or just near them? How to determine the orders of points? Can be trivial if relatively linear, less trivial if they are all over the plane.
In short, we need more info.
Re: interpolating curves
Reply #2 - Jun 4th, 2008, 1:57am
 
hi, to be more precise...
the points are created one point at a time (like a mouse trail), they can be placed anywhere on a 2D plane and id like to create a bezier curve of best fit through the points.
i think the curve should pass through the points (although not sure if this is realistic) and also the tightness of the curve should be adjustable through a parameter.

ive done a fair bit of reading on this but having problems of translating the math into code.  once figured out, i think there is a lot of potential for applying this since the bezier curve is so widely used.
Re: interpolating curves
Reply #3 - Jun 4th, 2008, 6:30am
 
Is this sort of what you're looking for?

Code:
// spline curve between random vertices
int nodeCount = 60;
float nodeSize = 6.0;
float padding = 50.0;
Vertex3D[] v = new Vertex3D[nodeCount];

void setup(){
size(500, 500, P3D);
background(255);
lights();

// argument changes spline interpolation
curveTightness(0);

// calc random vertices
for (int i=0; i<v.length; i++){
v[i] = new Vertex3D(random(padding, width-padding), random(padding, height-padding), random(-padding, padding));
}

// draw spline curve
noFill();
stroke(0);
beginShape();
curve(v[0].x, v[0].y, v[0].z, v[0].x, v[0].y, v[0].z, v[1].x, v[1].y, v[1].z, v[2].x, v[2].y, v[2].z);
for (int i=0; i<v.length-3; i++){
curve(v[i].x, v[i].y, v[i].z, v[i+1].x, v[i+1].y, v[i+1].z, v[i+2].x, v[i+2].y, v[i+2].z, v[i+3].x, v[i+3].y, v[i+3].z);
}
curve(v[v.length-3].x, v[v.length-3].y, v[v.length-3].z, v[v.length-2].x, v[v.length-2].y, v[v.length-2].z, v[v.length-1].x, v[v.length-1].y, v[v.length-1].z, v[v.length-1].x, v[v.length-1].y, v[v.length-1].z);

// draw nodes
noStroke();
for (int i=0; i<v.length; i++){
pushMatrix();
translate(v[i].x, v[i].y, v[i].z);
fill(100);
if (i==0 || i == v.length-1){
fill(255, 75, 0);
}
box(nodeSize, nodeSize, nodeSize);
popMatrix();
}
}

class Vertex3D{
float x, y, z;

Vertex3D(){
}

Vertex3D(float x, float y, float z){
this.x = x;
this.y = y;
this.z = z;
}
}
Re: interpolating curves
Reply #4 - Jun 5th, 2008, 1:43am
 
not really...
what you are doing there is using cat-mull rom splines.
as far as i know, they are different to the bezier curve.

the reason why im so hell bent on beziers is because they are used in SVG files to create paths or shapes and can be used in Illustrator.
Re: interpolating curves
Reply #5 - Jun 5th, 2008, 3:51am
 
if you want to get into the math, it's possible to convert catmull-rom curves to beziers. a curve is constructed using a "basis matrix", a 4x4 matrix of numbers that are multiplied out to create the exact curve coordinates. catmull-rom and bezier curves each have their own basis matrix, so you can do:

catmull-rom point * inverse of catmull-rom basis matrix * bezier basis matrix = bezier curve point

and catmull-rom curves (as implemented in p5) have the curveTightness() function that allows you to tweak how closely the points connect (this relates to a multiplier used in the matrix itself).

it's a little mind-bending, but fun when you get it to work :)

or barring all that, there's code around (i think graphics gems had some) that'll try to fit bezier curves to a set of points.
Re: interpolating curves
Reply #6 - May 3rd, 2009, 10:35am
 
http://tog.acm.org/GraphicsGems/gems/FitCurves.c

Is this the Graphics Gems algorithm for fitting a curve to points? I looked into this problem years ago when I was starting out and I hadn't worked in C before. These days I've had a stab at Openframeworks, so I'm not so shy to tackle it.

I'm keen to return to the problem. I'm sure it was Fry or someone that pointed me at either this routine or a similar one. Or is there a better solution that someone may have found in the meantime?

The choice of variable names in that link looks a bit bananas at times, but I'm ready to pull on my conversion gloves if it's the only route available.
Re: interpolating curves
Reply #7 - Jun 15th, 2009, 11:41pm
 
I think the easiest solution( conceptually and in code) to this is using quadratic beziers. The algorithm, as given in Keith Peter's 'Foundation Actionscript 3.0 Animation' and elsewhere ( and not too hard to come up by oneself if you think about it) is to use the given points you want to join as control points ( except the first and last point) of piecewise quadratic beziers anchored between the average of successive pairs of points.
Since Processing does not have quadratic beziers one will have to use its cubic beziers converted to quadratic beziers as given in my post 'quadratic bezier from cubic bezier' in this forum.

Here is some code to smoothly join a set of points captured in a mousedrag( i am capturing only every 5th point to make it more rounded):
Quote:
ArrayList gPts;
int gMvCnt = 0;
void setup()
{
  size(500,400);
  noLoop();
  gPts = new ArrayList();
  noFill();
  smooth();
}

void draw()
{
  int sz = gPts.size();
  if ( sz == 0)
    return;
  beginShape();
  float x1 = ((PVector)gPts.get(0)).x;
  float y1 = ((PVector)gPts.get(0)).y;
  float xc = 0.0;
  float yc = 0.0;
  float x2 = 0.0;
  float y2 = 0.0;
  vertex(x1,y1);
  for ( int i = 1; i< sz - 2; ++i)
  {
    xc = ((PVector)gPts.get(i)).x;
    yc = ((PVector)gPts.get(i)).y;
    x2 = (xc + ((PVector)gPts.get(i+1)).x)*0.5;
    y2 = (yc + ((PVector)gPts.get(i+1)).y)*0.5;
    bezierVertex((x1 + 2.0*xc)/3.0,(y1 + 2.0*yc)/3.0,
              (2.0*xc + x2)/3.0,(2.0*yc + y2)/3.0,x2,y2);
    x1 = x2;
    y1 = y2;
  }
  xc = ((PVector)gPts.get(sz-2)).x;
  yc = ((PVector)gPts.get(sz-2)).y;
  x2 = ((PVector)gPts.get(sz-1)).x;
  y2 = ((PVector)gPts.get(sz-1)).y;
  bezierVertex((x1 + 2.0*xc)/3.0,(y1 + 2.0*yc)/3.0,
         (2.0*xc + x2)/3.0,(2.0*yc + y2)/3.0,x2,y2);
  endShape();
  
}

void mousePressed()
{
  gPts = new ArrayList();
  gPts.add(new PVector(mouseX,mouseY));
  gMvCnt = 0;
}

void mouseDragged()
{
  if ( gMvCnt++ % 5 == 0 )
    gPts.add(new PVector(mouseX,mouseY));
}

void mouseReleased()
{
  redraw();
}

Page Index Toggle Pages: 1