PDA

View Full Version : Smoothing the dges of a polygon



jenny_wui
05-20-2013, 01:57 PM
1032

Hello every body, I have a polygon consisting of 26 points as shown in the figure. i would just like to smoothen the edges. Could you suggest me some simple way to do it? Thanks in advance.

The Little Body
05-23-2013, 05:37 PM
Something like this http://www.opengl.org/discussion_boards/showthread.php/131788-How-to-draw-a-bezier-curve-through-its-control-points ?

sevenfold
05-26-2013, 07:32 PM
Sounds like a Google question to me. Just divide the edges at their midpoints and connect them.

Carmine
05-27-2013, 04:53 PM
Sounds like a Google question to me. Just divide the edges at their midpoints and connect them. If that's all you do the polygon would look exactly like it does now.
You'd have to take those midpoints and 'push' them outward.
The question is 'How far outward do you push them'?

sevenfold
05-28-2013, 06:02 PM
If that's all you do the polygon would look exactly like it does now.
You'd have to take those midpoints and 'push' them outward.
The question is 'How far outward do you push them'?

You don't have to "push out" the edges. The process of subdivision makes them smoother. You're adding more points to the shape to make it smoother. Just keep on subdividing the edges by their midpoints until it looks smooth.

Carmine
05-29-2013, 12:03 PM
You don't have to "push out" the edges. The process of subdivision makes them smoother. You're adding more points to the shape to make it smoother. Just keep on subdividing the edges by their midpoints until it looks smooth. I didn't say 'push out the edges', I said push out the midpoints of each divided segment as below ...

1037

jenny_wui
05-30-2013, 09:55 AM
Thank you all for the suggestion.

The Little Body
05-30-2013, 01:14 PM
With only one midpoints step, this give something like this :


#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>

//================================================== ====
// GLOBAL VARIABLES
//================================================== ====

typedef struct
{
GLfloat x, y, z;
}position_t;

// modify the closed curve here
position_t vertices[] = {
{2.75,0.56,0},
{3.86, 1.56, 0},
{4.06, 2.79,0},
{3.69,3.51, 0},
{2.75, 4.11, 0},
{1.43, 4.15, 0},
{0.42, 3.38, 0},
{0.43, 1.79, 0},
{0.79, 1.00, 0},
{1.54, 0.47, 0}
};

position_t *middlePoints = NULL;
int numPoints = 0;


//================================================== ==================
// Allocate middlePoints array (with the same size as vertices)
//================================================== ==================
void AllocMiddlePoints()
{
middlePoints = (position_t *) malloc( sizeof(vertices));
numPoints = sizeof(vertices) / sizeof(position_t);
}

//================================================== ==================
// Draw controls points
//================================================== ==================
void DrawControlPoints(position_t *pos, int num, int pointSize, GLfloat red, GLfloat green, GLfloat blue)
{
int i;

glPointSize(pointSize);
glColor3f(red, green, blue);

glBegin(GL_POINTS);
for( i = 0; i < num; i++)
{
glVertex3fv( (GLfloat *) &pos[i] );
}
glEnd();

}

//================================================== ==================
// Draw multiples connected segments (with a loop)
//================================================== ==================
void DrawSegments(position_t *pos, int num, int lineSize, GLfloat red, GLfloat green, GLfloat blue)
{
int i;

glLineWidth(lineSize);
glColor3f(red, green, blue);

glBegin(GL_LINE_LOOP);
for( i = 0; i < num ; i++)
{
glVertex3fv((GLfloat *) &pos[i] );
}
glEnd();
}

//================================================== ==========================
// draw multiples connected segments from "interleaved' src and dst vertices
//================================================== ==========================
void DrawSegments2(position_t *src, position_t *dst, int num, int lineSize, GLfloat red, GLfloat green, GLfloat blue)
{
int i;

glLineWidth(lineSize);
glColor3f(red, green, blue);

glBegin(GL_LINE_LOOP);
for( i = 0; i < num ; i++)
{
glVertex3fv((GLfloat *) &src[i] );
glVertex3fv((GLfloat *) &dst[i] );
}
glEnd();
}

//================================================== ==================
// compute middles positions from initials segments
//================================================== ==================
void ComputeMiddlePositions(position_t *src, position_t *dst, int num)
{
int i;

for( i = 0 ; i < num; i++)
{
dst[i].x = src[i].x + (src[ (i+1) % num].x - src[i].x) / 2.0f;
dst[i].y = src[i].y + (src[ (i+1) % num].y - src[i].y) / 2.0f ;
dst[i].z = src[i].z + (src[ (i+1) % num].z - src[i].z) / 2.0f;
}
}

//================================================== ==================
// rescale middle positions for to give the "more smooth" impression
//================================================== ==================
void ScaleMiddlePositions(position_t *pos, int num, GLfloat scale)
{
int i;

float cx = 0, cy = 0, cz = 0;

for( i = 0 ; i < num; i++)
{
cx += pos[i].x;
cy += pos[i].y;
cz += pos[i].z;
}

cx /= num;
cy /= num;
cz /= num;


for( i = 0 ; i < num; i++)
{
pos[i].x = (pos[i].x - cx) * scale + cx;
pos[i].y = (pos[i].y - cy) * scale + cy;
pos[i].z = (pos[i].z - cz) * scale + cz;
}
}


//================================================== ====
// WINDOW RESHAPE ROUTINE
//================================================== ====
void displayReshape(int w, int h)
{
// If the display is re-sized in any way, the curve is redrawn
// so that it fits the display properly. Try it!

glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-4.0, 4.0, -3.0 * (GLfloat) h / (GLfloat) w,
5.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);
else
glOrtho(-4.0 * (GLfloat) w / (GLfloat) h,
4.0 * (GLfloat) w / (GLfloat) h, -3.0, 5.0, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
}

//================================================== ====
// DISPLAY CALL BACK ROUTINE
//================================================== ====
void displayCallBack()
{

int num = sizeof(vertices) / sizeof(position_t);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();
gluLookAt(1.0,1.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0);
glTranslatef(0.0, 1.0, 0.0);

DrawSegments(vertices, num, 1, 1,1,1);
DrawControlPoints(vertices, num, 3, 1,1,1);

ComputeMiddlePositions(vertices, middlePoints, num);
ScaleMiddlePositions(middlePoints, num, 1.1f);

DrawSegments2(vertices, middlePoints, num, 1, 1,0,0);
DrawControlPoints(middlePoints, num, 3, 1,0,0);


glutSwapBuffers();
}



//================================================== ====
// MAIN PROGRAM
//================================================== ====
int main(int argc, char** argv)
{
// Allow cmd line arguments to be passed to the glut
glutInit(&argc, argv);

// Create and name window
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // Need both double buffering and z buffer
glutInitWindowSize(500, 500);
glutCreateWindow("Smooth segments");

// Add Display CallBacks
glutReshapeFunc(displayReshape);
glutDisplayFunc(displayCallBack);

glClearColor(0.0,0.0,0.0,1.0);
glColor3f(0.0,0.0,0.0);

AllocMiddlePoints();

//Enter infinite loop calling 'displayCallBack'
glutMainLoop();

return 0;
}


You have only to modify values into the vertices[] array for to see another closed curve that mine

The centro´d (cx, cy, cz) is computed in the first part of the ScaleMiddlePositions()
[this is only the sum of all coordinates divided by the number of them]


float cx = 0, cy = 0, cz = 0;

for( i = 0 ; i < num; i++)
{
cx += pos[i].x;
cy += pos[i].y;
cy += pos[i].z;
}

cx /= num;
cy /= num;
cz /= num;


The pushing of midpoints is make at the second part of the same ScaleMiddlePositions()
[the "push out the midpoints of each divided segment" factor is the last parameter of this funtion, I have set it to 1.1 )


for( i = 0 ; i < num; i++)
{
pos[i].x = (pos[i].x - cx) * scale + cx;
pos[i].y = (pos[i].y - cy) * scale + cy;
pos[i].z = (pos[i].z - cz) * scale + cz;
}

(this translate the middlepoint to the centro´d origine, scale it for make the push, and retranslate it to his original origine)

sevenfold
05-31-2013, 05:59 PM
I was thinking you could have used some kind of corner cutting technique and discard the old point,
but you can just keep it and average the old point instead:

http://img515.imageshack.us/img515/6642/subdivide.png

Carmine
06-02-2013, 09:09 PM
Chaikin's Algorithm - interesting - looks easy to code.
Final product is totally inside the original.
Area of polygon decreases with each step.
OP has to decide if that's acceptable.