简体   繁体   English

3D阵列(1D平面)索引

[英]3D array (1D flat) indexing

I am using a coordinate system x (width), y (height), z (Depth) 我使用坐标系x(宽度),y(高度),z(深度)

Just to clear confusion if there is any x & y are a flat plane and I am using Z as elevation. 只是为了清除混淆,如果有任何x和y是一个平面,我使用Z作为高程。

I am going to be accessing the array millions of times per second and benchmarking shows that a 1D array using index is faster and I would like to squeeze as much efficiency as possible so that other things can use that time 我将每秒访问数组数百万次,并且基准测试显示使用索引的一维数组更快,我想尽可能多地挤压效率,以便其他东西可以使用那个时间

For example a 2D array --> 1D array creation is just 例如,2D阵列 - > 1D阵列创建就是

Object[] oneDArray = new Object[width * height]

and to index the array I can just use the following. 并索引数组我可以使用以下。

Object obj = oneDArray[x + y * width]

I did find the following on stackoverflow but I am not entirely sure which one is correct How to "flatten" or "index" 3D-array in 1D array? 我确实在stackoverflow上找到了以下内容,但我不完全确定哪一个是正确的如何在一维数组中“展平”或“索引”3D数组?

The "Correct" answer says to index the array do the following “正确”答案表示索引数组执行以下操作

Object[] oneDArray = new Object[width * height * depth]
Object obj = oneDArray[x + WIDTH * (y + DEPTH * z)]

But then another answer says that the "Correct" answer is wrong and uses the following 但另一个答案是说“正确”答案是错误的,并使用以下内容

Object[] oneDArray = new Object[width * height * depth]
Object obj = oneDArray[x + HEIGHT* (y + WIDTH* z)]

What is the correct way to read a flattened 3D array? 读取扁平3D阵列的正确方法是什么?

This depends on that how you want to order your 3D data in 1D array, if you wanted to have indexes in order: Z, Y, X then your 2x2x2 dimensioned 3D data will be stored like this: 这取决于你想如何在一维数组中订购3D数据,如果你想按顺序排列索引:Z,Y,X那么你的2x2x2尺寸的3D数据将被存储如下:

index 0: [z=0,y=0,x=0]
index 1: [z=0,y=0,x=1]
index 2: [z=0,y=1,x=0]
index 3: [z=0,y=1,x=1]
index 4: [z=1,y=0,x=0]
index 5: [z=1,y=0,x=1]
index 6: [z=1,y=1,x=0]
index 7: [z=1,y=1,x=1]

DEPTH dimension corresponds to z , HEIGHT to y and WIDTH to x DEPTH维度对应于z ,HEIGHT对应于y ,WIDTH对应于x

The index calculation will be: index = HEIGHT*WIDTH*z + WIDTH*y + x . 指数计算将是: index = HEIGHT*WIDTH*z + WIDTH*y + x

The x is not multiplied by anything because the next x index is right after the previous one. x不会乘以任何东西,因为下一个x索引就在前一个索引之后。

If you want to skip one Y row, you have to add whole row WIDTH, in this case 2, for example if you are at index 1, which has z=0,y=0 and x=1 and you add WIDTH=2 to index, you'll get index 3. Only y dimension has increased by 1. 如果要跳过一个Y行,则必须添加整行WIDTH,在本例中为2,例如,如果您在索引1处,其中z = 0,y = 0且x = 1并且您添加WIDTH = 2要索引,你将得到索引3.只有y维度增加了1。

To move from z=0 to z=1, you have to skip 4 indexes (look up at the index listing), the number is HEIGHT*WIDTH (in this example 2*2). 要从z = 0移动到z = 1,您必须跳过4个索引(查看索引列表),数字是HEIGHT * WIDTH(在此示例中为2 * 2)。

Performance 性能

To gain speed its best to process your 3D data with z,y,x coordinates incrementing in a sequence so you don't have to recalculate the index so often. 为了获得速度,最好处理您的3D数据,z,y,x坐标按顺序递增,这样您就不必经常重新计算索引。 For example: 例如:

int z = 1, y=1, x=0;
int index = HEIGHT*WIDTH*z + WIDTH*y;
int data;

for(x=0;x<WIDTH;x++)
{
    Object obj = oneDArray[index+x];
}

In ideal case, all processing of data is independent from each other and you don't have to even calculate the index, just increment one index trough whole oneDArray . 在理想情况下,所有数据处理都是相互独立的,您甚至不必计算索引,只需通过整个oneDArray递增一个索引。 What's possible to precompute depends on your usage. 预计算的可能性取决于您的使用情况。

use the formula index = x*height*depth + y*depth + z Sample java code illustration. 使用公式index = x*height*depth + y*depth + z示例java代码插图。

public class FlattenedArray {
    public static void main(String[] args) {
        int width = 2;
        int height = 3;
        int depth = 4;
        int[][][] d3 = new int[width][height][depth];
        int[] d1 = new int[width*height*depth];

        //3D Array :
        int w=0;
        for(int i=0;i<width;i++) 
            for(int j=0;j<height;j++)
                for(int k=0;k<depth;k++) {
                    d3[i][j][k] = ++w;
                    System.out.print(d3[i][j][k] + " ");
                }
        System.out.println();

        //1D Array :
        w=0;
        for(int i=0;i<width;i++) 
            for(int j=0;j<height;j++)
                for(int k=0;k<depth;k++) {
                    int index = i*height*depth + j*depth + k;
                    d1[index] = ++w;
                }

        for(int i=0;i<width*height*depth;i++) {
            System.out.print(d1[i] + " ");
        }
    }
}

Here is a solution in Java that gives you both: 这是一个Java解决方案,它为您提供:

  • from 3D to 1D 从3D到1D
  • from 1D to 3D 从1D到3D

My own micro benchmark showed that 1D array is 50% faster to get/set values than through 3D array. 我自己的微基准测试显示,1D阵列获得/设置值比通过3D阵列快50%。

Below is a graphical illustration of the path I chose to traverse the 3D matrix, the cells are numbered in their traversal order: 下面是我选择遍历3D矩阵的路径的图形说明,单元格按其遍历顺序编号:

2 3D矩阵的示例

Conversion functions: 转换功能:

public int to1D( int x, int y, int z ) {
    return (z * xMax * yMax) + (y * xMax) + x;
}

public int[] to3D( int idx ) {
    final int z = idx / (xMax * yMax);
    idx -= (z * xMax * yMax);
    final int y = idx / xMax;
    final int x = idx % xMax;
    return new int[]{ x, y, z };
}

The code above could surely be factorised to be faster, but I left it as such to make it easier to understand the 2 way conversion ;) 上面的代码肯定会被分解为更快,但我这样做是为了让它更容易理解2路转换;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM