栅格化和填充超球面的算法?

时间:2012-01-28 14:47:21

标签: geometry bresenham rasterize pixelate

我正在尝试光栅化和填充超球面。本质上,我有一个固定大小的d维网格和一个球体(中心,半径),想要找出网格的哪些单元格与球体重叠并存储它们的坐标。

我知道Midpoint circle algorithm利用8向镜像并生成圆的外部单元格(边框)。我还修改了链接的维基百科代码以填充圆圈(即,生成边框内所有单元格的坐标)。

但是我不知道任何更高维度的算法。例如在4d中,我一直在考虑通过生成所有可能的圆来实现,如下面的伪代码。基本思想是因为4d球是(x-x0) 2 +(y-y0)** 2 +(z-z0)** 2 +(k-k0)** 2 = r 2,这等于(x-x0) 2 +(y-y0)** 2 = r 2 - (z-z0)** 2 - (k-k0)** 2。由于我知道如何绘制圆,我只需要为z和k的所有可能值生成所有圆。

assume center=(x0,y0,z0,k0) and radius r

for all dimensions equal or higher than 2://this is z and k
  //make a list of possible values this dimension can take
  //from z0 to z0+radius with a step of 1
  all_lists.append([dim0,dim0+1,...,dim0+radius])

produce the product of all the lists in all_lists
//now i have a list [[z0,k0],[z0,k0+1],....,[z0+1,k0],[z0+1,k0+1],....,[z0+radius,k0],...[z0+radius,k0+radius]]

for every element l of the list, compute the radius of the circular "cut"
  l.append(r**2 - z**2 - k**2)

Now call the Midpoint Circle Algorithm, but for every (x,y) pair that it produces, we need to export 4 points, namely (x,y,±z,±k)

question似乎相关,但我不明白答案。

1 个答案:

答案 0 :(得分:1)

没有人回答一段时间,所以这里有简单而明显的C ++解决方案:

//---------------------------------------------------------------------------
const int N=10;                     // number of dimensions
struct point { double a[N]; };      // N-dimensional point
#define color DWORD                 // type of your color property
//---------------------------------------------------------------------------
// N x nested for(a=a0;a<=a1;a+=da) return false if ended
// it could be optimized a lot but for clarity I leve it as is
// ix=-1 at start and N = number of dimensions / nested count
bool nested_for(double *a0,double *a,double *a1,double *da,int &ix,int N)
    {
    if (ix<0)
        {
        int i;
        if (N<1) return false;                          // N too low
        for (i=0;i<N;i++) a[i]=a0[i];
        for (i=0;i<N;i++) if (a[i]>a1[i]) return false; // a0>a1 for some i that is wrong !!!
        ix=N-1;
        return true;
        }
    for (;;)                                            // a+=da
        {
        a[ix]+=da[ix];
        if (a[ix]<=a1[ix]) break;
        if (!ix) return false;                          // end of nested for
        a[ix]=a0[ix];
        ix--;
        }
    ix=N-1;

    return true;
    }
//---------------------------------------------------------------------------
void draw_point(point &p,color c)
    {
    // draw your point ...
    }
//---------------------------------------------------------------------------
void fill_hypersphere(point &p0,double r,color c)
    {
    int i,ix;
    bool init;
    point a,b,a0,a1,da;
    double aa,rr=r*r;
    for (i=0;i<N;i++) a0.a[i]=-r;           // loop boundary for all axises <-r,+r>
    for (i=0;i<N;i++) a1.a[i]=+r;
    for (i=0;i<N;i++) da.a[i]=1.0;          // step between pixels
    for (ix=-1;nested_for(a0.a,a.a,a1.a,da.a,ix,N);) // N x nested for
        {
        aa=0.0;                             // aa = distance from zero ^ 2
        for (i=0;i<N;i++) aa+=a.a[i]*a.a[i];
        if (aa<=rr)                         // if it is inside sphere
            {                               // compute the translated point by p0 to b
            for (i=0;i<N;i++) b.a[i]=p0.a[i]+a.a[i];
            draw_point(b,c);                // and draw/fill it or whatever
            }
        }
    }
//---------------------------------------------------------------------------

[Edit1]完成了一些测试

Hypersphere fill

  • 这是上面代码的测试应用输出
  • 查看XY平面(z = 0)
  • 用于1D,2D,3D和4D超球面
  • 我不确定1D但是其余的都没问题(不确定是否为1D定义了超空间或者应该只是一个点)
  • 即使是像素数〜体积看起来非常相似所以它应该没问题
  • 要知道复杂性是O(N!),其中N是维数
  • 和runtime = c0 *(N!)* r其中c0是常数时间,r是半径,N是维数