-1

Sutherland-Hodgeman 多边形裁剪的实现。这两个语句的声明顺序给出了正确的输出,反向没有。

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

颠倒声明时出现的确切错误是底部剪裁器产生一组空的顶点,因此剪裁后不显示多边形。

这个错误的原因是什么?

代码:

#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;
}
4

2 回答 2

1

    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 = p;
}

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

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

您可以增加numberOfVertices,但pointList只有初始点的空间。声明它

Point pointList[MAXVERTICES] = { ... };

有足够的空间。

于 2012-09-24T21:57:29.360 回答
1

您有一个内存踩踏错误 - 您正在pointList使用无效索引写入数组,随后会立即覆盖内存。您的原始代码恰好可以工作,因为它之后的内存没有被使用,但是当您切换声明的顺序时,内存踩踏会覆盖变量numberOfVertices

我建议使用 Valgrind 运行您的程序,以查找发生内存踩踏的位置。

于 2012-09-24T21:47:27.313 回答