【问题标题】:Angle between 3 points signed, bad results3点之间的角度签名,不好的结果
【发布时间】:2011-08-15 15:20:33
【问题描述】:

我想在 Java/Android 中开发一种命运之轮。当用户触摸屏幕时,我会检测到运动,并且对于每次变化,我都会计算旧压力与最新压力之间的角度(函数 onScroll)。我有一个问题,因为我不记得如何计算 3 点之间的角度...

我开发了 3 个函数,但每个函数都给我不同的结果:

public class Test {

public static void main(String[] args) {
    Test test = new Test();

    Point center = new Point(2.26f, 2.26f);
    Point current = new Point(2.54f, 3.64f);
    Point previous = new Point(2.25f, 3.73f);

    System.out.println("1) Angle is "
            + test.function1(center, current, previous));
    System.out.println("2) Angle is "
            + test.function2(center, current, previous));
    System.out.println("3) Angle is "
            + test.function3(center, current, previous));
    System.out.println("################################");

    center = new Point(2.26f, 2.26f);
    previous = new Point(3.29f, 1.04f);
    current = new Point(0.98f, 2.25f);
    System.out.println("1) Angle is "
            + test.function1(center, current, previous));
    System.out.println("2) Angle is "
            + test.function2(center, current, previous));
    System.out.println("3) Angle is "
            + test.function3(center, current, previous));
    System.out.println("################################");

    center = new Point(226.0f, 226.0f);
    previous = new Point(225.21994f, 373.3158f);
    current = new Point(254.31085f, 364.05264f);
    System.out.println("1) Angle is "
            + test.function1(center, current, previous));
    System.out.println("2) Angle is "
            + test.function2(center, current, previous));
    System.out.println("3) Angle is "
            + test.function3(center, current, previous));
    System.out.println("################################");
}

public double function1(Point center, Point current, Point previous) {

    double ang1 = Math.atan((previous.getdY() - center.getdY())
            / (previous.getdX() - center.getdX()));
    double ang2 = Math.atan((current.getdY() - center.getdY())
            / (current.getdX() - center.getdX()));
    double rslt = ang1 - ang2;

    return Math.toDegrees(rslt) * -1;
}

private double function2(Point center, Point current, Point previous) {
    float dx = current.getdX() - center.getdX();
    float dy = current.getdY() - center.getdY();
    double a = Math.atan2(dy, dx);

    float dpx = previous.getdX() - center.getdX();
    float dpy = previous.getdY() - center.getdY();
    double b = Math.atan2(dpy, dpx);

    double diff = a - b;
    double degres = Math.toDegrees(diff);
    return degres;
}

public double function3(Point center, Point current, Point previous) {
    Point p1 = new Point(current.getdX() - center.getdX(), current.getdY()
            - center.getdY());
    Point p2 = new Point(previous.getdX() - center.getdX(),
            previous.getdY() - previous.getdY());
    double angle = Math.atan2(p1.getdY() - p2.getdY(),
            p1.getdX() - p2.getdX());

    return Math.toDegrees(angle);
}

}

我在网上找到了这个功能,但我不知道哪个最好。

你能帮帮我吗?

【问题讨论】:

  • 最好的答案是举出真实的例子,并从中构建单元测试。聪明点,好好测试,选对的。
  • 你得到了什么结果?
  • Thomas 示例的接缝完美地工作。现在,我想知道我的角度是正的还是负的。我正在寻找解决方案的链接。

标签: java android math


【解决方案1】:
private double angleBetween(Point center, Point current, Point previous) {

  return Math.toDegrees(Math.atan2(current.x - center.x,current.y - center.y)-
                        Math.atan2(previous.x- center.x,previous.y- center.y));
}

这首先计算center->current和center->previous相对于x轴的角度,并取2之间的差

这类似于function2

【讨论】:

  • 注意atan2通常将y作为第一个参数,x作为第二个参数。
  • @ratchet 怪胎 NateS 在那边有正确的观点。编辑您的答案。它给出了正确的方向角度
【解决方案2】:

看看这里:http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm

就你的function2而言:

private double function2(Point center, Point current, Point previous) {
  float v1x = current.getdX() - center.getdX(); 
  float v1y = current.getdY() - center.getdY();

  //need to normalize:
  float l1 = Math.sqrt(v1x * v1x + v1y * v1y);
  v1x /= l1;
  v1y /= l1;

  float v2x = previous.getdX() - center.getdX();
  float v2y = previous.getdY() - center.getdY();

  //need to normalize:
  float l2 = Math.sqrt(v2x * v2x + v2y * v2y);
  v2x /= l2;
  v2y /= l2;    

  double rad = Math.acos( v1x * v2x + v1y * v2y );

  double degres = Math.toDegrees(rad);
  return degres;
}

编辑:对于有符号值,请使用 Math.atan2(...)。 引用链接页面:

如果我们想要一个 + 或 - 值来指示哪个向量在前面,那么我们可能需要使用 atan2 函数(如本页所述)。使用:

2 相对于 1 的角度 = atan2(v2.y,v2.x) - atan2(v1.y,v1.x)

因此,将double rad = Math.acos( v1x * v2x + v1y * v2y ); 替换为double rad = Math.atan2( v2y,v2x) - Math.atan2(v1y,v1x);,应该没问题。

【讨论】:

  • @FinalSpirit 我链接的页面给了你一个提示,但为了更容易我添加了一个编辑。
  • 谢谢,但我不明白这些结果:
    首先,我有这一点:Previous = Point(94.78006;219.21054) Current = Point(93.37244;225.10526) Center = Point(226.0;226.0) Calculate degres = -2.575375011820518 (good degres) 接下来,我有这个:Previous = Point(93.37244;225.10526) Current = Point(92.43402;227.63159) Center = Point(226.0;226.0) Calculate degres = 358.9136026239169 (It's very big !!!)
【解决方案3】:

从点中创建两个向量并使用dot product

【讨论】:

  • Indead,向量接缝是找到签名角度的完美方式!谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-04
  • 2016-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多