采样 x-y 平面中的螺旋线

Spiral in sampled x-y plane

假设我有以下 3D 离散化 space,其中 samples/nodes 的索引是连续的,如图所示。

现在只考虑水平中间层

我的 objective 是找到一个 以编程方式和迭代 rule/s 允许我 运行 一个 螺旋(像图像或类似的,它可以在中间层的任何方向)开始,从节点254开始,如图所示:

如图所示,黄色十字表示要探索的节点。在第一圈中,这些节点是连续的,而在第二圈中,它们被一个节点隔开,依此类推。

我开始解决问题如下(伪代码):

  1. 254 – z * y = 215
  2. 254 – z * (y + 1) = 212
  3. 254 – z = 251
  4. 254 + z * (y - 1) = 290
  5. 254 + z * y = 293
  6. 254 + z * (y + 1) = 296
  7. 254 + z = 257
  8. 254 – z * (y – 1) = 218
  1. 254 – 3 * z * y = 137
  2. 254 – 3 * z * (y + 2/3) = 131

但我认为可能有更简单、更通用的规则。

每个方向都有恒定的索引增量:

const int dx = 39;
const int dy =  3;
const int dz =  1;

所以要制作螺旋形,您只需从起始索引开始并沿当前方向递增 i-times 然后旋转 90 度并执行相同操作...然后递增 i 并执行此操作直到需要为止尺码命中 ...

你还应该添加范围检查,这样你的螺旋就不会超出你的数组范围,因为那样会把事情搞砸。通过检查实际 x,y,z 坐标。因此,要么并行计算它们,要么使用模块化算法从 ix 推断它们,例如 (C++):

const int dx = 39;
const int dy =  3;
const int dz =  1;

int cw[4]={-dx,-dy,+dx,+dy};    // CW rotation
int ix=254;                     // start point (center of spiral)
int dir=0;                      // direction cw[dir]
int n=5;                        // size
int i,j,k,x,y,z,a;                  // temp

for (k=0,i=1;i<=n;i+=k,k^=1,dir++,dir&=3)
 for (j=1;j<=i;j++)
   {
   int a=ix-1;
   z = a% 3; a/= 3; //  3 is z-resolution
   y = a%13; a/=13; // 13 is y-resolution
   x = a;
   if ((x>=0)&&(x<13)&&(y>=0)&&(y<13)&&(z>=0)&&(z<3))
      {
      // here use point ix
      // Form1->mm_log->Lines->Add(AnsiString().sprintf("%i (%i,%i,%i) %i",ix,x,y,z,i));
      }
   ix+=cw[dir];
   }

生成此输出

ix   x,y,z  i
254 (6,6,1) 1
215 (5,6,1) 1
212 (5,5,1) 2
251 (6,5,1) 2
290 (7,5,1) 2
293 (7,6,1) 2
296 (7,7,1) 3
257 (6,7,1) 3
218 (5,7,1) 3
179 (4,7,1) 3
176 (4,6,1) 3
173 (4,5,1) 3
170 (4,4,1) 4
209 (5,4,1) 4
248 (6,4,1) 4
287 (7,4,1) 4
326 (8,4,1) 4
329 (8,5,1) 4
332 (8,6,1) 4
335 (8,7,1) 4
338 (8,8,1) 5
299 (7,8,1) 5
260 (6,8,1) 5
221 (5,8,1) 5
182 (4,8,1) 5
143 (3,8,1) 5
140 (3,7,1) 5
137 (3,6,1) 5
134 (3,5,1) 5
131 (3,4,1) 5

如果您想要 CCW 螺旋反转 cw[] 或代替 dir++,请执行 dir--

如果您想要可变螺丝宽度,那么您只需将 i 增加实际宽度而不是仅仅增加一个。

根据@Spektre 的回答,这段代码对我有用:

const int x_res = 13;
const int y_res = 13;
const int z_res = 3;

const int dx = 39;
const int dy =  3;
const int dz =  1;

int cw[4]={-dx,-dy,+dx,+dy};    // CW rotation
int ix=254;                     // start point (center of spiral)
int dir=0;                      // direction cw[dir]
int n=30;                        // size
int i,j,k;

cout << ix << endl;

// first "lap" (consecutive nodes)
for (k=0,i=1;i<=2;i+=k,k^=1,dir++,dir&=3)
    for (j=1;j<=i;j++)
    {
        ix+=cw[dir];
        cout << ix << endl;
    }
i-=1;

int width = 2; //screw width
i+=width;
int dist = 1; //nodes separation
int node_count = 0; //nodes counter

for (k=k,i=i;i<=n;i+=k,k^=width,dir++,dir&=3)
{
    if (dir==1) 
    {
        dist+=1;
    }
    
    for (j=1;j<=i;j++)
    {
        ix+=cw[dir];
        node_count +=1;
        if ((0 < ix) && (ix <= x_res*y_res*z_res))
        {
            if (node_count == dist)
            {
                cout << ix << endl;
                node_count = 0;
            }
        }
        else return 0;
    }
}

return 0;

使用此输出:

254 215 212 251 290 293 296 257 218 179 140 134 128 206 284 362 368 374 380 302
224 146 68 59 50 83 200 317 434 443 452 461 386 269 152 35