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 & HelpPrograms › Help with bezier polygons
Page Index Toggle Pages: 1
Help with bezier polygons (Read 3250 times)
Help with bezier polygons
Jun 8th, 2010, 2:19pm
 
I think I'm very close to getting this working, but it's not quite there yet.

I've built an application to accept an int polyPoints that describes how many points to give my polygon, and a matching array to describe how far each vertex should be from the center (the whole numbers are treated as % in the code).

It generates the polygon nicely, but I've tried to make the connections into bezier curves with the tension of the curves tied to mouseX. I have small ellipses drawing the control point locations properly, but the curves themselves don't match up with my anticipated output.

If someone could help me jumble this into place, I would be extremely thankful.

Code:



int pointDiameter = 4;
int margin = 20;
float[] points = {
 50,50,50,50,50,50};
int polyPoints = 6;
float polyAngles = 360/polyPoints;
float xVertex;
float yVertex;
float CX1;
float CY1;
float CX2;
float CY2;
float tension;

void setup(){
 size(1000,1000);
 noFill();
 stroke(255);
 smooth();
}

void draw(){
 background(0);
 smooth();
 beginShape();
 drawCurve(points);
 endShape();
 drawPoints(points);
 tension = mouseX/10;
}


void drawCurve(float[] points){

 vertex(width/2 + cos(radians(0)) * ((points[0]/100)*(width/2-margin)), height/2 + sin(radians(0)) * ((points[0]/100)*(height/2-margin))); // origin vertex
 for (int i = 0; i<polyPoints; i++){
   xVertex = width/2 + cos(radians(i * polyAngles)) * ((points[i]/100)*(width/2-margin));
   yVertex = height/2 + sin(radians(i * polyAngles)) * ((points[i]/100)*(height/2-margin));
   CX1 = xVertex + cos(radians(i * polyAngles -90)) * tension;
   CY1 = yVertex + sin(radians(i * polyAngles -90)) * tension;
   CX2 = xVertex + cos(radians(i * polyAngles +90)) * tension;
   CY2 = yVertex + sin(radians(i * polyAngles +90)) * tension;
   bezierVertex(CX1, CY1, CX2, CY2, xVertex, yVertex); // angle vertices
   ellipse(CX1, CY1, pointDiameter, pointDiameter);
   ellipse(CX2, CY2, pointDiameter, pointDiameter);
   println((xVertex-CX1) + ", " + (yVertex-CY1) + ", " + (xVertex-CX2) + ", " + (yVertex-CY2) + ", " + xVertex + ", " + yVertex);
 }
 vertex(width/2 + cos(radians(0)) * ((points[0]/100)*(width/2-margin)), height/2 + sin(radians(0)) * ((points[0]/100)*(height/2-margin))); // origin vertex

}


void drawPoints(float[] points){
 ellipse(width/2, height/2, pointDiameter, pointDiameter); //center point
 for (int i = 0; i<polyPoints; i++){
   ellipse(width/2 + cos(radians(i * polyAngles)) * ((points[i]/100)*(width/2-margin)), height/2 + sin(radians(i * polyAngles)) * ((points[i]/100)*(height/2-margin)), pointDiameter, pointDiameter); // angle vertices
 }
}

Re: Help with bezier polygons
Reply #1 - Jun 8th, 2010, 2:47pm
 
your control points are either side of the initial vertex, so the bezier folds back on itself.

change the colour of the control points so you can see what's what (one green, one red, say) and put an if (i == 0) {} around them so you only see one pair.

you want to use the initial vertex, the control point related to this then the control point this side of the NEXT vertex and then the next vertex.
Re: Help with bezier polygons
Reply #2 - Jun 8th, 2010, 2:55pm
 
thanks @koogy… I see that now. I'm going to work on getting the control points attached to the right vertices, and I like your idea for coloring the control points.

Cheers, Nicholas.
Re: Help with bezier polygons
Reply #3 - Jun 8th, 2010, 2:56pm
 
yes, thats the problem. as koogy suggested. color them.
just put

colorMode(HSB,360);
stroke(360/polyPoints*i,255,255);

before you call the ellipses and you can see that they are actually not paired the way you need them. you can disable the wrong one by writing
   bezierVertex(CX1, CY1, xVertex, yVertex, xVertex, yVertex);  you get closer to what you want i guess.
Re: Help with bezier polygons
Reply #4 - Jun 8th, 2010, 3:23pm
 
That was really helpful… I'm in the final stretch - working on the last tricky bezier connection between the last point and the first one.

Thanks!
Re: Help with bezier polygons
Reply #5 - Jun 8th, 2010, 3:32pm
 
edit: got it... maybe not the best way to write it. but works.

Code:


int pointDiameter = 6;
int margin = 20;
float[] points = {
50,50,50,50,50,50};
int polyPoints = 6;
float polyAngles = 360/polyPoints;
float xVertex;
float yVertex;
float xVertex2;
float yVertex2;
float CX1;
float CY1;
float CX2;
float CY2;
float tension;

void setup(){
size(1000,1000);
noFill();
stroke(255);
smooth();
}

void draw(){
background(0);
smooth();
beginShape();
drawCurve(points);
endShape();
drawPoints(points);
tension = mouseX/5;
}


void drawCurve(float[] points){

vertex(width/2 + cos(radians(0)) * ((points[0]/100)*(width/2-margin)), height/2 + sin(radians(0)) * ((points[0]/100)*(height/2-margin))); // origin vertex
for (int i = 1; i<polyPoints ; i++){
xVertex = width/2 + cos(radians(i * polyAngles)) * ((points[i]/100)*(width/2-margin));
yVertex = height/2 + sin(radians(i * polyAngles)) * ((points[i]/100)*(height/2-margin));

xVertex2 = width/2 + cos(radians((i-1) * polyAngles)) * ((points[i-1]/100)*(width/2-margin));
yVertex2 = height/2 + sin(radians((i-1) * polyAngles)) * ((points[i-1]/100)*(height/2-margin));

CX2 = xVertex + cos(radians(i * polyAngles -90)) * tension;
CY2 = yVertex + sin(radians(i * polyAngles -90)) * tension;
CX1 = xVertex2 + cos(radians((i-1) * polyAngles +90)) * tension;
CY1 = yVertex2 + sin(radians((i-1) * polyAngles +90)) * tension;
bezierVertex( CX1, CY1,CX2, CY2, xVertex, yVertex); // angle vertices

colorMode(HSB,360);
stroke(360/polyPoints*i,255,255);
ellipse(CX1, CY1, pointDiameter, pointDiameter);
ellipse(CX2 , CY2 , pointDiameter, pointDiameter);

println((xVertex-CX1) + ", " + (yVertex-CY1) + ", " + (xVertex-CX2) + ", " + (yVertex-CY2) + ", " + xVertex + ", " + yVertex);
}
stroke(255);

xVertex = width/2 + cos(radians(0 * polyAngles)) * ((points[0]/100)*(width/2-margin));
yVertex = height/2 + sin(radians(0 * polyAngles)) * ((points[0]/100)*(height/2-margin));
xVertex2 = width/2 + cos(radians(((polyPoints-1)) * polyAngles)) * ((points[(polyPoints-1)]/100)*(width/2-margin));
yVertex2 = height/2 + sin(radians(((polyPoints-1)) * polyAngles)) * ((points[(polyPoints-1)]/100)*(height/2-margin));
CX2 = xVertex + cos(radians(0 * polyAngles -90)) * tension;
CY2 = yVertex + sin(radians(0 * polyAngles -90)) * tension;
CX1 = xVertex2 + cos(radians(((polyPoints-1)) * polyAngles +90)) * tension;
CY1 = yVertex2 + sin(radians(((polyPoints-1)) * polyAngles +90)) * tension;
bezierVertex( CX1, CY1,CX2, CY2, xVertex, yVertex); // angle vertices

}


void drawPoints(float[] points){
ellipse(width/2, height/2, pointDiameter, pointDiameter); //center point
for (int i = 0; i<polyPoints; i++){
ellipse(width/2 + cos(radians(i * polyAngles)) * ((points[i]/100)*(width/2-margin)), height/2 + sin(radians(i * polyAngles)) * ((points[i]/100)*(height/2-margin)), pointDiameter, pointDiameter); // angle vertices
}
}
Re: Help with bezier polygons
Reply #6 - Jun 9th, 2010, 6:17am
 
I love this… thanks Cedric
Re: Help with bezier polygons
Reply #7 - Jun 9th, 2010, 7:23am
 
youre welcome. I am a big fan of your work, so I'm glad I could help.
Re: Help with bezier polygons
Reply #8 - Jun 9th, 2010, 8:27am
 
Thanks so much Cedric!

I successfully took your fixes and ported them into a class… now to insert a little data!


[code]



// GLOBAL VARIABLES
int margin = 20;
int pointDiameter = 5; //marker point diameter

// POLYGON 1
float[] points1 = {
 50,50,50,50,50};
float tension1;
Polygon myPolygon1 = new Polygon(points1, color(0,360,360)); // first polygon with array as constructor argument

// POLYGON 2
float[] points2 = {
 70,70,70};
float tension2;
Polygon myPolygon2 = new Polygon(points2, color(360,0,360)); // first polygon with array as constructor argument

// POLYGON 3
float[] points3 = {
 25,25,25,25,25,25,25,25};
float tension3;
Polygon myPolygon3 = new Polygon(points3, color(360,360,360)); // first polygon with array as constructor argument

// SETUP
void setup(){
 size(1000,1000);
 noFill();
 stroke(255);
 smooth();
 colorMode(HSB,360);
}

// DRAW
void draw(){
 background(0);
 tension1 = mouseX/5;
 myPolygon1.drawPoints();
 myPolygon1.drawCurve(tension1);
 tension2 = mouseX/2;
 myPolygon2.drawPoints();
 myPolygon2.drawCurve(tension2);
 tension3 = mouseX/10;
 myPolygon3.drawPoints();
 myPolygon3.drawCurve(tension3);
}

// POLYGON CLASS
class Polygon {

 //GLOBAL POLYGON VARIABLES
 float points[];
 float polyAngles;
 float xVertex;
 float yVertex;
 float xVertex2;
 float yVertex2;
 float CX1;
 float CY1;
 float CX2;
 float CY2;
 color c;


 //CONSTRUCTOR
 Polygon(float[] inputPoints, color tempC) {
   points = inputPoints;
   c = tempC;
 }

 void drawCurve(float tension){
   polyAngles = 360 / points.length;
   xVertex = width/2 + cos(radians(0)) * ((points[0]/100)*(width/2-margin));
   yVertex = height/2 + sin(radians(0)) * ((points[0]/100)*(height/2-margin));

   beginShape();
   stroke(c);
   vertex(xVertex, yVertex); // origin vertex
   for (int i = 1; i<points.length; i++){
     xVertex = width/2 + cos(radians(i * polyAngles)) * ((points[i]/100)*(width/2-margin));
     yVertex = height/2 + sin(radians(i * polyAngles)) * ((points[i]/100)*(height/2-margin));
     xVertex2 = width/2 + cos(radians((i-1) * polyAngles)) * ((points[i-1]/100)*(width/2-margin));
     yVertex2 = height/2 + sin(radians((i-1) * polyAngles)) * ((points[i-1]/100)*(height/2-margin));
     CX2 = xVertex + cos(radians(i * polyAngles -90)) * tension;
     CY2 = yVertex + sin(radians(i * polyAngles -90)) * tension;
     CX1 = xVertex2 + cos(radians((i-1)  * polyAngles +90)) * tension;
     CY1 = yVertex2 + sin(radians((i-1)  * polyAngles +90)) * tension;
     bezierVertex( CX1, CY1, CX2, CY2,  xVertex, yVertex); // angle vertices
     ellipse(CX1, CY1, pointDiameter, pointDiameter);
     ellipse(CX2 , CY2 , pointDiameter, pointDiameter);
   }
   xVertex = width/2 + cos(radians(0 * polyAngles)) * ((points[0]/100)*(width/2-margin));
   yVertex = height/2 + sin(radians(0 * polyAngles)) * ((points[0]/100)*(height/2-margin));
   xVertex2 = width/2 + cos(radians(((points.length-1)) * polyAngles)) * ((points[(points.length-1)]/100)*(width/2-margin));
   yVertex2 = height/2 + sin(radians(((points.length-1)) * polyAngles)) * ((points[(points.length-1)]/100)*(height/2-margin));
   CX2 = xVertex + cos(radians(0 * polyAngles -90)) * tension;
   CY2 = yVertex + sin(radians(0 * polyAngles -90)) * tension;
   CX1 = xVertex2 + cos(radians(((points.length-1))  * polyAngles +90)) * tension;
   CY1 = yVertex2 + sin(radians(((points.length-1))  * polyAngles +90)) * tension;
   bezierVertex( CX1, CY1, CX2, CY2,  xVertex, yVertex); // origin vertex to close
   endShape();
   ellipse(CX1, CY1, pointDiameter, pointDiameter);
   ellipse(CX2 , CY2 , pointDiameter, pointDiameter);
 }


 //POINT DRAWING FUNCTION
 void drawPoints() {
   stroke(0,0,360);
   polyAngles = 360 / points.length;
   ellipse(width/2, height/2, pointDiameter, pointDiameter); //center point
   stroke(c);
   for (int i = 0; i<points.length; i++){
     xVertex = width/2 + cos(radians(i * polyAngles)) * ((points[i]/100)*(width/2-margin));
     yVertex = height/2 + sin(radians(i * polyAngles)) * ((points[i]/100)*(height/2-margin));
     ellipse(xVertex, yVertex, pointDiameter, pointDiameter); // angle vertices
   }
 }

}

[code]
Re: Help with bezier polygons
Reply #9 - Jun 9th, 2010, 8:42am
 
Looks good Smiley

i see you are storing your data in the points1,points2,points3 arrays.
Do you want to enter them by hand later or load them from a text file, or excel sheet for example?, maybe create one circle for every line of numbers in your text file...if you need some more help on this or anything else, feel free to come back.

Re: Help with bezier polygons
Reply #10 - Jun 9th, 2010, 9:01am
 
For now, the arrays are simple… just 8 points and 4 polygons for this project… but I've got the basics of importing and parsing text strings into arrays. If I need more help, I'll come knocking!

Cheers, nf
Re: Help with bezier polygons
Reply #11 - Jun 9th, 2010, 1:44pm
 
looks nice but (personal bugbear here) it's using 100% of cpu when it's not changing.

just add
noLoop();
to the bottom of draw() and a new mouseMoved() method:

void mouseMoved() {
 redraw();
}

it's as responsive as ever and uses 0 cpu when the mouse isn't moving.
Re: Help with bezier polygons
Reply #12 - Jun 10th, 2010, 1:49am
 
also, there are a lot of constant values that you calculate again and again. (width / 2 - margin), for instance. use a global variable.

look at removing the radians() calls too. 90 degrees = HALF_PI, 360 = TWO_PI

and you calculate all the points twice. you calculate for both i and i - 1 in a loop so when i = 2 you recalculate point 1 etc. i'd have two loops, one for the calculations and one for the drawing. cedric might be responsible for this last bit 8)
Re: Help with bezier polygons
Reply #13 - Jun 10th, 2010, 2:13am
 
hey Smiley but true. doing the calculation and drawing in two separated steps is much more efficient and you can save a lot lines of code. that happens when trying to fix a given code and not writing it from scratch. sorry  Roll Eyes
Page Index Toggle Pages: 1