【问题标题】:ellipse midpoint algorithm counterclockwise version椭圆中点算法逆时针版本
【发布时间】:2015-04-25 09:55:01
【问题描述】:

我正在尝试转换从“使用 OpenGL 的计算机图形”一书中获取的标准顺时针椭圆中点算法,以便它从区域 2 开始逆时针工作。 我让它工作并绘制了一个椭圆,但它与原始算法绘制的椭圆不同,所以我认为我的代码中有一个我似乎无法找到的小错误,可以帮忙吗?

这是原始算法:

void ellipseMidpoint(int xCenter, int yCenter, int Rx, int Ry)
{
    int Rx2 = Rx * Rx;
    int Ry2 = Ry * Ry;
    int twoRx2 = 2 * Rx2;
    int twoRy2 = 2 * Ry2;
    int p;
    int x = 0;
    int y = Ry;
    int px = 0;
    int py = twoRx2 * y;
    void ellipsePlotPoints(int, int, int, int);

    /* Plot the initial point in each quadrant. */
    ellipsePlotPoints(xCenter, yCenter, x, y);

    /* Region 1 */
    p = round(Ry2 - (Rx2 * Ry) + (0.25 * Rx2));
    while (px < py) {
        x++;
        px += twoRy2;
        if (p < 0)
            p += Ry2 + px;
        else {
            y--;
            py -= twoRx2;
            p += Ry2 + px - py;
        }
        ellipsePlotPoints(xCenter, yCenter, x, y);
    }

    /* Region 2 */
    p = round(Ry2 * (x + 0.5) * (x + 0.5) + Rx2 * (y - 1) * (y - 1) - Rx2 * Ry2);
    while (y > 0) {
        y--;
        py -= twoRx2;
        if (p > 0)
            p += Rx2 - py;
        else {
            x++;
            px += twoRy2;
            p += Rx2 - py + px;
        }
        ellipsePlotPoints(xCenter, yCenter, x, y);
    }
}

void ellipsePlotPoints(int xCenter, int yCenter, int x, int y)
{
    setPixel(xCenter + x, yCenter + y);
    setPixel(xCenter - x, yCenter + y);
    setPixel(xCenter + x, yCenter - y);
    setPixel(xCenter - x, yCenter - y);
}

这是我的版本:

void ellipseMidpointCounterClockwise(int xCenter, int yCenter, int Rx, int Ry)
{
    int Rx2 = Rx * Rx;
    int Ry2 = Ry * Ry;
    int twoRx2 = 2 * Rx2;
    int twoRy2 = 2 * Ry2;
    int p;
    int x = Rx;
    int y = 0;
    int px = twoRy2 * x;
    int py = 0;
    void ellipsePlotPoints(int, int, int, int);

    /* Plot the initial point in each quadrant. */
    ellipsePlotPoints(xCenter, yCenter, x, y);

    /* Region 2 */
    p = round(Ry2 * (x - 0.5) * (x - 0.5) + Rx2 * (y + 1) * (y + 1) - Rx2 * Ry2);
    while (py < px) {
        y++;
        py += twoRx2;
        if (p > 0)
            p += Rx2 - py;
        else {
            x--;
            px -= twoRy2;
            p += Rx2 - py + px;
        }
        ellipsePlotPoints(xCenter, yCenter, x, y);
    }

    /* Region 1 */

    p = round(Ry2 * (x - 1.0) * (x - 1.0) + Rx2 * (y + 0.5) * (y + 0.5) - Rx2 * Ry2);
    while (x > 0) {
        x--;
        px -= twoRy2;
        if (p < 0)
            p += Ry2 + px;
        else {
            y++;
            py += twoRx2;
            p += Ry2 + px - py;
        }
        ellipsePlotPoints(xCenter, yCenter, x, y);
    }
}

如果能帮助我找出我做错了什么,我真的很感激。

【问题讨论】:

    标签: algorithm opengl graphics


    【解决方案1】:

    第一个问题是原始代码关于 x 和 y 不是对称的(而您的 ellipseMidpointCounterClockwise 实际上只是替换了 x 和 y)。

    ellipseMidpoint(0,0,3,2) 为第一象限生成

    0 2
    1 2
    2 1
    3 0
    

    而 ellipseMidpoint(0,0,2,3) 为第一象限生成

    0 3
    1 3
    2 2
    2 1
    2 0
    

    在交换坐标和颠倒我们得到的顺序时:

    0 2
    1 2
    2 2
    3 1
    3 0
    

    这意味着:

    002
    | 12
    +--0
    

    其中+ 表示中心,0 表示两个结果中的椭圆点,1 个点仅在第一个结果中,2 个点仅在第二个结果中(镜像)。

    如果您希望您的 ellipseMidpointCounterClockwise 生成完全相同的点,您可以 - 而不是替换 x 和 y - 只需进入负 x 方向(即 x-- 而不是原始代码中的 x++)。否则你必须忍受对称性的差异。

    第二个问题是你不仅替换了 x 和 y,还做了一些其他奇怪的替换。如果您只是在区域内替换 x 和 y,您会得到正确的结果:

    void ellipseMidpointCounterClockwise(int xCenter, int yCenter, int Rx, int Ry)
    {
      int Rx2 = Rx * Rx;
      int Ry2 = Ry * Ry;
      int twoRx2 = 2 * Rx2;
      int twoRy2 = 2 * Ry2;
      int p;
      int x = Rx;
      int y = 0;
      int px = twoRy2 * x;
      int py = 0;
      void ellipsePlotPoints(int, int, int, int);
    
      /* Plot the initial point in each quadrant. */
      ellipsePlotPoints(xCenter, yCenter, x, y);
    
      /* Region 2 */
      p = round(Rx2 - (Ry2 * Rx) + (0.25 * Ry2));
      while (py < px) {
        y++;
        py += twoRx2;
        if (p < 0)
          p += Rx2 + py;
        else {
          x--;
          px -= twoRy2;
          p += Rx2 + py - px;
        }
        ellipsePlotPoints(xCenter, yCenter, x, y);
      }
    
      /* Region 1 */
      p = round(Rx2 * (y + 0.5) * (y + 0.5) + Ry2 * (x - 1) * (x - 1) - Ry2 * Rx2);
      while (x > 0) {
        x--;
        px -= twoRy2;
        if (p > 0)
          p += Ry2 - px;
        else {
          y++;
          py += twoRx2;
          p += Ry2 - px + py;
        }
        ellipsePlotPoints(xCenter, yCenter, x, y);
      }
    }
    

    【讨论】:

    • 仅仅在负 x 方向上是不够的,因为要求是我从位置 (rx,0) 开始,这意味着我必须从第二个区域开始并以正 y 方向然后到达区域 1 并进入负 x。所以你是说我的算法是正确的,只是产生了不同的结果?
    • 我还没有检查你的算法 - 你现在可以自己做 :-) 如果你的算法是正确的,那么 ellipseMidpointCounterClockwise(0,0,Rx,Ry) 将产生与 ellipseMidpoint(0, 0,Ry,Rx) - 除了 x 和 y 交换。
    • 不,这该死的东西不一样,我不知道为什么
    • 只是严格地替换 x 和 y。你是来偷别人时间的吗?
    • 什么意思?我尝试了你在上一条评论中写的内容,如果它是相同的,那么它会产生相同的椭圆,只旋转 90 度,但它没有,我不确定我的算法有什么问题,我想你的答案可能是不正确,我不是想偷走任何人的时间,我只是在寻求帮助,我不会强迫任何人帮助我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多