【问题标题】:Debugging Polygon Approximation Algorithm Code C++ [closed]调试多边形逼近算法代码 C++ [关闭]
【发布时间】:2012-11-26 08:11:56
【问题描述】:

我想知道您是否可以帮助我调试我的一些代码。我已经为一个我们正在实现多边形逼近算法的类项目编写了以下代码。但我似乎无法让代码做我想做的事情。这是该算法的维基文章的链接:http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm

我遇到的问题是第二个数组 closedStack 要么没有正确更新内部的值,要么没有正确显示。但是第一个数组,即从文件中读取的数组正确显示。我还不断收到已满的 closedStack 错误,因此我将 if 语句更改为不使用 fileSize 变量,因此它也可能存在问题。如果您需要我解释任何逻辑或变量等,请询问,我会解释。

#include "math.h"
#include <iostream>
#include <fstream>
#include "glut.h"

using namespace std;

struct point{
    int x, y;
};

void display(void);
void fileRead();
void oPush(point);
void cPush(point);
point oPop();
int deviation();

point pixel[2000];
int fileSize = 0;
int errorAllowed= 5;
int errorDeviation=0;
int oTop = 0;
int cTop = 0;
point first;
point last;
point openStack[5000];
point closedStack[5000];
int V1 = 0;
int V2 = 0;

void main(int argc, char **argv){

    fileRead();

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(500,500);
    glutInitWindowPosition(75,75);
    glutCreateWindow("Ramer's Iterative Algorithm");
    glutDisplayFunc(display);
    gluOrtho2D(0,500,0,500);

    fileSize = fileSize/2;

    int tmp1 = pixel[0].x+pixel[0].y;
    int tmp2 = 0;


    for(int i = 0; i<2000; i++){
        tmp2 = pixel[i].x+pixel[i].y;

        if(tmp2 < tmp1){
            tmp1 = tmp2;
            V1 = i;
        }
    }

    for(int i = 0; i<2000; i++){
        tmp2 = pixel[i].x+pixel[i].y;

        if(tmp2 > tmp1){
            tmp1 = tmp2;
            V2 = i;
        }
    }

    oPush(pixel[V1]);
    oPush(pixel[V2]);
    oPush(pixel[V1]);

    do{
        first = oPop();
        last = oPop();

        int Mid = deviation();

        if(errorDeviation>errorAllowed){
            oPush(last);
            oPush(pixel[Mid]);
            oPush(first);
        }

        else if(errorDeviation<=errorAllowed){
            oPush(last);
            cPush(first);
        }

    }while(oTop>=2);

    glutMainLoop();

    cin >> V1;

}

void display(void){
    glClearColor(0,0,0,0);
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1,1,1);

    glBegin(GL_POINTS);
    for(int i=0; i<2000; i++)
        glVertex2i(pixel[i].x,pixel[i].y);
    glEnd();

    glColor3f(1,0,0);
    glBegin(GL_LINE_STRIP);
    for(int i=0;i<=cTop; i++)
        glVertex2i(closedStack[i].x,closedStack[i].y);
    glEnd();

    glFlush();
}

void fileRead(){
    char fileName[20];

    cout << "Enter the name of the file you would like to parse data from: ";
    cin >> fileName;

    ifstream boundary;
    boundary.open(fileName);
    if(boundary.fail()){
        cout << "Could not open '" << fileName << "' for reading.\n";
        exit(0);
    }

    for(int i=0; !boundary.eof(); i++){
        boundary >> pixel[i].x;
        boundary >> pixel[i].y;
        fileSize ++;
    }

}

void oPush(point p){
    if(oTop>fileSize){
        cout << "Full Stack--Open\n";
        exit(0);
    }

    else{
        oTop++;
        openStack[oTop]= p;
    }
}

void cPush(point p){
    if(cTop>10000){
        cout << "Full Stack--Closed\n";
        exit(0);
    }

    else{
        cTop++;
        closedStack[cTop]= p;
    }
}

point oPop(){
    point temp;

    if(oTop<=0){
        cout << "Stack Empty\n";
        exit(0);
    }

    else{
        temp = pixel[oTop];
        oTop--;
    }
    return temp;
}

int deviation(){
    float y = last.y-first.y;
    float x = last.x-first.x;
    float theta = atan(y/x);
    int most = 0;

    for(int i = V1+1; i < V2; i++){
        float ped = (-(pixel[i].x-first.x)*sin(theta))+((pixel[i].y-last.y)*cos(theta));
        float errDev= abs(ped);

        if(errDev>most)
            most = i;
        errorDeviation = (int)errDev;
    }

    return most;
}

为了详细说明 V1 和 V2,它们应该是数组的左下角和右上角。检查循环我已简化为:

for(int i = 0; i<fileSize; i++){
tmp2 = (pixel[i].x)+(pixel[i].y);

if(tmp2 <= tmp1){
    tmp1 = tmp2;
    V1 = i;
}

if(tmp2 >= tmp1){
    tmp1 = tmp2;
    V2 = i;
}

循环将点的 x+y 加在一起,然后将其与前一个点进行检查以更新它。 x+y 最低的点最终应该是 V1,最高的点应该是 V2。但我认为循环运行不正常。通过放大绘制的内容,显示循环的第二部分只有三个点。它看起来像初始数组的第一个和第二个点以及 0,0 被绘制。不知道为什么会这样。

【问题讨论】:

  • V1和V2的意义是什么?为什么你的起始堆栈是 [V1, V2, V1]? deviation() 是用来应对 V2
  • 所以 V1 和 V2 是 Mid 检查偏差的线段的开始和结束像素的索引号。堆栈是这样开始的,因为这些是近似值的最初三个点。然后,该算法将更多内容添加到封闭堆栈,然后成为要绘制的新点集。我还没有实现递归版本,没有。但我真的没有时间。这个项目对我来说太早了。只是想获取我已经使用的代码,以便我可以上交部分功劳。
  • 坦率地说,这段代码有很多问题。给我们一个你能想到的最简单的例子来显示错误(输入数据和你期望closedStack 是什么),也许我们可以提供帮助。
  • 你的意思是给出一个点的例子,以及结果堆栈应该在它们上使用算法吗?我可以尝试这样做。不过数学有点复杂。并且不确定我是否能够真正提供文本 cmets 的帮助。

标签: c++ algorithm debugging opengl polygon


【解决方案1】:

就目前而言,您的问题实在是太宽泛了。您需要尝试自己缩小范围。这是一个很好的清单:http://msmvps.com/blogs/jon_skeet/archive/2012/11/24/stack-overflow-question-checklist.aspx

您不会通过尝试一次性编写完整的工作程序来解决您的问题。视觉输出是无价的,但它不能代替实际点列表的文本输出。您的问题和 cmets 建议您仅通过查看最终的视觉输出来尝试调试它。您需要将其分解为更小的部分,并查看每个步骤之间的数据,以便了解您的程序与您的预期不同的地方。

正如您所说的“第二个数组, closedStack 要么没有正确更新内部的值,要么没有正确显示”。解决这个问题的第一步是找出这些情况中的哪一个!数组是否有错误的值,或者显示不正确?您可以通过打印中间值并将它们与手动解决问题时的期望值进行比较来发现这一点。如果输入太大,请创建一组较小的输入点,您可以手动处理。缩小范围后,您会发现您可以自己解决问题,或者您有一个更集中的问题要问,这样可以得到更好的答案。


粗略检查,我猜:

  1. 您似乎误解了输入。你没有描述它是什么。如果它是形成piece-wise linear curve 的点序列,那么不清楚为什么选择最西南和最东北的元素会有所帮助(假设东是+ve x 和北+ve y)。如果是点云,那么您需要做的不仅仅是挑选角点,以使其余部分按有意义的顺序排列。
  2. 您的函数deviation() 似乎假设索引first 小于索引last。但似乎没有什么可以保证这一点。首先,也许 V1 比 V2 具有更大的索引。即使没有,您也可以使用 [V1, V2, V1] 填充初始堆栈,以保证 deviation() 将看到 first > last 的输入。虽然我当然不能保证 deviation() 没有问题,但我猜你输入的内容有问题。

【讨论】:

  • 感谢您的建议。我一直在这里和那里尝试找出变量,这很有帮助。我会再做一些工作,一旦我有了更具体的内容,可能会再次发布。
  • 程序的输入是一组像素,其坐标存储在文本文件中。像素构成具有闭合边界的弯曲形状。我可以通过任何形状,但为了测试,我只是使用一个简单的圆圈。选择 SW 和 NE 点的原因是为了将点数大致减半。我可以沿边界做任何两个点,但我想不出一个简单的循环来找出沿边界的其他点。我不能只选择第一个和中间点,因为这是一个作业,所以老师让我们做西南和东北或西北和东南。
  • 我明白你现在关于偏差函数的意思了。我要做的是测试这两个索引之间数组的每个点与端点 V1 和 V2 的线的偏差。您能否建议一种更简单的方法来循环遍历 V1 和 V2 之间的索引,并且不会受到一个大于另一个的影响?
  • 嗯,我看错了。您真的是要每次循环遍历 V1 和 V2 之间的所有点吗?当然,您只是想循环通过first 和last 之间的点吗?目前尚不清楚当它们以相反的顺序排列时您要做什么...您的意思是继续沿同一方向绕圆的周边前进吗?在这种情况下,您可能会阅读 en.wikipedia.org/wiki/Modulo_operation">modulus/…> 运算符“%”,并为您的循环考虑更合适的结束条件,也许是“i != last”而不是“i
  • 是的,我就是这个意思。偏差函数应该只从头到尾扫描索引。但是 first 和 last 是点变量,它们没有与之关联的索引号。我将如何使用指针来访问该数据?因为 first 和 last 也不是初始数组的一部分。它们只是 openStack 的前两个。所以我需要以某种方式跟踪初始数组中的第一个和最后一个。
猜你喜欢
  • 1970-01-01
  • 2014-05-06
  • 2011-11-15
  • 2021-10-19
  • 1970-01-01
  • 2020-04-04
  • 2015-05-31
  • 2017-07-24
  • 2018-06-30
相关资源
最近更新 更多