Smoothing the dges of a polygon

[ATTACH=CONFIG]424[/ATTACH]

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.

Something like this How to draw a bezier curve through its control points - OpenGL: Basic Coding - Khronos Forums ?

Sounds like a Google question to me. Just divide the edges at their midpoints and connect them.

[QUOTE=sevenfold;1251135]Sounds like a Google question to me. Just divide the edges at their midpoints and connect them.[/QUOTE] 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.

[QUOTE=sevenfold;1251189]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.[/QUOTE] I didn’t say ‘push out the edges’, I said push out the midpoints of each divided segment as below …

[ATTACH=CONFIG]1037[/ATTACH]

Thank you all for the suggestion.

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)

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:

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.