在容器中迭代一系列角度的成语

idiom for iterating a range of angles in a container?

本文关键字:成语 一系列 迭代      更新时间:2023-10-16

假设我有2D行的数据

struct Point { int x, y; };
struct Line {
    Point p1, p2;
    double angle() const { return atan2(p2.y-p1.y, p2.x-p1.x); }
};

我想以角度存储这些分类,必须在间隔(-PI, PI]中进行分类。

我的问题:我想迭代该容器中的一个范围,但请允许其围绕间隔的末端包裹。例如"角度 PI*3/4-PI*3/4之间的所有线条"。

要澄清,如果我使用multimap等标准容器,我不能简单地做通常的事情:

std::multimap<double, Line> lm;
//insert elements...
auto begin = lm.lower_bound(PI*3/4);
auto end = lm.upper_bound(-PI*3/4);
for(auto & i = begin; i != end; ++i) {  //infinite loop: end is before begin!
    //do stuff with i
}

我猜我可以攻击"循环迭代i"功能,以取代循环中的++i。但这似乎应该是一个普遍的问题,所以我想知道是否已经有一个现有的习语来解决它?

有三角方法可以解决圆形范围的问题。对于范围 - 将其末端标准化(此处的示例),并获得中间角度和半角度

if range_end < range_start then
   range_end = range_end + 2 * Pi
half = (range_end - range_start) / 2
mid  = (range_end + range_start) / 2
coshalf = Cos(half)

现在比较中间角度和范围的差异比半角度较低。余弦通过周期性,负值等解决潜在的麻烦。

if Cos(angle - mid) >= coshalf then
  angle lies in range