2014-10-20 159 views
2

我试图计算图中两条边之间的角度,以便将两条边转移到原点,然后使用点积来计算角度。我的问题是,对于像e1e2的某些边缘,angle(e1,e2)的输出是-1.#INDOO。 这是什么输出?这是一个错误? 这里是我的代码:图的两条边之间的角度

double angle(Edge e1, Edge e2){ 
    Edge t1 = e1, t2 = e2; 
    Point tail1 = t1.getTail(), head1 = t1.getHead(); 
    Point u(head1.getX() - tail1.getX(), head1.getY() - tail1.getY()); 

    Point tail2 = t2.getTail(), head2 = t2.getHead(); 
    Point v(head2.getX() - tail2.getX(), head2.getY() - tail2.getY()); 

    double dotProduct = u.getX()*v.getX() + u.getY()*v.getY(); 
    double cosAlpha = dotProduct/(e1.getLength()*e2.getLength()); 

    return acos(cosAlpha); 
} 

Edge是持有两分一类,并且Point是把两个双号为x和y的类。 即时通讯使用angle(e1,e2)来计算像b向量的正交投影长度到一个向量像a

double orthogonalProjectionLength(Edge b, Edge a){ 
    return (b.getLength()*sin(angle(b, a) * (PI/180))); 
} 

和该功能有时也给我-1.#INDOO。你可以看到执行PointEdgehere。 我的输入是在二维空间中的一个集合S n Point。 IV构成p和q之间的所有边缘(P,Q是S),然后试图计算这样的角度:

for (int i = 0; i < E.size(); i++) 
    for (int j = 0; j < E.size(); j++){ 
     if (i == j) 
     cerr << fixed << angle(E[i], E[j]) << endl; //E : set of all edges 
    } 

如果问题来自cos()sin()功能,如何解决呢?在这里,其他的图书馆是以更有效的方式计算罪恶和罪犯的吗?

请看this的例子。 本例中的输入是两个不同的点(如p和q),并且它们之间有两个边(pqqp)。请问angle(pq , qp)总是180? angle(pq,pq)angle(qp,qp)应该为0.我的程序显示两种不同的行为,有时为angle(qp,qp) == angle(pq,pq) ==0angle(pq , qp) == angle(pq , qp) == 180.0,有时对于所有四条边来说,答案是-1.#INDOOOut:

Here是一个代码示例。 运行几次,你会看到错误。

+0

请给我们作出了榜样。 – 2014-10-20 07:39:54

+1

这是什么180?所有的东西都应该用弧度表示,所以只需要用弧度表示。 – 2014-10-20 07:59:01

+0

我很确定问题出在您发布的代码之外。但看起来你的问题在于边缘长度为零,这导致被零问题分隔。没有看到更多的代码,很难肯定地说为什么。 – 2014-10-20 08:07:57

回答

1

回答我的评论移动

检查,如果你的点积是<-1,+1>范围...

  • 由于浮动四舍五入它可以是例如1.000002045,这将导致acos失败。
  • 所以添加两个if s并夹紧到这个范围。
  • 或使用更快的方式:acos(0.99999*dot)
  • 但是降低了精确度各个角度
  • 并且如果0.9999常数太大,则错误仍然存​​在
2

它似乎被零除。确保你的矢量长度总是有0<

+0

这并没有提供问题的答案。要批评或要求作者澄清,请在其帖子下方留言。 – fredtantini 2014-10-20 08:01:22

+1

我觉得这是一个答案。没有完整的代码和一切,但仍然。它会回答'-1。#INDOO'错误是什么以及导致它的原因。 – fejese 2014-10-20 08:05:39

3

你想投影,你通过所有这些触发?你只需要在a的方向上用单位矢量来点b。所以最终的答案是

(Xa.Xb + Ya.Yb)/square_root(Xa^2 + Ya^2) 

您是否检查过cosAlpha没有达到1.000000000000000000000001?这将解释结果,并提供另一个不去这样的房子周围的理由。

+1

仍然必须确保'Xa^2 + Ya^2!= 0' – fejese 2014-10-20 08:06:36

+0

非常感谢,但无论如何,我需要的角度,因为我也想构建一个锥角TETA和检查天气点是在这个锥或不。 – MoNo 2014-10-20 08:07:55

+0

fejese是正确的检查非零长度,但它很难成像你尝试投射到一个点。 – 2014-10-20 08:09:08

1

推荐的计算角度的方法是使用atan2函数,它有两个参数。它返回四个象限的角度。

您可以通过两种方式来使用它:

  • 计算的uv角度分别核减:atan2(Vy, Vx) - atan2(Uy, Ux)

  • 计算交叉点和点积:atan2(Ux.Vy - Uy.Vx, Ux.Uy + Vx.Vy)

唯一的失败案例是(0, 0)

+0

非常感谢,这样做比我的方式容易。 – MoNo 2014-10-20 14:38:10