【问题标题】:A function to populate an array with maps用地图填充数组的函数
【发布时间】:2011-07-26 05:59:56
【问题描述】:

我对 C++ 很陌生,所以我不确定我是否以正确的方式解决这个问题。我正在处理体素数据的 3D 数组,我想创建一个并行数据结构来存储等值面法线向量。内存效率是一个问题,所以我想使用一个 2D 地图数组,它由一个整数索引并包含一个 3D 向量。

这个想法是二维数组索引每个 x 和 y 坐标,而地图只索引包含一个值的 z 坐标(通常在 z 轴的每一行分散在 0 到 3 个值之间)。

问题 1:如何创建像 std::map<int, Vector3f> surfaceNormals; 这样的二维地图数组?

问题 2:我的想法是声明 2D 数组全局然后用一个函数填充它,该函数通过指针处理它并为每个数组单元创建一个映射,下面的代码是否在正确的轨道上? ????? 表示鉴于我对问题 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 中并使用数组算法访问元素?为什么要在那里使用地图?
  • 花了我一些时间,但我想我明白了。当您在问题中说 3D 矢量 时,您的意思是几何中的矢量,对吗?不是嵌套的std::vector。对吗?

标签: c++ arrays map


【解决方案1】:

如果我理解正确,你想将坐标用作 std::map 键吗?

您可以只创建一维 std::map,并将 XYZ 坐标转换为一维坐标系:

int pos1d = z*max_x*max_y+y*max_x+x;

然后把它放到地图键上。

编辑: 或者您可以只使用 x,y,z 作为整数的结构,如 Space_C0wb0y 所示,但这当然会占用每个 std::map 键 3 倍的内存,还请注意我展示的示例将具有最大立方体大小:1625x1625x1625(如果是 unsigned int),因此如果您需要更长的坐标,请使用结构,但请注意,对于结构,您必须为 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

#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);

【讨论】:

  • 感谢菜鸟,但我将如何将地图传入和传出函数?
  • 我认为你不应该从函数返回 std::map 作为返回值,而是使用 std::map 作为函数参数引用:void extractIS(float Threshold, MyMap &amp;surfacePointer){ 因为现在你可以发送和返回std::map 在同一个参数。
【解决方案2】:

首先,地图有一个higher memory overhead 而不是a vector。这就提出了一个问题,有多少元素?有部分为空的向量是否可行?考虑以下实现:

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);

您只需将所有值保存在内存中,假设其中只有少数是空的,并且 z 值永远不会超过 4 个。您可以像这样在X, Y, Z 位置访问3dvec

data[X + Y*width][Z]

这是做了很多假设,但最终,您将不得不比较可能的解决方案,因为可行性取决于数据。

【讨论】:

  • 谢谢,我不确定我是否完全理解,我已经有一个我想使用的 3D(几何)矢量类...数据由 256*256*100 体素组成,可能最多到需要并行存储的 3*256*256 个表面法线向量。这行得通吗?
  • 我是否正确假设,对于每个向量,您存储 3*256*256 表面法线向量?在这种情况下,使用 Rookie 的解决方案肯定会更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
  • 1970-01-01
  • 2018-12-23
  • 2019-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多