如何计算两条线之间的正负角度?

Jaa*_*nus 13 math geometry 2d

这里有一组非常方便的2d几何实用程序.

但是,AngleBetweenLines存在问题.结果总是积极的.我需要检测正角度和负角度,因此如果一条线在另一条线"高于"或"低于"15度,则形状显然看起来不同.

我的配置是一条线保持静止,而另一条线旋转,我需要通过将它与固定线进行比较来了解它旋转的方向.

编辑:为了回应下面swestrup的评论,情况实际上是我有一条线,我记录了它的起始位置.然后该线从其起始位置旋转,我需要计算从其起始位置到当前位置的角度.例如,如果它顺时针旋转,则为正旋转; 如果逆时针,则为负.(或相反亦然.)

如何改进算法,使其根据线的位置返回正负角度?

Jaa*_*nus 20

这是brainjam建议的实现.(它符合我的约束条件,线条之间的差异保证足够小,不需要对任何东西进行标准化.)

CGFloat angleBetweenLinesInRad(CGPoint line1Start, CGPoint line1End, CGPoint line2Start, CGPoint line2End) {
    CGFloat a = line1End.x - line1Start.x;
    CGFloat b = line1End.y - line1Start.y;
    CGFloat c = line2End.x - line2Start.x;
    CGFloat d = line2End.y - line2Start.y;

    CGFloat atanA = atan2(a, b);
    CGFloat atanB = atan2(c, d);

    return atanA - atanB;
}
Run Code Online (Sandbox Code Playgroud)

我喜欢它简洁.矢量版本会更简洁吗?

  • 在我看来,这应该是公认的答案. (3认同)

bra*_*jam 8

@ duffymo的回答是正确的,但如果你不想实现跨产品,你可以使用atan2函数.这将返回-π和π之间的角度,您可以在每条线上使用它(或者更准确地说是表示线条的矢量).

如果你得到第一条(静止线)的角度θ,你必须将第二条线的角度φ标准化,使其在θ-π和θ+π之间(加上±2π).那么两条线之间的角度将是φ-θ.

  • 所有这些矢量的东西让我大吃一惊。(抱歉,我忘记了很多数学知识...)现在,我只需计算两条线的 atan2 并进行比较,效果很好。谢谢。 (2认同)

duf*_*ymo 7

这是涉及2D矢量的简单问题.两个矢量之间的角度的正弦值与两个矢量之间的交叉积相关.并且"上方"或"下方"由交叉乘积产生的向量的符号确定:如果跨越两个向量A和B,并且产生的交叉积为正,则A"低于"B; 如果它是否定的,A是"高于"B.有关详细信息,请参阅Mathworld.

以下是我在Java中编写代码的方法:

package cruft;

import java.text.DecimalFormat;
import java.text.NumberFormat;

/**
 * VectorUtils
 * User: Michael
 * Date: Apr 18, 2010
 * Time: 4:12:45 PM
 */
public class VectorUtils
{
    private static final int DEFAULT_DIMENSIONS = 3;
    private static final NumberFormat DEFAULT_FORMAT = new DecimalFormat("0.###");

    public static void main(String[] args)
    {
        double [] a = { 1.0, 0.0, 0.0 };
        double [] b = { 0.0, 1.0, 0.0 };

        double [] c = VectorUtils.crossProduct(a, b);

        System.out.println(VectorUtils.toString(c));
    }

    public static double [] crossProduct(double [] a, double [] b)
    {
        assert ((a != null) && (a.length >= DEFAULT_DIMENSIONS ) && (b != null) && (b.length >= DEFAULT_DIMENSIONS));

        double [] c = new double[DEFAULT_DIMENSIONS];

        c[0] = +a[1]*b[2] - a[2]*b[1];
        c[1] = +a[2]*b[0] - a[0]*b[2];
        c[2] = +a[0]*b[1] - a[1]*b[0];

        return c;
    }

    public static String toString(double [] a)
    {
        StringBuilder builder = new StringBuilder(128);

        builder.append("{ ");

        for (double c : a)
        {
            builder.append(DEFAULT_FORMAT.format(c)).append(' ');
        }

        builder.append("}");

        return builder.toString();
    }
}
Run Code Online (Sandbox Code Playgroud)

检查第3个组件的标志.如果是正数,A是"低于"B; 如果它是负的,A是"高于"B - 只要两个矢量位于y轴右侧的两个象限中.显然,如果它们都位于y轴左侧的两个象限中,则反之亦然.

你需要考虑你的"上方"和"下方"的直观概念.如果A在第一象限(0 <=θ<= 90)且B在第二象限(90 <=θ<= 180),该怎么办?"上方"和"下方"失去了意义.

然后该线从其起始位置旋转,我需要计算从其起始位置到当前位置的角度.例如,如果它顺时针旋转,则为正旋转; 如果逆时针,则为负.(或相反亦然.)

这正是跨产品的用途.第三个分量的符号对于逆时针是正的而对于顺时针是负的(当你向下看旋转的平面时).