我对C ++很陌生,所以我不确定我是否会以正确的方式解决这个问题。我正在处理体素数据的3D数组,我想创建一个并行数据结构来存储等值面法线向量。内存效率是一个问题所以我想使用2D数组的地图,它们由一个整数索引并包含一个3D矢量。
2D阵列的想法是对每个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);
答案 0 :(得分:4)
如果我理解正确,你想将坐标用作std :: map键吗?
您可以创建1维std :: map,并将XYZ坐标转换为1维坐标系:
int pos1d = z*max_x*max_y+y*max_x+x;
然后将其放入地图键。
编辑:或者您可以使用带有x,y,z的结构作为整数,如Space_C0wb0y所示,但当然每个std :: map键需要多3倍的内存,同时请注意我展示的示例将具有最大立方体大小:1625x1625x1625(如果是unsigned int),因此如果您需要更长的坐标,则使用结构,但请注意,对于结构,您必须为std :: map键数据类型编写比较函数。 / p>
<强> EDIT3:强> 我认为这就是你要找的东西,因为我注意到你使用了最大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&lt;&lt; 16)|(y&lt;&lt; 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);
答案 1 :(得分:1)
首先,地图的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);
您只需将所有值保留在内存中,基于以下假设:只有少数值为空,并且永远不会有超过4个z值。您可以访问3dvec
位置X, Y, Z
,如下所示:
data[X + Y*width][Z]
这做了很多假设,但最后,你必须比较可能的解决方案,因为可行性取决于数据。