一个用于填充数组的映射函数

3
我对C++还不是很熟悉,因此我不确定我是否以正确的方式解决了这个问题。我正在处理一个三维体素数据数组,并且想要创建一个并行数据结构来存储等值面法线向量。内存效率是一个问题,因此我想使用一个二维的映射数组,它们由整数索引,并包含一个三维向量。
我的想法是,二维数组索引每个x和y坐标,而映射仅索引包含值的z坐标(通常在z轴的每一行上分散0到3个值)。
问题1:如何创建一个映射数组的二维数组,例如std::map surfaceNormals;?
问题2:我的想法是全局声明这个二维数组,然后用指针处理它并为每个数组单元格创建一个映射的函数来填充它,下面的代码是否正确??????表示我不确定在问题1中应该放什么。
特别是,我是否正确地管理了指针/引用/值,以便实际存储我需要的所有数据?
????? isoSurfaces1 [256][100];

????? *extractIS(float Threshold, ????? *pointy){

   ????? *surfacePointer = pointy;

   for loop over x and y {

      std::map<int, Vector3f> surfaceNormals;

      for loop over z {

         [ ... find surface voxels and their normal vectors ... ]

         Vector3f newNormalVector(x,y,z);

         surfaceNormals[zi] = newNormalVector;
      }           

      surfacePointer[x][y] = surfaceNormals;
   }

   return surfacePointer;
}

extractIS(0.45, isoSurfaces1);

你的问题描述非常不清楚。为什么不直接将所有数据存储在一个std::vector中,并使用数组算术访问元素?为什么要在其中使用map? - Björn Pollex
1
花了我一些时间,但是我想我明白了。当你在你的问题中说“3D向量”时,你指的是几何中的向量,对吗?不是一个嵌套的std::vector。这样正确吗? - Björn Pollex
2个回答

4
如果我理解正确,您想将坐标用作std :: map键?您可以创建一个一维的std :: map,并将XYZ坐标转换为一维坐标系统:
int pos1d = z*max_x*max_y+y*max_x+x;

然后将其放入地图键中即可。
编辑:或者您可以像Space_C0wb0y展示的那样使用具有x、y、z整数的结构体,但这当然会使每个std::map键占用3倍的内存。还要注意,如果使用无符号整数,则我显示的示例将具有最大立方体尺寸:1625x1625x1625,因此,如果需要更长的坐标,请使用结构体,但请注意,对于std::map键数据类型,您必须编写比较器函数。
编辑3:我认为这就是您要找的,因为我注意到您使用了最大256个坐标值,以下是我的想法:
// NOTE: max 256x256x256 cube coordinates with this struct. change unsigned char to short or int etc if you need larger values.
// also note that if you change to something else than unsigned char, you cant use nor compare the union: v1.Pos > v2.Pos anymore. 
// (unless you use unsigned short for each coordinate, and unsigned __int64 for the union Pos value)

union PosXYZ {
    struct {
        unsigned char x, y, z, padding; // use full 32bits for better performance
    };
    unsigned __int32 Pos; // assure its 32bit even on 64bit machines

    PosXYZ(unsigned char x, unsigned char y, unsigned char z) : x(x), y(y), z(z), padding(0) {} // initializer list, also set padding to zero so Pos can be compared correctly.
};   


inline bool operator>(const PosXYZ &v1, const PosXYZ &v2){
    return v1.Pos > v2.Pos;
}


typedef map<PosXYZ, Vector3f, greater<PosXYZ> > MyMap;


void extractIS(float Threshold, MyMap &surfacePointer){
    for loop over x and y {
        for loop over z {
            // [ ... find surface voxels and their normal vectors ... ]
            Vector3f newNormalVector(x,y,z);

            surfacePointer[PosXYZ(x,y,z)] = newNormalVector;
        }           
    }
}


MyMap isoSurfaces1;

extractIS(0.45, isoSurfaces1);

另一种实现std::map键结构的方法是使用普通整数值,您可以通过自己类似于以下函数生成:((x << 16) | (y << 8) | z),这将使事情变得简单一些,因为您不再需要std::map的比较函数。
#define PosXYZ(x,y,z) (((x) << 16) | ((y) << 8) | (z)) // generates the std::map key for 256x256x256 max cube coords.

typedef map<unsigned __int32, Vector3f, greater<unsigned __int32> > MyMap;


void extractIS(float Threshold, MyMap &surfacePointer){
    for loop over x and y {
        for loop over z {
            // [ ... find surface voxels and their normal vectors ... ]
            Vector3f newNormalVector(x,y,z);

            surfacePointer[PosXYZ(x,y,z)] = newNormalVector;
        }           
    }
}


MyMap isoSurfaces1;

extractIS(0.45, isoSurfaces1);

谢谢你,新手,但是我该如何将地图传递到函数中并从函数中返回呢? - Nat
我认为你不应该将std :: map作为返回值从函数返回,而是使用std :: map作为函数参数引用:void extractIS(float Threshold,MyMap&surfacePointer){,因为现在可以在同一参数中发送和返回std :: map。 - Rookie

1
首先,地图比向量有更高的内存开销。这就引出了一个问题,有多少个元素?部分为空的向量是否可行?考虑下面的实现方法:
struct 3dvec {
    3dvec(int x, int y, int z) : x(x), y(y), z(z) {}

    int x;
    int y;
    int z;
};
std::vector<3dvec> empty_z_vector(4, 3dvec(0, 0, 0));
std::vector< std::vector<3dvec> > data(width*height, empty_z_vector);

你可以简单地将所有值保存在内存中,基于这样的假设:只有少数值为空,并且永远不会超过4个z值。你可以像这样访问3dvec在位置X,Y,Z

data[X + Y*width][Z]

这里做了很多假设,但最终你必须比较可能的解决方案,因为可行性取决于数据。


谢谢,不过我还不确定是否完全理解了。我已经有一个三维(几何)向量类想要使用... 数据由256256100个体素组成,可能需要同时存储高达3256256个表面法线向量。这样可以吗? - Nat
我猜测你为每个向量存储了3256256个表面法向量,是吗?如果是这样,那么使用Rookie的解决方案肯定会更好。 - Björn Pollex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接