让我们说你有这个:
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.我需要它,但没有标记它们.
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最终在原点),然后你考虑绝对角度的差异P3和P2.
优点atan2是表示整圆(你可以在-π和π之间得到任何数字),而acos你需要根据符号处理几种情况来计算正确的结果.
唯一的奇点atan2是(0, 0)......它意味着P2和P3必须来自不同的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)
我最近遇到了类似的问题,只是我需要区分正角度和负角度.如果这对任何人都有用,我建议我从这个邮件列表中抓取的代码片段,关于检测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)
几天前,一个人遇到了同样的问题,不得不坐在数学书上.我通过组合和简化一些基本公式解决了这个问题.
让我们考虑这个数字 -
我们想知道Θ,所以我们需要先找出α和β.现在,对于任何直线 -
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)
在Objective-C中你可以做到这一点
float xpoint = (((atan2((newPoint.x - oldPoint.x) , (newPoint.y - oldPoint.y)))*180)/M_PI);
Run Code Online (Sandbox Code Playgroud)
或者在这里阅读更多