Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 10 of 10

Thread: Smoothing the dges of a polygon

  1. #1
    Junior Member Regular Contributor
    Join Date
    Jun 2010
    Posts
    162

    Smoothing the dges of a polygon

    Click image for larger version. 

Name:	boundary.jpg 
Views:	138 
Size:	5.8 KB 
ID:	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.

  2. #2
    Junior Member Regular Contributor
    Join Date
    Jan 2011
    Location
    Paris, France
    Posts
    248
    @+
    Yannoo

  3. #3
    Junior Member Newbie
    Join Date
    May 2012
    Posts
    17
    Sounds like a Google question to me. Just divide the edges at their midpoints and connect them.

  4. #4
    Junior Member Regular Contributor
    Join Date
    Apr 2012
    Posts
    164
    Quote Originally Posted by sevenfold View Post
    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'?

  5. #5
    Junior Member Newbie
    Join Date
    May 2012
    Posts
    17
    Quote Originally Posted by Carmine View Post
    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.

  6. #6
    Junior Member Regular Contributor
    Join Date
    Apr 2012
    Posts
    164
    Quote Originally Posted by sevenfold View Post
    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 ...

    Click image for larger version. 

Name:	splitsegs.jpg 
Views:	75 
Size:	47.7 KB 
ID:	1037

  7. #7
    Junior Member Regular Contributor
    Join Date
    Jun 2010
    Posts
    162
    Thank you all for the suggestion.

  8. #8
    Junior Member Regular Contributor
    Join Date
    Jan 2011
    Location
    Paris, France
    Posts
    248
    With only one midpoints step, this give something like this :
    Code :
    #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]
    Code :
      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 )
    Code :
        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)
    Last edited by The Little Body; 05-30-2013 at 05:07 PM.
    @+
    Yannoo

  9. #9
    Junior Member Newbie
    Join Date
    May 2012
    Posts
    17
    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:


  10. #10
    Junior Member Regular Contributor
    Join Date
    Apr 2012
    Posts
    164
    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •