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 › Best way to convert this into curves
Page Index Toggle Pages: 1
Best way to convert this into curves? (Read 936 times)
Best way to convert this into curves?
Jan 13th, 2010, 5:03am
 
I've written the below sketch with the intent of drawing a smooth curve that will connect all the (xpos,ypos) points, but I've only managed to get it to draw straight lines at the moment - resulting in a jagged, unnatural shape.

Can anyone offer any advice on how best to go about this?
Here's the code:

Code:

int num = 90;
float deg=0;

float[] xpos = new float[num];
float[] ypos = new float[num];

void setup(){
size(600, 600);
smooth();
noFill();

for (int i=0; i<num; i++){
xpos[i]=0;
ypos[i]=0;
}
}
void draw(){
background(25.5);
translate(width/2, height/2);
stroke(255);
path();
}

void path(){
for(int i=0; i<num-1; i++){
xpos[i] = xpos[i+1];
ypos[i] = ypos[i+1];
}
beginShape();
for(int j=1; j<num; j++){
deg += 0.0008;
float n = map(noise(xpos[j]), 0.0, 1.0, 10, 300);
float rx = sin(deg)*n;
float ry = cos(deg)*n;
xpos[num-1] = rx;
ypos[num-1] = ry;

vertex(xpos[j-1], ypos[j-1]);
vertex(xpos[j], ypos[j]);
}
endShape();
}
Re: Best way to convert this into curves?
Reply #1 - Jan 13th, 2010, 6:24am
 
First, let me simplify a bit your code: you get a much faster code with P2D instead of JAVA2D, no need to initialize arrays to default value, no need to recompute over and over a value changing only the last item of the array.
Code:
int num = 90;
float deg = 0;

// By default initialized to 0
float[] xpos = new float[num];
float[] ypos = new float[num];

void setup() {
size(600, 600, P2D);
smooth();
noFill();
}

void draw() {
background(25.5);
translate(width/2, height/2);
stroke(255);
path();
}

void path() {
for(int i = 0; i < num-1; i++) {
xpos[i] = xpos[i+1];
ypos[i] = ypos[i+1];
}
deg += 0.0008 * num;
float n = map(noise(xpos[num-1]), 0.0, 1.0, 10, 300);
float rx = sin(deg)*n;
float ry = cos(deg)*n;
xpos[num-1] = rx;
ypos[num-1] = ry;

beginShape();
vertex(xpos[0], ypos[0]);
for(int j = 1; j < num; j++) {
vertex(xpos[j], ypos[j]);
}
endShape();
}

Next step: I will try to use curves.
Re: Best way to convert this into curves?
Reply #2 - Jan 13th, 2010, 6:42am
 
OK, here are my attempts to get curves (updated for curveXxx per d.rifkin suggestion below):
Code:
final int NUM = 90;
float deg = 0;
int method = 2;
float tightness = 0;

// By default initialized to 0
float[] xpos = new float[NUM];
float[] ypos = new float[NUM];

void setup() {
 size(600, 600, P2D);
 smooth();
 noFill();
}

void draw() {
 background(25.5);
 translate(width/2, height/2);
 stroke(255);
 path();
}

void path() {
 for (int i = 0; i < NUM-1; i++) {
   xpos[i] = xpos[i+1];
   ypos[i] = ypos[i+1];
 }
 deg += 0.0008 * NUM;
 float n = map(noise(xpos[NUM-1]), 0.0, 1.0, 10, 300);
 float rx = sin(deg)*n;
 float ry = cos(deg)*n;
 xpos[NUM-1] = rx;
 ypos[NUM-1] = ry;

 curveTightness(tightness);
 beginShape();
 vertex(xpos[0], ypos[0]);
 for (int j = 1; j < NUM; j++) {
   switch (method) {
   case 1: // Straight lines
vertex(xpos[j], ypos[j]);
break;
   case 2: { // First version of curves
float cp1x = xpos[j-1];
float cp1y = ypos[j-1];
float cp2x = xpos[j];
float cp2y = ypos[j];
bezierVertex(cp1x, cp1y, cp2x, cp2y, (cp1x + cp2x)/2, (cp1y + cp2y)/2);
}
break;
   case 3: { // Second version of curves
// Should compute line parameters and put the control points at a given distance of pos
float cp1x = xpos[j];
float cp1y = ypos[j] - 5;
float cp2x = xpos[j] - 5;
float cp2y = ypos[j];
bezierVertex(cp1x, cp1y, cp2x, cp2y, xpos[j], ypos[j]);
}
break;
   case 4: // Using curve instead of bezier
curveVertex(xpos[j], ypos[j]);
break;
   case 5: // Using curve instead of bezier
curveVertex((xpos[j-1] + xpos[j])/2, (ypos[j-1] + ypos[j])/2);
break;
   default: // Whatever...
   }
 }
 endShape();
}

void keyPressed() {
 if (key == '1') method = 1;
 else if (key == '2') method = 2;
 else if (key == '3') method = 3;
 else if (key == '4') method = 4;
 else if (key == '5') method = 5;
 else if (key == '+') tightness += 0.2;
 else if (key == '-') tightness -= 0.2;
}

I put the code in a switch to quickly change between methods and compare them. You can change the method by pressing 1 to 5, + and - change tightness on 4 and 5.
Re: Best way to convert this into curves?
Reply #3 - Jan 13th, 2010, 10:50am
 
That's a good technique for comparing methods, PhiLho.

The actual curve drawing might work a little bit better using curveVertex() instead of bezierVertex().  When using curveVertex(), you don't explicitly set the tangents—the tangents are automatically computed, with the hope that the overall curve will be fairly smooth (this kind of curve is called a Cardinal Spline).  You can then use curveTightness() to fine-tune how curvy you want the spline to be.

Documentation for curveVertex():

http://processing.org/reference/curveVertex_.html

and for curveTightness():

http://processing.org/reference/curveTightness_.html
Re: Best way to convert this into curves?
Reply #4 - Jan 14th, 2010, 2:33am
 
Good idea, d.rifkin!
I usually prefers Bézier curves to Catmull-Rom splines as I am more familiar with them and I find I have greater control.
But curveXxx is a good fit for this task.
I just update the above code with new test code (4 and 5, use + and - to change tightness coarsely).
Re: Best way to convert this into curves?
Reply #5 - Jan 14th, 2010, 3:14am
 
Thanks for all your help! It makes perfect sense now (doesn't it always Wink )
Re: Best way to convert this into curves?
Reply #6 - Jan 14th, 2010, 3:19am
 
Very useful way of comparing methods actually, will remember that!
Page Index Toggle Pages: 1