对于一些背景信息,我正在尝试使用字典查找创建快速四叉树生成算法。基本概念涉及通过二进制表示将坐标映射到四叉树节点:
struct vec2 { // Test coordinate object
double x, y; // replacing double with signed int everywhere does not achieve results either
vec2(const double& x = NULL, const double& y = NULL)
: x(x), y(y) {}
friend std::ostream& operator<<(std::ostream& os, vec2 vector)
{
return os << "(" << vector.x << ", " << vector.y << ")\n";
}
bool operator()(const vec2& lhs, const vec2& rhs) const
{
/* TODO: make proper sorting function */
if ((lhs.x < rhs.x) && (lhs.y < rhs.y)) {
return true;
}
if (std::hypot(lhs.x, lhs.y) < std::hypot(rhs.x, rhs.y)) {
return true;
}
return false;
}
};
std::map<vec2, std::bitset<4>, vec2> nodeLoc = { // quadtree node mapping
{ ( 1, 1), 1000 }, // first quadrant
{ (-1, 1), 0100 }, // second quadrant
{ (-1,-1), 0010 }, // third quadrant
{ ( 1,-1), 0001 }, // fourth quadrant
{ ( 0, 0), 0000 },
{ ( 0, 1), 1100 }, // first and second
{ ( 0,-1), 0011 }, // third and fourth
{ ( 1, 0), 1001 }, // first and fourth
{ (-1, 0), 0110 }, // second and third
};
int main() {
std::cout << nodeLoc[(-1, -1)];
return 0;
}
主函数应该将
0010
打印到控制台,但它却打印 1000
。地图函数将 (-1, -1)
与 (1, 1)
进行识别,但我认为 bool operator()
的定义会阻止它们被识别为相同的输入。我尝试创建一个与 std::unordered_map
一起使用的哈希函数,但最终遇到了类似的问题(尽管有点不同,因为 (-1,1)
会映射为与 (1,-1)
相同的映射)。
如何在有符号坐标与其二进制节点表示之间正确创建映射?
编译器可以指出代码中的两个关键错误:
<source>:9:28: warning: converting to non-pointer type 'double' from NULL [-Wconversion-null]
9 | vec2(const double& x = NULL, const double& y = NULL)
| ^~~~
首先,您所做的本质上是该代码中的
const double& x = 0
。 C++ 中不存在空引用之类的东西,这看起来就像您想要创建的那样。也不是说 const&
可以绑定到临时值(临时物化),以便代码可以编译。
要解决这个问题,要么完全删除构造函数,这使得
vec2
成为聚合类型。或者:
// note: don't use default arguments because they would allow initialization
// with just one argument, which is undesirable
vec2(double x, double y) : x(x), y(y) {}
vec2() : vec2(0, 0) {}
(1, 1)
是逗号表达式,而不是构造函数调用第二个错误是使用这种语法:
<source>:30:17: warning: left operand of comma operator has no effect [-Wunused-value]
30 | { ( 1, 1), 1000 }, // first quadrant
| ^
(1, 1)
并不是做vec2(1, 1)
,而是使用逗号运算符,其中左边的1
被丢弃,右边的1
用来调用vec2(1)
。您的原始构造函数只需一个参数即可调用,并且不是 explicit
,因此可以从 1
到 vec2
进行隐式转换。
要解决此问题,请使用
{ { 1, 1}, 1000 }
,其中内部 { 1, 1}
相当于 vec2(1, 1)
。
vec2
不应该是提供给std::map
的函数对象;您只需将 operator()
转换为 operator<
并使用 std::map<vec2, std::bitset<4>>
nodeLoc
应声明为 const
,而不是 nodeLoc[(x, y)]
(也使用逗号运算符),请编写 nodeLoc.at(x, y)