如何从三点计算角度?

120 algorithm math geometry

让我们说你有这个:

P1 = (x=2, y=50)
P2 = (x=9, y=40)
P3 = (x=5, y=20)
Run Code Online (Sandbox Code Playgroud)

假设这P1是圆的中心点.它总是一样的.我想要由P2和组成的角度P3,或者换句话说,接下来的角度P1.内角是精确的.它总是一个锐角,所以小于-90度.

我想:伙计,这是简单的几何数学.但我现在已经找了一个大约6个小时的公式,并且只找到人们谈论复杂的美国宇航局的东西,如arccos和矢量标量产品.我的头感觉像在冰箱里.

一些数学大师认为这是一个简单的问题吗?我不认为编程语言在这里很重要,但对于那些认为它的人来说:java和objective-c.我需要它,但没有标记它们.

Lan*_*rts 87

如果你的意思是P1是顶点的角度那么使用余弦定律应该有效:

ARCCOS((P 12 2 + P 13 2 - P 23 2)/(2*P 12*P 13))

其中P 12是从P1到P2的段的长度,由...计算

sqrt((P1 x - P2 x)2 +(P1 y - P2 y)2)

  • http://www.mathwords.com/c/cosine_inverse.htm (2认同)

And*_*mbu 47

如果你认为它是两个向量,一个从点P1到P2,一个从P1到P3,它变得非常简单

所以:
a =(p1.x - p2.x,p1.y - p2.y)
b =(p1.x - p3.x,p1.y - p3.y)

然后,您可以反转点积公式:
点积
获得角度:
两个向量之间的角度

记住这一点 点积 只是意味着:a1*b1 + a2*b2(这里只有2个尺寸......)


650*_*502 25

处理角度计算的最佳方法是使用atan2(y, x)给定点x, y返回该点的角度和X+相对于原点的轴.

鉴于计算是

double result = atan2(P3.y - P1.y, P3.x - P1.x) -
                atan2(P2.y - P1.y, P2.x - P1.x);
Run Code Online (Sandbox Code Playgroud)

即你基本上翻译两个点-P1(换句话说,你翻译所有内容,以便P1最终在原点),然后你考虑绝对角度的差异P3P2.

优点atan2是表示整圆(你可以在-π和π之间得到任何数字),而acos你需要根据符号处理几种情况来计算正确的结果.

唯一的奇点atan2(0, 0)......它意味着P2P3必须来自不同的P1是在这种情况下没有意义谈论的角度.


sha*_*sir 19

让我举一个JavaScript的例子,我已经与之斗争了很多:

/**
 * Calculates the angle (in radians) between two vectors pointing outward from one center
 *
 * @param p0 first point
 * @param p1 second point
 * @param c center point
 */
function find_angle(p0,p1,c) {
    var p0c = Math.sqrt(Math.pow(c.x-p0.x,2)+
                        Math.pow(c.y-p0.y,2)); // p0->c (b)   
    var p1c = Math.sqrt(Math.pow(c.x-p1.x,2)+
                        Math.pow(c.y-p1.y,2)); // p1->c (a)
    var p0p1 = Math.sqrt(Math.pow(p1.x-p0.x,2)+
                         Math.pow(p1.y-p0.y,2)); // p0->p1 (c)
    return Math.acos((p1c*p1c+p0c*p0c-p0p1*p0p1)/(2*p1c*p0c));
}
Run Code Online (Sandbox Code Playgroud)

奖励:HTML5-canvas示例

  • 你可以通过减少`sqrt`和平方来提高效率.请参阅[我的答案](http://stackoverflow.com/a/21693144/405017)(用Ruby编写),或者在[更新演示](http://jsfiddle.net/d3aZD/88/)(JavaScript) ). (5认同)

And*_*ler 15

基本上你有两个向量,一个从P1到P2,另一个从P1到P3.所以你需要的是一个计算两个向量之间角度的公式.

看看这里有一个很好的解释和公式.

替代文字


Tre*_*reb 12

如果你认为P1是圆圈的中心,你会觉得太复杂了.你有一个简单的三角形,所以你的问题可以通过余弦定律来解决.不需要任何极坐标变换或某些.假设距离为P1-P2 = A,P2-P3 = B且P3-P1 = C:

角度= arccos((B ^ 2-A ^ 2-C ^ 2)/ 2AC)

您需要做的就是计算距离A,B和C的长度.您可以从点的x坐标和y坐标以及毕达哥拉斯定理中轻松获得这些距离.

长度= sqrt((X2-X1)^ 2 +(Y2-Y1)^ 2)


Mar*_*arc 8

我最近遇到了类似的问题,只是我需要区分正角度和负角度.如果这对任何人都有用,我建议我从这个邮件列表中抓取的代码片段,关于检测Android触摸事件的旋转:

 @Override
 public boolean onTouchEvent(MotionEvent e) {
    float x = e.getX();
    float y = e.getY();
    switch (e.getAction()) {
    case MotionEvent.ACTION_MOVE:
       //find an approximate angle between them.

       float dx = x-cx;
       float dy = y-cy;
       double a=Math.atan2(dy,dx);

       float dpx= mPreviousX-cx;
       float dpy= mPreviousY-cy;
       double b=Math.atan2(dpy, dpx);

       double diff  = a-b;
       this.bearing -= Math.toDegrees(diff);
       this.invalidate();
    }
    mPreviousX = x;
    mPreviousY = y;
    return true;
 }
Run Code Online (Sandbox Code Playgroud)


Min*_*mal 7

非常简单的几何解法与解释

几天前,一个人遇到了同样的问题,不得不坐在数学书上.我通过组合和简化一些基本公式解决了这个问题.


让我们考虑这个数字 -

角度

我们想知道Θ,所以我们需要先找出αβ.现在,对于任何直线 -

y = m * x + c
Run Code Online (Sandbox Code Playgroud)

A =(ax,ay),B =(bx,by),O =(ox,oy).所以对于OA线-

oy = m1 * ox + c   ? c = oy - m1 * ox   ...(eqn-1)

ay = m1 * ax + c   ? ay = m1 * ax + oy - m1 * ox   [from eqn-1]
                   ? ay = m1 * ax + oy - m1 * ox
                   ? m1 = (ay - oy) / (ax - ox)
                   ? tan ? = (ay - oy) / (ax - ox)   [m = slope = tan ?]   ...(eqn-2)
Run Code Online (Sandbox Code Playgroud)

以同样的方式,对于线OB -

tan ? = (by - oy) / (bx - ox)   ...(eqn-3)
Run Code Online (Sandbox Code Playgroud)

现在,我们需要? = ? - ?.在三角学中,我们有一个公式 -

tan (?-?) = (tan ? + tan ?) / (1 - tan ? * tan ?)   ...(eqn-4)
Run Code Online (Sandbox Code Playgroud)

在替换tan ?eqn-4中的(来自eqn-2)和tan b(来自eqn-3)的值并应用简化后,我们得到 -

tan (?-?) = ( (ax-ox)*(by-oy)+(ay-oy)*(bx-ox) ) / ( (ax-ox)*(bx-ox)-(ay-oy)*(by-oy) )
Run Code Online (Sandbox Code Playgroud)

所以,

? = ?-? = tan^(-1) ( ((ax-ox)*(by-oy)+(ay-oy)*(bx-ox)) / ((ax-ox)*(bx-ox)-(ay-oy)*(by-oy)) )
Run Code Online (Sandbox Code Playgroud)

这就对了!


现在,采取以下数字 -

角度

这个C#或Java方法计算角度(Θ) -

    private double calculateAngle(double P1X, double P1Y, double P2X, double P2Y,
            double P3X, double P3Y){

        double numerator = P2Y*(P1X-P3X) + P1Y*(P3X-P2X) + P3Y*(P2X-P1X);
        double denominator = (P2X-P1X)*(P1X-P3X) + (P2Y-P1Y)*(P1Y-P3Y);
        double ratio = numerator/denominator;

        double angleRad = Math.Atan(ratio);
        double angleDeg = (angleRad*180)/Math.PI;

        if(angleDeg<0){
            angleDeg = 180+angleDeg;
        }

        return angleDeg;
    }
Run Code Online (Sandbox Code Playgroud)


Ade*_*raa 6

在Objective-C中你可以做到这一点

float xpoint = (((atan2((newPoint.x - oldPoint.x) , (newPoint.y - oldPoint.y)))*180)/M_PI);
Run Code Online (Sandbox Code Playgroud)

或者在这里阅读更多

  • 呃,不.有三个点,中心不在(0,0),这给出了一个直角三角形,而不是顶点的角度.什么样的名字是一个角度的"xpoint"? (7认同)