Вычислить угол между двумя линиями без необходимости вычислять наклон? (Джава)
У меня есть две линии: 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;
}
Благодарю.
8 ответов
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;
}
Точечный продукт, вероятно, более полезен в этом случае. Здесь вы можете найти геометрический пакет для Java, который предоставляет несколько полезных помощников. Ниже приведен их расчет для определения угла между двумя трехмерными точками. Надеюсь, это поможет вам начать:
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;
}
Удачи!
дх1 = х2-х1; dy1 = y2-y1; дх2 = х4-х3; dy2 = y4-y3; d = dx1 * dx2 + dy1 * dy2; // скалярное произведение двух векторов l2 = (dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2) // произведение квадратов длин угол = acos(d/sqrt(l2));
Точечное произведение двух векторов равно косинусу угла времени на длину обоих векторов. Это вычисляет скалярное произведение, делит на длину векторов и использует функцию обратного косинуса для восстановления угла.
Может быть, мой подход к системе координат Android будет кому-то полезен (для хранения точек использовался класс Android PointF)
/**
* 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
Вы можете проверить мой класс полезности здесь
Формула для получения угла tan a = (slope1-slope2)/(1+slope1*slope2)
Ты используешь:
tan a = (slope1 - slope2) / (1 - slope1 * slope2)
Так и должно быть:
double angle = Math.atan((slope1 - slope2) / (1 + slope1 * slope2));
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)))
Проверьте этот код 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)
Во-первых, вы уверены, что скобки в правильном порядке? Я думаю (может быть неправильно) это должно быть так:
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;
}