web-dev-qa-db-fra.com

Calculer l'angle entre deux lignes sans avoir à calculer la pente? (Java)

J'ai deux lignes: L1 et L2. Je veux calculer l'angle entre les deux lignes. L1 a des points: {(x1, y1), (x2, y2)} et L2 a des points: {(x3, y3), (x4, y4)}.

Comment calculer l'angle formé entre ces deux lignes sans avoir à calculer les pentes? Le problème que je rencontre actuellement est que j'ai parfois des lignes horizontales (lignes le long de l'axe des x) et que la formule suivante échoue (exception de division par zéro): 

arctan((m1 - m2) / (1 - (m1 * m2)))

m1 et m2 sont les pentes des lignes 1 et 2 respectivement. Existe-t-il une formule/un algorithme permettant de calculer les angles entre les deux lignes sans jamais obtenir d’exceptions de division par zéro? Toute aide serait très appréciée.

Voici mon extrait de code:

// 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;
}

Merci.

33
jNoob

La fonction atan2 facilite le traitement de atan.

Il est déclaré en tant que double atan2(double y, double x) et convertit les coordonnées rectangulaires (x,y) en angle theta à partir des coordonnées polaires (r,theta)

Donc, je réécris votre code comme

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;
}
95
brainjam

Le produit ponctuel est probablement plus utile dans ce cas. Ici vous pouvez trouver un paquet de géométrie pour Java qui fournit des aides utiles. Vous trouverez ci-dessous leur calcul pour déterminer l'angle entre deux points tridimensionnels. Espérons que cela vous aidera à démarrer:

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;
}

Bonne chance!

13
Joseph Weissman
 dx1 = x2-x1; 
 dy1 = y2-y1; 
 dx2 = x4-x3; 
 dy2 = y4-y3; 

 d = dx1 * dx2 + dy1 * dy2; // produit scalaire des 2 vecteurs 
 l2 = (dx1 * dx1 + dy1 * dy1) * (dx2 * dx2 + dy2 * dy2) // produit des longueurs au carré 

 angle = acos (d /sqrt(l2));

Le produit scalaire de 2 vecteurs est égal au cosinus de l'angle, la longueur des deux vecteurs. Ceci calcule le produit scalaire, divise par la longueur des vecteurs et utilise la fonction cosinus inverse pour récupérer l'angle.

10
phkahler

Peut-être que mon approche du système de coordonnées Android sera utile à quelqu'un (classe Android PointF utilisée pour stocker des points)

/**
 * 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;
}

Il renvoie une valeur positive en degrés pour tout quadrant: 0 <= x <360

Vous pouvez commander mon utilitaire ici

7
Dehimb

La formule pour obtenir l'angle est tan a = (slope1-slope2)/(1+slope1*slope2)

Vous utilisez:

tan a = (slope1 - slope2) / (1 - slope1 * slope2)

Donc ça devrait être:

double angle = Math.atan((slope1 - slope2) / (1 + slope1 * slope2));
3
AliveStar

Vérifiez ce code 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)
0
Tirtha Chetry
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)))
0
theodore panagos

Tout d’abord, êtes-vous sûr que les crochets sont dans le bon ordre? Je pense (pourrait être faux) ce devrait être ceci:

   double slope1 = (line1.getY1() - line1.getY2()) / (line1.getX1() - line1.getX2());
   double slope2 = (line2.getY1() - line2.getY2()) / (line2.getX1() - line2.getX2());

Deuxièmement, il y a deux choses que vous pouvez faire pour la div par zéro: vous pouvez attraper l'exception et la gérer

double angle;
try
{
    angle = Math.atan((slope1 - slope2) / (1 - (slope1 * slope2)));
catch (DivideByZeroException dbze)
{
    //Do something about it!
}

... ou vous pouvez vérifier que vos diviseurs ne sont jamais à zéro avant vous tentez l'opération.

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;
 }