图形的两个边缘之间的角度

时间:2014-10-20 07:38:18

标签: c++ visual-c++ math

我试图计算图形中两条边之间的角度,为了做到这一点,我将两条边都转移到原点,然后使用点积来计算角度。我的问题是,对于某些边缘,例如e1e2angle(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。您可以看到PointEdge here的实施情况。 我的输入是2D空间中的n Point s的集合S. 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()函数,我该如何解决?在这里是其他图书馆以更有效的方式计算罪和cos?

查看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.#INDOO四个边缘。 Out:

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

4 个答案:

答案 0 :(得分:3)

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

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

您是否检查过cosAlpha是否达不到1.000000000000000000000001?这可以解释结果,并提供另一个理由,不要像这样四处走动。

答案 1 :(得分:2)

似乎除以零。确保您的向量始终具有0<长度。

答案 2 :(得分:1)

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

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

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

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

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

答案 3 :(得分:1)

从我的评论中移出答案

检查点积是否在<-1,+1>范围内......

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