测试角度是否在范围内(有效且优雅)
Test if angle is in range (efficiently and elegantly)
我有一个角度phi
,我想测试它是否在周期性0..2pi
空间中的区间a
、b
内(比如说闭合,但无关紧要)。phi
、a
和b
的值没有限制,特别是:
a>b
是可能的(例如a=(3/2.)pi,b=pi/;2对应于区间-pi/2…pi/2)- 如果是
a==b
,则间隔为零宽度,并且只有phi==a
在内部 - 有了
a-b>=2*pi
,phi
将始终在内部
我想出了以下方法:
bool angleInside(const double& phi, double a, const double& b){
if(std::abs(a-b)>=2*M_PI) return true; // interval covers everything
if(a>b) a-=2*M_PI;
if(a==b) return (fmod(a,2*M_PI)==fmod(phi,2*M_PI)); // corner case
assert(b-a>0 && b-a<2*M_PI); // unless I overlooked something?
// wrap phi so that a+pphi is in a..a+2*M_PI, i.e. pphi in 0..2*M_PI
double n=(phi-a)/(2*M_PI); // n in <0..2pi)
double pphi=(n-floor(n))*(2*M_PI);
return pphi<(b-a);
}
但我不确定它是否有效,也许没有libs实现这样的东西。
您的条件是矛盾的,特别是条件:
当a-b>=2*pi时,phi将始终在内
有点奇怪。任一:
- 您的范围是模空间中的[a,b],即
a-b
永远不会大于2pi
- 您的范围是[a,b]如果(a<b)或[b,a]如果(a>b)和,则应用模
在任何情况下,每当你遇到这样的问题时,都可以方便地从左边界和范围大小来考虑,而不是从左极限和右极限来考虑。
也就是说,如果你能用a==0
解决这个问题,那么你就可以用phi' = phi - a
和b' = b - a
来使用这个解决方案。
还要记住,在此类问题中,std::remainder
(仅C++11)是您的朋友,因为与fmod
不同,它总是会产生(-pi, pi)
范围内的结果。
我提出的解决方案是:
bool angleInside(const double phi, const double a, const double b)
{
//Case 1 above
const double d = phi - a;
const double s = std::remainder(b-a - M_PI, 2 * M_PI) + M_PI;
// Or (Case 2)
const double d = phi - std::min(a,b);
const double s = std::fabs(b-a);
return std::remainder( d - M_PI, 2 * M_PI ) + M_PI <= s;
}
请注意,在这两种情况下,边界情况很难得到一致的结果,尤其是当phi
大并且落在范围边界模2pi
中时。
如果您可以将"double phi"更改为类/结构Angle,它存储角度的cos和sin值,而不是角度值本身。然后你可以很容易地区分,一个角度alpha是在另一个角度beta的"右边"还是"左边"。样品:
struct Angle {
Angle() : m_cos(1.), m_sin(0.) {} // 0 degree
// some other methods
friend double sin( const Angle& a ) { return a.m_sin; }
friend double cos( const Angle& a ) { return a.m_cos; }
bool operator<( const Angle& beta ) const {
return (m_cos * beta.m_sin - m_sin * beta.m_cos) > 0.;
}
private:
double m_cos, m_sin;
};
不知道这在您的应用程序中是否有意义。如果是,您可以编程一个间隔
struct Interval {
Interval( const Angle& from, const Angle& to )
: m_from( from ), m_to( to ), m_inner( from < to )
{}
friend bool in( const Angle& a, const Interval& i ) { // true, if 'a' is in ]from, to[
if( i.m_inner )
return i.m_from < a && a < i.m_to;
return i.m_from < a || a < i.m_to;
}
private:
Angle m_from, m_to;
bool m_inner;
};
使用函数"in"检查角度"a"是否在区间"i"中。
请考虑,没有定义从==到的空(或整体满!)间隔!在这种情况下你需要特别处理。
相关文章:
- 为什么在全局范围内使用"extern int a"似乎不行?
- 错误:未在此范围内声明'reverse'
- 并行用于C++17中数组索引范围内的循环
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 不计算一个范围内的完美数
- 错误:"imread"未在此范围内声明
- 我在范围内未声明的错误类有问题
- 如何在cpp中使用地图显示给定日期范围内(在下面的问题中)的费率?
- 我有一个数组,我想输入一个范围,然后找到范围内所有偶数的总和?
- 未在此范围内声明错误 'xy'
- 在C++中使用变量而不是"#define"来指定数组大小是不是一种糟糕的做法?(C错误:在文件范围内
- 命名空间范围内的外部 - GCC vs clang vs msvc
- 如何改进一堆在已知值范围内评估变量的 else-if 条件?
- 如何仅使用 While 循环在给定范围内找到可被 7 整除的计数整数
- "using namespace"子句在什么范围内有效?
- 如何有效地获得给定范围内的除数和
- 如何在大数组中最有效地增加指定范围内的值,然后找到最大值
- C++中数组范围内的有效元素计数
- 测试角度是否在范围内(有效且优雅)
- 如何检查两个数字是否在浮点类型的精度限制的有效数字"x"范围内?