我有一个角度phi
,我会在定期a
空间内测试其内部(比如已关闭,但无关紧要)间隔b
,0..2pi
。对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);
}
但我不确定它是否有效,也许如果没有lib实现这样的事情。
答案 0 :(得分:0)
你的条件是矛盾的,特别是条件:
a-b> = 2 * pi,phi将始终位于
之内
有点奇怪。之一:
a-b
永远不会超过2pi
。在任何情况下,无论何时遇到这样的问题,都可以考虑左边界和范围大小,而不是左右限制。
也就是说,如果您可以使用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
时。
答案 1 :(得分:0)
如果你有可能改变双重发帖。到类/结构角度,它存储角度的cos值和sin值而不是角度值本身。然后,您可以轻松区分,角度alpha是否在“正确”位置。或者&#39;离开&#39;另一角β的一面。 样品:
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;
};
..功能&#39; in&#39;检查一个角度是否是一个角度&#39;在区间&#39; i&#39;。
请注意,未定义from == to的空(或整体!)间隔!在这种情况下,您需要特殊处理。