椭圆中点算法逆时针版本

3
我正在尝试将从书籍“使用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);
    }
}

我真的很感激能够帮我找到我做错了什么。
1个回答

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方向前进,然后到达第一个区域并向负x方向前进。所以你是说我的算法是正确的,只是产生了不同的结果? - Amit Ofer
我没有检查过你的算法 - 现在你可以自己检查了 :-) 如果你的算法是正确的,那么ellipseMidpointCounterClockwise(0,0,Rx,Ry)将会产生与ellipseMidpoint(0,0,Ry,Rx)相同的点 - 只是x和y被交换了。 - coproc
这玩意儿不一样,我也搞不清为什么。 - Amit Ofer
你是来浪费别人时间的吗? - coproc
你的意思是什么?我尝试了你在上一条评论中写的内容,如果是相同的话,它应该只会产生一个旋转了90度的椭圆,但它并没有,我不确定我的算法有什么问题,我认为也许你的答案是错误的,我不想浪费任何人的时间,我只是在寻求帮助,我并没有强迫任何人来帮助我。 - Amit Ofer
没事了,我看到你上面做的第二个修复解决了它,我认为这是因为我的窗口宽高比不同所以看起来不一样。 - Amit Ofer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接