基于位运算的3D坐标点八分象限计数:修正索引匹配问题
修正位运算实现的八分象限计数索引匹配问题
问题背景
我需要实现一个和OctantPopCount功能完全一致,但无if语句的八分象限计数函数。通过位运算实现的octant_count函数功能正常,但象限统计的索引和原函数不匹配——比如全正分量的点在原函数中对应counters[0],但在位运算实现中对应counters[7]。需要修正此索引匹配问题。
原OctantPopCount函数
#include <vector> #include <array> struct Point3D { double x, y, z; }; std::array<int, 8> OctantPopCount(const std::vector<Point3D>& points) { std::array<int, 8> counters = {0}; for (const auto& p : points) { if (p.x >= 0 && p.y >= 0 && p.z >= 0) { counters[0]++; } else if (p.x < 0 && p.y >= 0 && p.z >= 0) { counters[1]++; } else if (p.x < 0 && p.y < 0 && p.z >= 0) { counters[2]++; } else if (p.x >= 0 && p.y < 0 && p.z >= 0) { counters[3]++; } else if (p.x >= 0 && p.y >= 0 && p.z < 0) { counters[4]++; } else if (p.x < 0 && p.y >= 0 && p.z < 0) { counters[5]++; } else if (p.x < 0 && p.y < 0 && p.z < 0) { counters[6]++; } else if (p.x >= 0 && p.y < 0 && p.z < 0) { counters[7]++; } } return counters; }
初始位运算实现(索引不匹配)
std::array<int, 8> octant_count(const std::vector<Point3D>& points) { std::array<int, 8> counters = {0}; for (const auto& p : points) { // 正分量对应1,负分量对应0,全正组合为111=7,与原函数索引规则不符 int x_sign = (p.x >= 0) ? 1 : 0; int y_sign = (p.y >= 0) ? 1 : 0; int z_sign = (p.z >= 0) ? 1 : 0; int index = (z_sign << 2) | (y_sign << 1) | x_sign; counters[index]++; } return counters; }
测试结果对比
测试用例:包含全正点(1,1,1)、全负点(-1,-1,-1)、x负y正z正点(-1,1,1)各1个
- 原函数返回:
[1, 1, 0, 0, 0, 0, 1, 0] - 初始位运算实现返回:
[0, 0, 0, 0, 0, 0, 1, 1](全正点统计到counters[7],全负点统计到counters[0],x负y正z正点统计到counters[6])
可行的修正方法
- 索引反转法:在位运算生成初始索引后,用
7 - index得到修正后的索引。由于8个象限的索引范围是0-7,反转后正好将全正对应的7转为0,完全对齐原函数的索引规则。 - 索引映射表法:预先定义一个包含8个元素的映射数组,将位运算生成的索引映射为原函数对应的索引。例如:
const int octant_map[] = {7, 6, 5, 4, 3, 2, 1, 0};,后续用octant_map[calculated_index]作为计数器的下标。 - 符号位逻辑调整法:修改符号位的生成规则,将“正分量对应1”改为“负分量对应1,正分量对应0”。这样全正分量的符号位组合为
000,对应索引0,直接匹配原函数的统计规则,无需额外索引转换。
最终修正后的代码
方法1:索引反转法
std::array<int, 8> octant_count(const std::vector<Point3D>& points) { std::array<int, 8> counters = {0}; for (const auto& p : points) { int x_sign = (p.x >= 0) ? 1 : 0; int y_sign = (p.y >= 0) ? 1 : 0; int z_sign = (p.z >= 0) ? 1 : 0; int index = (z_sign << 2) | (y_sign << 1) | x_sign; // 反转索引对齐原函数规则 int corrected_index = 7 - index; counters[corrected_index]++; } return counters; }
方法2:符号位逻辑调整法
std::array<int, 8> octant_count(const std::vector<Point3D>& points) { std::array<int, 8> counters = {0}; for (const auto& p : points) { // 负分量标记为1,正分量标记为0,全正组合为000=0,直接匹配原函数索引 int x_sign = (p.x < 0) ? 1 : 0; int y_sign = (p.y < 0) ? 1 : 0; int z_sign = (p.z < 0) ? 1 : 0; int index = (z_sign << 2) | (y_sign << 1) | x_sign; counters[index]++; } return counters; }
内容的提问来源于stack exchange,提问作者Sinan Pasic
相关产品推荐
相关产品推荐

