Bresenham 3d Ellipsoid问题

时间:2012-04-04 17:08:49

标签: java algorithm math

我正在用体素制作一个椭圆体,我有一个实现,但它没有正常工作,在过去的几个小时里,我一直在尝试没有成功的事情。

以下是它的工作原理:

  • 使用Bresenham圆算法
  • 沿Z轴绘制2D椭圆
  • 它计算前进的圆圈和一个左右的坐标
  • 它使用这些坐标作为X和Y的半径

这是有效的:

  • 球体是完美的
  • Ellipsoids是完美的
    • z> x和z> ÿ
    • x == y

这不是:

我猜它是因为我每次都从中心到前面画切片,但我不知道。下面是我的实现,这是一团糟。我很快就清理了一下,所以在某种程度上这是可以理解的。此外,我正在为以后保存优化,我只是想让它现在正常工作。

我不会展示我对圆形算法本身的实现,因为我知道它的工作原理并且只会让这个问题变得更长。所以我将为它解释两个函数。

private List<Integer> getSlice(int rx, int ry)从Bresenham圆算法的运行中获得原始结果,不需要对称性。它将结果作为x,y结果的列表返回。

public void generateEllipse(int z, int cx, int cy, int cz, int rx, int ry)生成一个带有给定信息的椭圆,并使用对称性绘制坐标,这些将在屏幕上呈现。

ArrayList<Integer> s = getSlice(rz, rx);
ArrayList<Integer> s2 = getSlice(rz, ry);

int cap = Math.max(s2.size(), s.size());

while (s.size() > 1)
{
    int x = 0;
    int z = 0;
    int z2 = 0;
    int y2 = 0;

    int i = cap - 2;

    if (s.size() > i)
    {
        z = s.get(i);
        x = s.get(i + 1);

        s.remove(i + 1);
        s.remove(i);
    }

    if (s2.size() > i)
    {
        z2 = s2.get(i);
        y2 = s2.get(i + 1);

        s2.remove(i + 1);
        s2.remove(i);
    }

    if (x != 0 && y2 != 0)
        generateEllipse(z, cx, cy, cz, x, y2);

    cap = Math.max(s2.size(), s.size());

我在一两个星期后回答了一个类似的问题(是的,我一直遇到问题:()并得到答案,我实施了它并且有效,但我不满意,我想避免浮点数全部在一起。请参阅3D Ellipsoid out of discrete units

由于这个问题,我在修补数字和获得不均匀的切片时遇到了问题,所以球体是不可能的。具有讽刺意味的是,现在球体是唯一可能的(除了前后椭圆)。

编辑:

我得到x&gt; y通过添加

工作
else if (y2 < x && ry - y2 != 0)
    generateEllipse(z, cx, cy, cz, x, ry - y2);

|| r - y2 == 0到底部的第一个测试。

我不太确定为什么会这样,我现在正在考虑这个问题。但我仍然遇到y&gt;的问题。 X。任何人吗?

EDIT2:

现在我看着它,它与y = x椭圆体不同,回到绘图板。

EDIT3:

昨晚我在想这个,我想我已经弄明白了,这不是我自己问题的答案,但我想指出我看到的错误。我正在测试第一个列表,并从最大列表的大小开始逐渐绘制坐标。

这是不好的,因为两个列表不能保证相同的长度,这是我试图赶紧算法的失败。

在图片中,你看不到,但是小椭圆实际上距离大椭圆几个街区。这是由未绘制的省略号引起的,这是由没有数据的列表引起的。导致实际的小椭圆大椭圆是因为算法绘制了两个八分圆,两个八分圆都存储在getSlice(...)的列表中。

那么我该如何解决这个问题呢?我还没有实现任何东西,可能暂时不会(它很早)但这就是我大脑的动作。同样,这不是问题的答案,只是想法。

我迭代while(!s.isEmpty())并在循环外定义两个新值:incX = s.sizeincY = s1.size我测试他们的z值是否匹配,如果没有,那么我更正它。我想我会得到值,测试最大的列表,如果它们不匹配,那么将最小列表的inc值减2,得到旧值。

我测试!s.isEmpty()因为两个列表同时是空的。同样绘制省略号,我将使用任何一个z值,因为它们两者应该相等。

如果这是错的,那么我想我已经找到了这个文件:http://www.cs.sunysb.edu/vislab/wordpress/pdf/398.pdf

1 个答案:

答案 0 :(得分:2)

感谢所有观看此内容的人(即使我没有得到任何回复:(),我正在设置此答案,因为问题已解决,代码如下:

    ArrayList<Integer> s = getSlice(rz, rx);
    ArrayList<Integer> s2 = getSlice(rz, ry);

    boolean yMax = Math.max(s2.size(), s.size()) == s2.size();

    int decX = s.size() - 1;
    int decY = s2.size() - 1;

    boolean done = false;

    while (!done)
    {

        int x = 0;
        int z = 0;
        int z2 = 0;
        int y = 0;

        y = s2.get(decY--);
        z2 = s2.get(decY--);

        x = s.get(decX--);
        z = s.get(decX--);

        if (z != z2)
        {
            if (yMax)
            {
                decX += 2;
                x = s.get(decX);

                s2.remove(decY + 2);
                s2.remove(decY + 1);    
            }
            else
            {
                decY += 2;
                y = s2.get(decY);

                s.remove(decX + 2);
                s.remove(decX + 1); 
            }

            z = z < z2 ? z : z2;
        }
        else
        {
            s.remove(decX + 2);
            s.remove(decX + 1);             

            s2.remove(decY + 2);
            s2.remove(decY + 1);    
        }

        if (y != 0 && x != 0)
            generateEllipse(z, cx, cy, cz, x, y);

        done = yMax ? s2.isEmpty() : s.isEmpty();
    }

现在需要做的就是优化。我仍然会阅读那篇论文,它涵盖了对我的程序有趣且有用的其他主题:)。

问题在于我没有考虑每个列表的不同大小,如果曲线比另一个曲线更陡,它将具有更多坐标。当rx == ry时,Z将始终相同。这使我能够绘制球体和前后椭圆体。

当它们不相同时,z会发生变化,因为曲线会更快/更慢。当我在测试第一个列表时发生这种情况时,它会忽略这些,因为迭代会在它到达之前停止。

大椭圆,小椭圆是由于它们被向后拉动而引起的,因此首先绘制外部八分圆,其总值较少。

在不久的将来,我会提出更详细的答案和更优雅的实施方案。我只是提出这个答案,让任何一个路人都知道问题已经解决了。我希望没有人能够经历过我试图弄清楚这一切的挫败感!令人惊讶的是,最棘手的问题是由最愚蠢的事情引起的。

相关问题