algorithmindexinggridpseudocodesample-data

Spiral in sampled x-y plane


Let’s say I have the following 3D discretized space, in which the indexes of the samples/nodes are sequential as it is shown in the picture.

sampled 3D

Now consider only the horizontal middle layer.

My objective is to find a programmatically and iterative rule/s that allow me to run a spiral (like the image or similar, it can start in any direction) over the mid-layer, starting from node 254, as it is shown on the image:

spiral

As you can see in the picture, the yellow crosses show the nodes to be explored. In the first lap these nodes are consecutive while in the second they are separated by 1 node and so on.

I started to solve the problem as follows (pseudocode):

  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

But I think there may be a simpler, more general rule.


Solution

  • Based on @Spektre answer, this code worked for me:

    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;
    

    with this output:

    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