Incorrect output on changing sequence of declarations

Posted by max on Stack Overflow See other posts from Stack Overflow or by max
Published on 2012-09-24T21:33:13Z Indexed on 2012/09/24 21:37 UTC
Read the original article Hit count: 198

Filed under:
|
|

Writing C++ code to implement Sutherland-Hodgeman polygon clipping. This order of declaration of these 2 statements gives correct output, reverse does not.

int numberOfVertices = 5;
Point pointList[] = { {50,50}, {200,300}, {310,110}, {130,90}, {70,40} };

I am passing the polygon vertex set to clippers in order - LEFT, RIGHT, TOP, BOTTOM.

The exact error which comes when the declarations are reversed is that the bottom clipper, produces an empty set of vertices so no polygon is displayed after clipping.

Correct: enter image description here

Incorrent: enter image description here

Confirmed by outputting the number of vertices produced after each pass:

Correct: enter image description here

Incorrect: enter image description here

What is the reason for this error?

Code:

#include <iostream>
#include <GL/glut.h>
#define MAXVERTICES 10
#define LEFT 0
#define RIGHT 1
#define TOP 2
#define BOTTOM 3
using namespace std;

/* Clipping window */
struct Window {
    double xmin;
    double xmax;
    double ymin;
    double ymax;
};

struct Point {
    double x;
    double y;
};

/* If I interchange these two lines, the code doesn't work. */
/**************/
int numberOfVertices = 5;
Point pointList[] = { {50,50}, {200,300}, {310,110}, {130,90}, {70,40} };
/**************/
const Window w = { 100, 400, 60, 200 };

/* Checks whether a point is inside or outside a window side */
int isInside(Point p, int side) {
    switch(side) {
        case LEFT:
            return p.x >= w.xmin;
        case RIGHT:
            return p.x <= w.xmax;
        case TOP:
            return p.y <= w.ymax;
        case BOTTOM:
            return p.y >= w.ymin;
    }
}

/* Calculates intersection of a segment and a window side */
Point intersection(Point p1, Point p2, int side) {
    Point temp;
    double slope, intercept;
    bool infinite;

    /* Find slope and intercept of segment, taking care of inf slope */
    if(p2.x - p1.x != 0) {
       slope = (p2.y - p1.y) / (p2.x - p1.x);
       infinite = false;
    } else {
        infinite = true;
    }

    intercept = p1.y - p1.x * slope;

    /* Calculate intersections */
    switch(side) {
        case LEFT:
            temp.x = w.xmin;
            temp.y = temp.x * slope + intercept;
            break;
        case RIGHT:
            temp.x = w.xmax;
            temp.y = temp.x * slope + intercept;
            break;
        case TOP:
            temp.y = w.ymax;
            temp.x = infinite ? p1.x : (temp.y - intercept) / slope;
            break;
        case BOTTOM:
            temp.y = w.ymin;
            temp.x = infinite ? p1.x : (temp.y - intercept) / slope;
            break;
    }

    return temp;
}

/* Clips polygon against a side, updating the point list
(called once for each side) */
void clipAgainstSide(int sideToClip) {
    int i, j=0;
    Point s,p;
    Point outputList[MAXVERTICES];

    /* Main algorithm */
    s = pointList[numberOfVertices-1];
    for(i=0 ; i<numberOfVertices ; i++) {
        p = pointList[i];

        if(isInside(p, sideToClip)) {
            /* p inside */
            if(!isInside(s, sideToClip)) {
                /* p inside, s outside */
                outputList[j] = intersection(p, s, sideToClip);
                j++;
            }
            outputList[j] = p;
            j++;
        }
        else if(isInside(s, sideToClip)) {
            /* s inside, p outside */
            outputList[j] = intersection(s, p, sideToClip);
            j++;
        }

        s = p;
    }

    /* Updating number of points and point list */
    numberOfVertices = j;

    /* ERROR: In last call with BOTTOM argument, numberOfVertices becomes 0 */
/* all earlier 3 calls have correct output */
    cout<<numberOfVertices<<endl;

    for(i=0 ; i<numberOfVertices ; i++) {
        pointList[i] = outputList[i];
    }
}

void SutherlandHodgemanPolygonClip() {    
    clipAgainstSide(LEFT);
    clipAgainstSide(RIGHT);
    clipAgainstSide(TOP);
    clipAgainstSide(BOTTOM);
}

void init() {
    glClearColor(1,1,1,0);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0,1000,0,500);
}

void display() {
    glClear(GL_COLOR_BUFFER_BIT);

    /* Displaying ORIGINAL box and polygon */
    glColor3f(0,0,1);
    glBegin(GL_LINE_LOOP);
        glVertex2i(w.xmin, w.ymin);
        glVertex2i(w.xmin, w.ymax);
        glVertex2i(w.xmax, w.ymax);
        glVertex2i(w.xmax, w.ymin);
    glEnd();

    glColor3f(1,0,0);
    glBegin(GL_LINE_LOOP);
        for(int i=0 ; i<numberOfVertices ; i++) {
            glVertex2i(pointList[i].x, pointList[i].y);
        }
    glEnd();

    /* Clipping */
    SutherlandHodgemanPolygonClip();

    /* Displaying CLIPPED box and polygon, 500px right */
    glColor3f(0,0,1);
    glBegin(GL_LINE_LOOP);
        glVertex2i(w.xmin+500, w.ymin);
        glVertex2i(w.xmin+500, w.ymax);
        glVertex2i(w.xmax+500, w.ymax);
        glVertex2i(w.xmax+500, w.ymin);
    glEnd();

    glColor3f(1,0,0);
    glBegin(GL_LINE_LOOP);
        for(int i=0 ; i<numberOfVertices ; i++) {
            glVertex2i(pointList[i].x+500, pointList[i].y);
        }
    glEnd();

    glFlush();
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(1000,500);
    glutCreateWindow("Sutherland-Hodgeman polygon clipping");

    init();
    glutDisplayFunc(display);
    glutMainLoop();

    return 0;
}

© Stack Overflow or respective owner

Related posts about c++

Related posts about opengl