鉴于:
我想确定这三点之间的角度,我想知道,在哪个象限中找到最后一次触摸。
角度的计算效果很好,而象限总是1或2,从不3或4。
我哪里错了?
CGFloat DistanceBetweenTwoPoints(CGPoint point1,CGPoint point2)
{
CGFloat dx = point2.x - point1.x;
CGFloat dy = point2.y - point1.y;
return sqrt(dx*dx + dy*dy );
};
NSInteger GetQuadrant(double angle)
{
double sinAngle = sin(angle);
double cosAngle = cos(angle);
double tanAngle = tan(angle);
double cotAngle = 1.0/tanAngle;
NSLog(@"%f %f %f %f", sinAngle, cosAngle, tanAngle, cosAngle);
if(sinAngle > 0 && cosAngle > 0 && tanAngle > 0 && cotAngle > 0) return 1;
if(sinAngle > 0 && cosAngle < 0 && tanAngle < 0 && cotAngle < 0) return 2;
if(sinAngle < 0 && cosAngle < 0 && tanAngle > 0 && cotAngle > 0) return 3;
if(sinAngle < 0 && cosAngle > 0 && tanAngle < 0 && cotAngle < 0) return 4;
return 0;
}
double AngleBetweenThreePoints(CGPoint point1,CGPoint point2, CGPoint point3)
{
CGPoint point_a = point1;
CGPoint point_b = point2;
CGPoint point_c = point3;
CGFloat a, b, c;
a = DistanceBetweenTwoPoints(point_b, point_c);
b = DistanceBetweenTwoPoints(point_a, point_c);
c = DistanceBetweenTwoPoints(point_a, point_b);
double result = acos((b*b+c*c-a*a)/(2*b*c));
NSLog(@"%d", GetQuadrant(result));
return result/M_PI * 180.0;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
startPoint = [[touches anyObject] locationInView:self];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint point = [[touches anyObject] locationInView:self];
double angle = AngleBetweenThreePoints(self.clickWheelCenter, startPoint, point);
NSLog(@"%f", angle);
}
答案 0 :(得分:4)
这一切都可以轻松完成。
{x1,y1} =第一个点 - 中心点,{x2,y2} =第三个点 - 中心点,有符号角度( - pi,+ pi)由下式给出:
atan2(x2*y1 - x1*y2,x1*x2 + y1*y2)
根据您对角度符号的定义,您可能想要或不想在前面添加减号。
您可以轻松地从符号和绝对大小派生象限。
答案 1 :(得分:3)
正如其他人所提到的那样,你所做的事情的内角总是小于180度。我假设您想要从一个矢量到另一个矢量的逆时针角度测量的象限。
获得此象限的一种简单方法是使用点积和perp点积并检查每个结果的符号。
这是因为点积等于| A | * | B | * cos(theta)其中||表示幅度,theta是A和B之间的角度。由于幅度总是正的,通过检查结果的符号,您实际上是在检查cos(theta)的符号。
Perp点积实际上是| A | * | B | * sin(theta)所以通过检查perp点的符号,你实际上是在检查sin(theta)的符号。
让我们说我们测量theta为从A到B的逆时针角度。象限也用θ测量。我们可以通过以下
计算点和perpdot首先,您需要获取向量A和B. A和B将是从clickWheelCenter到startpoint的向量,从clickWheelCenter到您称为'point'的向量
dot = A.x * B.x + A.y * B.y
perpdot = A.x * B.y - A.y * B.x
然后检查标志,注意下表。
quadrant dot perpdot 1 positive positive 2 negative positive 3 positive negative 4 negative negative
同样,通过检查点积的符号,您实际上是在检查cos(theta)的符号,并通过检查perpdot来检查sin(theta)的符号。您只需要一组if语句进行比较,如果这些语句是&gt; 0或&lt; 0
(注意:我上面写的很快,并没有很好地检查一切准确性,但一般的想法是正确的)
BBitmaster
答案 2 :(得分:1)
因为余弦定律只会返回180度或更小的内角。我不太确定你在这里尝试做什么,但这种方法在四分法方面没有意义。此外,您需要错误检查这是否是生产级代码。当你的三角形退化时,余弦定律会爆炸。
答案 3 :(得分:1)
似乎你的函数AngleBetweenThreePoints
只返回0和Pi之间的角度,然后传递给它。
你的问题是acos不是一对一的功能。对于任何给定的输入,有多个值,因此没有任何进一步的知识,它将只选择给定范围内的一个。一个简单的例子是270degrees和90degrees都有cos等于0.所以如果你acos(0)那么它显然只能返回两个中的一个。
我有点不清楚你在哪个象限意味着什么。通常你可以通过查看x和y坐标的符号来判断并使用它来计算你的象限。观察两条线之间的角度将为象限(相对于第一条线的象限)提供一个奇怪的值 - 这是你想要的吗?
答案 4 :(得分:1)
您正在计算始终小于180度的内角。 这是计算直角值的快速而正确的方法:
double AngleBetweenThreePoints(CGPoint pointA, CGPoint pointB, CGPoint pointC)
{
CGFloat a = pointB.x - pointA.x;
CGFloat b = pointB.y - pointA.y;
CGFloat c = pointB.x - pointC.x;
CGFloat d = pointB.y - pointC.y;
CGFloat atanA = atan2(a, b);
CGFloat atanB = atan2(c, d);
return atanB - atanA;
}