Вычисление угла между двумя линиями без вычисления наклона? (Ява)
У меня есть две строки: L1 и L2. Я хочу рассчитать угол между двумя линиями. L1 имеет точки: {(x1, y1), (x2, y2)}
и L2 имеет точки: {(x3, y3), (x4, y4)}
.
Как я могу рассчитать угол, образованный между этими двумя линиями, без вычисления наклонов? Проблема, с которой я в настоящее время сталкиваюсь, состоит в том, что иногда у меня есть горизонтальные линии (линии вдоль оси x), и следующая формула не работает (деление на ноль исключение):
arctan((m1 - m2) / (1 - (m1 * m2)))
где m1
и m2
- наклоны линии 1 и строки 2 соответственно. Есть ли формула/алгоритм, который может вычислять углы между двумя линиями, не получая при этом исключений по принципу "деление на ноль"? Любая помощь будет высоко оценена.
Это мой фрагмент кода:
// Calculates the angle formed between two lines
public static double angleBetween2Lines(Line2D line1, Line2D line2)
{
double slope1 = line1.getY1() - line1.getY2() / line1.getX1() - line1.getX2();
double slope2 = line2.getY1() - line2.getY2() / line2.getX1() - line2.getX2();
double angle = Math.atan((slope1 - slope2) / (1 - (slope1 * slope2)));
return angle;
}
Спасибо.
Ответы
Ответ 1
Функция atan2
облегчает боль при работе с atan
.
Объявляется как double atan2(double y, double x)
и преобразует прямоугольные координаты (x,y)
в угол theta
от полярных координат (r,theta)
Итак, я переписал ваш код как
public static double angleBetween2Lines(Line2D line1, Line2D line2)
{
double angle1 = Math.atan2(line1.getY1() - line1.getY2(),
line1.getX1() - line1.getX2());
double angle2 = Math.atan2(line2.getY1() - line2.getY2(),
line2.getX1() - line2.getX2());
return angle1-angle2;
}
Ответ 2
Точечный продукт, вероятно, более полезен в этом случае. Здесь вы можете найти пакет геометрии для Java, который предоставляет некоторые полезные помощники. Ниже приведен их расчет для определения угла между двумя 3-мя точками. Надеюсь, вам это поможет:
public static double computeAngle (double[] p0, double[] p1, double[] p2)
{
double[] v0 = Geometry.createVector (p0, p1);
double[] v1 = Geometry.createVector (p0, p2);
double dotProduct = Geometry.computeDotProduct (v0, v1);
double length1 = Geometry.length (v0);
double length2 = Geometry.length (v1);
double denominator = length1 * length2;
double product = denominator != 0.0 ? dotProduct / denominator : 0.0;
double angle = Math.acos (product);
return angle;
}
Удачи!
Ответ 3
dx1 = x2-x1;
dy1 = y2-y1;
dx2 = x4-x3;
dy2 = y4-y3;
d = dx1*dx2 + dy1*dy2; // dot product of the 2 vectors
l2 = (dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2) // product of the squared lengths
angle = acos(d/sqrt(l2));
Точечное произведение 2 векторов равно косинусу угла времени длины обоих векторов. Это вычисляет произведение точек, делит на длину векторов и использует обратную косинусную функцию для восстановления угла.
Ответ 4
Возможно, мой подход для системы координат Android будет полезен для кого-то (используется для определения очков PointF класса Android)
/**
* Calculate angle between two lines with two given points
*
* @param A1 First point first line
* @param A2 Second point first line
* @param B1 First point second line
* @param B2 Second point second line
* @return Angle between two lines in degrees
*/
public static float angleBetween2Lines(PointF A1, PointF A2, PointF B1, PointF B2) {
float angle1 = (float) Math.atan2(A2.y - A1.y, A1.x - A2.x);
float angle2 = (float) Math.atan2(B2.y - B1.y, B1.x - B2.x);
float calculatedAngle = (float) Math.toDegrees(angle1 - angle2);
if (calculatedAngle < 0) calculatedAngle += 360;
return calculatedAngle;
}
Возвращает положительное значение в градусах для любого квадранта: 0 <= x < 360
Здесь вы можете посмотреть мой класс
Ответ 5
Формула для получения угла tan a = (slope1-slope2)/(1+slope1*slope2)
Вы используете:
tan a = (slope1 - slope2) / (1 - slope1 * slope2)
Итак, это должно быть:
double angle = Math.atan((slope1 - slope2) / (1 + slope1 * slope2));
Ответ 6
Во-первых, уверены ли вы, что скобки находятся в правильном порядке? Я думаю (может быть неправильно), это должно быть так:
double slope1 = (line1.getY1() - line1.getY2()) / (line1.getX1() - line1.getX2());
double slope2 = (line2.getY1() - line2.getY2()) / (line2.getX1() - line2.getX2());
Во-вторых, вы можете сделать две вещи для div на ноль: вы можете поймать исключение и обработать его
double angle;
try
{
angle = Math.atan((slope1 - slope2) / (1 - (slope1 * slope2)));
catch (DivideByZeroException dbze)
{
//Do something about it!
}
... или вы можете проверить, что ваши делители никогда не ноль, прежде чем пытаться выполнить операцию.
if ((1 - (slope1 * slope2))==0)
{
return /*something meaningful to avoid the div by zero*/
}
else
{
double angle = Math.atan((slope1 - slope2) / (1 - (slope1 * slope2)));
return angle;
}
Ответ 7
Проверьте этот код Python:
import math
def angle(x1,y1,x2,y2,x3,y3):
if (x1==x2==x3 or y1==y2==y3):
return 180
else:
dx1 = x2-x1
dy1 = y2-y1
dx2 = x3-x2
dy2 = y3-y2
if x1==x2:
a1=90
else:
m1=dy1/dx1
a1=math.degrees(math.atan(m1))
if x2==x3:
a2=90
else:
m2=dy2/dx2
a2=math.degrees(math.atan(m2))
angle = abs(a2-a1)
return angle
print angle(0,4,0,0,9,-6)
Ответ 8
dx1=x2-x1 ; dy1=y2-y1 ; dx2=x4-x3 ;dy2=y4-y3.
Angle(L1,L2)=pi()/2*((1+sign(dx1))* (1-sign(dy1^2))-(1+sign(dx2))*(1-sign(dy2^2)))
+pi()/4*((2+sign(dx1))*sign(dy1)-(2+sign(dx2))*sign(dy2))
+sign(dx1*dy1)*atan((abs(dx1)-abs(dy1))/(abs(dx1)+abs(dy1)))
-sign(dx2*dy2)*atan((abs(dx2)-abs(dy2))/(abs(dx2)+abs(dy2)))