Comment puis-je vérifier si deux segments se croisent?

Comment puis-je vérifier si deux segments se croisent?

j'ai les données suivantes:

Segment1 [ {x1,y1}, {x2,y2} ]
Segment2 [ {x1,y1}, {x2,y2} ] 

j'ai besoin d'écrire un petit algorithme en python pour détecter si les 2 lignes d'intersection.

mise à jour:

alt text

60
demandé sur aneuryzm 2010-10-01 14:24:41

17 réponses

L'équation d'une ligne est:

f(x) = A*x + b = y

pour un segment, il est exactement le même, sauf que x est inclus sur un intervalle I.

si vous avez deux segments, définis comme suit:

Segment1 = {(X1, Y1), (X2, Y2)}
Segment2 = {(X3, Y3), (X4, Y4)}

l'abcisse Xa du point potentiel d'intersection (Xa,Ya) doit être contenu dans l'intervalle I1 et I2, défini comme suit:

I1 = [min(X1,X2), max(X1,X2)]
I2 = [min(X3,X4), max(X3,X4)]

et nous pourrions dire que Xa est inclus en:

Ia = [max( min(X1,X2), min(X3,X4) ),
      min( max(X1,X2), max(X3,X4) )]

Maintenant, nous devons vérifier que cet intervalle Ia existe :

if (max(X1,X2) < min(X3,X4))
    return false; // There is no mutual abcisses

donc, nous avons deux lignes de formule, et un intervalle mutuel. Vos formules de ligne sont:

f1(x) = A1*x + b1 = y
f2(x) = A2*x + b2 = y

comme nous avons obtenu deux points par segment, Nous sommes en mesure de déterminer A1, A2, b1 et b2:

A1 = (Y1-Y2)/(X1-X2) // Pay attention to not dividing by zero
A2 = (Y3-Y4)/(X3-X4) // Pay attention to not dividing by zero
b1 = Y1-A1*X1 = Y2-A1*X2
b2 = Y3-A2*X3 = Y4-A2*X4

si les segments sont parallèles, alors A1 = = A2:

if (A1 == A2)
    return false; // Parallel segments

Un point (Xa,Ya) debout sur les deux lignes doit vérifier les deux formules f1 et f2:

Ya = A1 * Xa + b1
Ya = A2 * Xa + b2
A1 * Xa + b1 = A2 * Xa + b2
Xa = (b2 - b1) / (A1 - A2) // Once again, pay attention to not dividing by zero

la dernière chose à faire est de vérifier que Xa est inclus dans Ia:

if ( (Xa < max( min(X1,X2), min(X3,X4) )) ||
     (Xa > min( max(X1,X2), max(X3,X4) )) )
    return false; // intersection is out of bound
else
    return true;

En plus de cela, vous pouvez vérifier au démarrage que deux des quatre fournies points ne sont pas égaux pour éviter tous ces tests.

37
répondu OMG_peanuts 2017-12-09 23:14:58

L'utilisateur @i_4_got pointe vers cette page avec une solution très efficace en Python. Je reproduis ici pour plus de commodité (car il m'aurait fait plaisir de l'avoir ici):

def ccw(A,B,C):
    return (C.y-A.y) * (B.x-A.x) > (B.y-A.y) * (C.x-A.x)

# Return true if line segments AB and CD intersect
def intersect(A,B,C,D):
    return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)
53
répondu Grumdrig 2012-04-03 16:19:22

vous ne devez pas calculer exactement les segments se croisent, mais seulement comprendre si ils se croisent du tout. Cela simplifiera la solution.

l'idée est de traiter un segment comme le" point d'ancrage " et de séparer le second segment en 2 points.

Maintenant, vous devez trouver la position relative de chaque point par rapport au segment "ancré" (OnLeft, OnRight ou Collinéar).

Après avoir fait ainsi pour les deux points, vérifier que l'un des points est OnLeft et l'autre est OnRight (ou peut-être inclure position Collinéaire, si vous souhaitez inclure impropre intersections ainsi).

vous devez alors répéter le processus avec les rôles d'ancrage et les segments séparés.

une intersection existe si, et seulement si, un des points est OnLeft et l'autre est OnRight. Voir ce lien pour une explication plus détaillée avec des images d'exemple pour chaque cas possible.

mettre en œuvre une telle méthode sera beaucoup plus facile que de réellement mettre en œuvre une méthode qui trouve le point d'intersection (étant donné les nombreux cas de coin que vous aurez à gérer ainsi).

mise à Jour

les fonctions suivantes devraient illustrer l'idée (source: géométrie computationnelle en C ).

Remarque: cet échantillon suppose l'utilisation d'entiers. Si vous utilisez plutôt une représentation en virgule flottante (ce qui pourrait évidemment compliquer les choses), alors vous devriez déterminer une valeur epsilon pour indiquer "égalité" (surtout pour l'évaluation IsCollinear ).

// points "a" and "b" forms the anchored segment.
// point "c" is the evaluated point
bool IsOnLeft(Point a, Point b, Point c)
{
     return Area2(a, b, c) > 0;
}

bool IsOnRight(Point a, Point b, Point c)
{
     return Area2(a, b, c) < 0;
}

bool IsCollinear(Point a, Point b, Point c)
{
     return Area2(a, b, c) == 0;
}

// calculates the triangle's size (formed by the "anchor" segment and additional point)
int Area2(Point a, Point b, Point c)
{
     return (b.X - a.X) * (c.Y - a.Y) -
            (c.X - a.X) * (b.Y - a.Y);
}

bien sûr, lors de l'utilisation de ces fonctions, il faut se rappeler de vérifier que chaque segment se trouve "entre" l'autre segment (puisqu'il s'agit de segments finis, et non de lignes infinies).

aussi, en utilisant cette fonction, vous pouvez comprendre si vous avez un bon ou impropre intersection.

  • Proper : il n'y a pas de points collinéaires. Les segments croisent chaque d'autres "de gauche à droite".
  • Impropre : un segment seulement "touche" le autre (au moins un des les points est collinéaire à la segment ancré).
24
répondu Liran 2014-05-10 17:01:39

supposons que les deux segments aient des Paramètres A, B et C,D. La façon numériquement robuste de déterminer l'intersection est de vérifier le signe des quatre déterminants:

| Ax-Cx  Bx-Cx |    | Ax-Dx  Bx-Dx |
| Ay-Cy  By-Cy |    | Ay-Dy  By-Dy |

| Cx-Ax  Dx-Ax |    | Cx-Bx  Dx-Bx |
| Cy-Ay  Dy-Ay |    | Cy-By  Dy-By |

pour l'intersection, chaque déterminant à gauche doit avoir le signe opposé de celui à droite, mais il n'est pas nécessaire qu'il y ait une relation entre les deux lignes. Vous êtes essentiellement vérifier chaque point d'un segment contre l'autre segment pour s'assurer qu'ils se trouvent sur les côtés opposés de la ligne définie par l'autre segment.

voir ici: http://www.cs.cmu.edu/~quake/robust.html

15
répondu Victor Liu 2010-10-01 18:47:58

basé sur Liran's et Grumdrig's excellentes réponses voici un code Python complet pour vérifier si les segments closed se croisent. Œuvres pour segments collinéaires, segments parallèles à l'axe Y, segments dégénérés (le diable est dans les détails). Suppose entier coordonnées. Les coordonnées des points flottants doivent être modifiées pour le test d'égalité des points.

def side(a,b,c):
    """ Returns a position of the point c relative to the line going through a and b
        Points a, b are expected to be different
    """
    d = (c[1]-a[1])*(b[0]-a[0]) - (b[1]-a[1])*(c[0]-a[0])
    return 1 if d > 0 else (-1 if d < 0 else 0)

def is_point_in_closed_segment(a, b, c):
    """ Returns True if c is inside closed segment, False otherwise.
        a, b, c are expected to be collinear
    """
    if a[0] < b[0]:
        return a[0] <= c[0] and c[0] <= b[0]
    if b[0] < a[0]:
        return b[0] <= c[0] and c[0] <= a[0]

    if a[1] < b[1]:
        return a[1] <= c[1] and c[1] <= b[1]
    if b[1] < a[1]:
        return b[1] <= c[1] and c[1] <= a[1]

    return a[0] == c[0] and a[1] == c[1]

#
def closed_segment_intersect(a,b,c,d):
    """ Verifies if closed segments a, b, c, d do intersect.
    """
    if a == b:
        return a == c or a == d
    if c == d:
        return c == a or c == b

    s1 = side(a,b,c)
    s2 = side(a,b,d)

    # All points are collinear
    if s1 == 0 and s2 == 0:
        return \
            is_point_in_closed_segment(a, b, c) or is_point_in_closed_segment(a, b, d) or \
            is_point_in_closed_segment(c, d, a) or is_point_in_closed_segment(c, d, b)

    # No touching and on the same side
    if s1 and s1 == s2:
        return False

    s1 = side(c,d,a)
    s2 = side(c,d,b)

    # No touching and on the same side
    if s1 and s1 == s2:
        return False

    return True
4
répondu dmitri 2017-05-23 12:34:50

vous avez deux segments de ligne. Définissez un segment par point final A et B et le second segment par point final C et D. Il y a une bonne astuce pour montrer qu'ils doivent se croiser, à l'intérieur des limites des segments. (Notez que les lignes elles-mêmes peuvent se croiser au-delà des limites des segments, vous devez donc être prudent. Le bon code surveillera également les lignes parallèles.)

le truc est de tester que les points A et B doivent se aligner sur les côtés opposés de la ligne CD, et que les points C et D doit se trouver sur les côtés opposés de la ligne AB.

comme c'est un devoir, Je ne te donnerai pas de solution explicite. Mais un test simple pour voir quel côté d'une ligne un point tombe sur, est d'utiliser un produit de point. Ainsi, pour une ligne CD donnée, calculez le vecteur normal de cette ligne (je l'appellerai N_C.) Maintenant, il suffit de tester les signes de ces deux résultats:

dot(A-C,N_C)

et

dot(B-C,N_C)

si ces résultats ont des signes opposés, alors A et b sont côtés opposés de la ligne CD. Maintenant, faites le même test pour L'autre ligne, AB. Il a un vecteur normal N_A. Comparer les signes de

dot(C-A,N_A)

et

dot(D-A,N_A)

je vous laisse décider comment calculer un vecteur normal. (En 2-d, c'est trivial, mais votre code se souciera-t-il de savoir si A et B sont des points distincts? De même, C et D sont-ils distincts?)

vous devez toujours vous soucier des segments de ligne qui se trouvent le long de la même ligne infinie, ou si un point tombe effectivement sur l'autre segment de ligne lui-même. Un bon code répondra à tous les problèmes possibles.

3
répondu 2010-10-01 14:43:23

voici le code C pour vérifier si deux points sont sur les côtés opposés du segment de ligne. En utilisant ce code, vous pouvez vérifier si deux segments se croisent aussi bien.

// true if points p1, p2 lie on the opposite sides of segment s1--s2
bool oppositeSide (Point2f s1, Point2f s2, Point2f p1, Point2f p2) {

//calculate normal to the segment
Point2f vec = s1-s2;
Point2f normal(vec.y, -vec.x); // no need to normalize

// vectors to the points
Point2f v1 = p1-s1;
Point2f v2 = p2-s1;

// compare signs of the projections of v1, v2 onto the normal
float proj1 = v1.dot(normal);
float proj2 = v2.dot(normal);
if (proj1==0 || proj2==0)
        cout<<"collinear points"<<endl;

return(SIGN(proj1) != SIGN(proj2));

}

3
répondu Vlad 2013-06-19 17:58:59

voici un autre code python pour vérifier si des segments fermés se croisent. C'est la version réécrite du code C++ dans http://www.cdn.geeksforgeeks.org/check-if-two-given-line-segments-intersect / . Cette mise en œuvre couvre tous les cas spéciaux (par exemple, tous les points colinear).

def on_segment(p, q, r):
    '''Given three colinear points p, q, r, the function checks if 
    point q lies on line segment "pr"
    '''
    if (q[0] <= max(p[0], r[0]) and q[0] >= min(p[0], r[0]) and
        q[1] <= max(p[1], r[1]) and q[1] >= min(p[1], r[1])):
        return True
    return False

def orientation(p, q, r):
    '''Find orientation of ordered triplet (p, q, r).
    The function returns following values
    0 --> p, q and r are colinear
    1 --> Clockwise
    2 --> Counterclockwise
    '''

    val = ((q[1] - p[1]) * (r[0] - q[0]) - 
            (q[0] - p[0]) * (r[1] - q[1]))
    if val == 0:
        return 0  # colinear
    elif val > 0:
        return 1   # clockwise
    else:
        return 2  # counter-clockwise

def do_intersect(p1, q1, p2, q2):
    '''Main function to check whether the closed line segments p1 - q1 and p2 
       - q2 intersect'''
    o1 = orientation(p1, q1, p2)
    o2 = orientation(p1, q1, q2)
    o3 = orientation(p2, q2, p1)
    o4 = orientation(p2, q2, q1)

    # General case
    if (o1 != o2 and o3 != o4):
        return True

    # Special Cases
    # p1, q1 and p2 are colinear and p2 lies on segment p1q1
    if (o1 == 0 and on_segment(p1, p2, q1)):
        return True

    # p1, q1 and p2 are colinear and q2 lies on segment p1q1
    if (o2 == 0 and on_segment(p1, q2, q1)):
        return True

    # p2, q2 and p1 are colinear and p1 lies on segment p2q2
    if (o3 == 0 and on_segment(p2, p1, q2)):
        return True

    # p2, q2 and q1 are colinear and q1 lies on segment p2q2
    if (o4 == 0 and on_segment(p2, q1, q2)):
        return True

    return False # Doesn't fall in any of the above cases

ci-dessous est une fonction d'essai pour vérifier qu'elle fonctionne.

import matplotlib.pyplot as plt

def test_intersect_func():
    p1 = (1, 1)
    q1 = (10, 1)
    p2 = (1, 2)
    q2 = (10, 2)
    fig, ax = plt.subplots()
    ax.plot([p1[0], q1[0]], [p1[1], q1[1]], 'x-')
    ax.plot([p2[0], q2[0]], [p2[1], q2[1]], 'x-')
    print(do_intersect(p1, q1, p2, q2))

    p1 = (10, 0)
    q1 = (0, 10)
    p2 = (0, 0)
    q2 = (10, 10)
    fig, ax = plt.subplots()
    ax.plot([p1[0], q1[0]], [p1[1], q1[1]], 'x-')
    ax.plot([p2[0], q2[0]], [p2[1], q2[1]], 'x-')
    print(do_intersect(p1, q1, p2, q2))

    p1 = (-5, -5)
    q1 = (0, 0)
    p2 = (1, 1)
    q2 = (10, 10)
    fig, ax = plt.subplots()
    ax.plot([p1[0], q1[0]], [p1[1], q1[1]], 'x-')
    ax.plot([p2[0], q2[0]], [p2[1], q2[1]], 'x-')
    print(do_intersect(p1, q1, p2, q2))

    p1 = (0, 0)
    q1 = (1, 1)
    p2 = (1, 1)
    q2 = (10, 10)
    fig, ax = plt.subplots()
    ax.plot([p1[0], q1[0]], [p1[1], q1[1]], 'x-')
    ax.plot([p2[0], q2[0]], [p2[1], q2[1]], 'x-')
    print(do_intersect(p1, q1, p2, q2))
2
répondu Fabian Ying 2018-04-27 10:18:57

pour les segments AB et CD, trouver la pente de CD

slope=(Dy-Cy)/(Dx-Cx)

étendre CD sur A et B, et prendre la distance à CD aller tout droit

dist1=slope*(Cx-Ax)+Ay-Cy
dist2=slope*(Dx-Ax)+Ay-Dy

vérifier s'ils sont sur des côtés opposés

return dist1*dist2<0
1
répondu Anonymous 2012-05-26 15:07:40

Puisque vous ne mentionnez pas que vous voulez trouver le point d'intersection de la ligne, le problème devient plus simple à résoudre. Si vous avez besoin du point d'intersection, alors la réponse par OMG_peanuts est une approche plus rapide. Cependant, si vous voulez simplement savoir si les lignes se croisent ou non, vous pouvez le faire en utilisant l'équation de la ligne (ax + by + c = 0). L'approche est la suivante:

  1. commençons par deux segments de ligne: segment 1 et segment 2.

    segment1 = [[x1,y1], [x2,y2]]
    segment2 = [[x3,y3], [x4,y4]]
    
  2. vérifier si les deux segments de ligne ne sont pas des segments de longueur zéro et des segments distincts.

  3. à partir de là, je suppose que les deux segments sont de longueur non nulle et distincts. Pour chaque segment de ligne, calculer la pente de la ligne, puis obtenir l'équation d'une droite sous la forme ax + by + c = 0. Maintenant, calculez la valeur de f = ax + par + c pour les deux points autre segment de ligne (répétez cette procédure pour l'autre segment de ligne).

    a2 = (y3-y4)/(x3-x4);
    b1 = -1;
    b2 = -1;
    c1 = y1 - a1*x1;
    c2 = y3 - a2*x3;
    // using the sign function from numpy
    f1_1 = sign(a1*x3 + b1*y3 + c1);
    f1_2 = sign(a1*x4 + b1*y4 + c1);
    f2_1 = sign(a2*x1 + b2*y1 + c2);
    f2_2 = sign(a2*x2 + b2*y2 + c2);
    
  4. il ne reste plus que les différents cas. Si f = 0 pour un point quelconque, alors les deux lignes se touchent en un point. Si f1_1 et f1_2 sont égaux ou f2_1 et f2_2 sont égales, alors les lignes ne se croisent pas. Si f1_1 et f1_2 sont inégaux et f2_1 et f2_2 sont inégaux, alors les segments de ligne se croisent. Selon que vous voulez considérer le lignes qui se touchent comme "se croisant" ou non, vous pouvez adapter vos conditions.

1
répondu achyuthan_jr 2017-05-23 11:55:09

j'ai pensé que j'apporterais une solution rapide:

struct Pt {
    var x: Double
    var y: Double
}

struct LineSegment {
    var p1: Pt
    var p2: Pt
}

func doLineSegmentsIntersect(ls1: LineSegment, ls2: LineSegment) -> Bool {

    if (ls1.p2.x-ls1.p1.x == 0) { //handle vertical segment1
        if (ls2.p2.x-ls2.p1.x == 0) {
            //both lines are vertical and parallel
            return false
        }

        let x = ls1.p1.x

        let slope2 = (ls2.p2.y-ls2.p1.y)/(ls2.p2.x-ls2.p1.x)
        let c2 = ls2.p1.y-slope2*ls2.p1.x

        let y = x*slope2+c2 // y intersection point

        return (y > ls1.p1.y && x < ls1.p2.y) || (y > ls1.p2.y && y < ls1.p1.y) // check if y is between y1,y2 in segment1
    }

    if (ls2.p2.x-ls2.p1.x == 0) { //handle vertical segment2

        let x = ls2.p1.x

        let slope1 = (ls1.p2.y-ls1.p1.y)/(ls1.p2.x-ls1.p1.x)
        let c1 = ls1.p1.y-slope1*ls1.p1.x

        let y = x*slope1+c1 // y intersection point

        return (y > ls2.p1.y && x < ls2.p2.y) || (y > ls2.p2.y && y < ls2.p1.y) // validate that y is between y1,y2 in segment2

    }

    let slope1 = (ls1.p2.y-ls1.p1.y)/(ls1.p2.x-ls1.p1.x)
    let slope2 = (ls2.p2.y-ls2.p1.y)/(ls2.p2.x-ls2.p1.x)

    if (slope1 == slope2) { //segments are parallel
        return false
    }

    let c1 = ls1.p1.y-slope1*ls1.p1.x
    let c2 = ls2.p1.y-slope2*ls2.p1.x

    let x = (c2-c1)/(slope1-slope2)

    return (((x > ls1.p1.x && x < ls1.p2.x) || (x > ls1.p2.x && x < ls1.p1.x)) &&
        ((x > ls2.p1.x && x < ls2.p2.x) || (x > ls2.p2.x && x < ls2.p1.x)))
    //validate that x is between x1,x2 in both segments

}
1
répondu Matej Ukmar 2017-11-12 18:51:10

nous pouvons également résoudre ce en utilisant des vecteurs.

définissons les segments comme [start, end] . Étant donné que deux de ces segments [A, B] et [C, D] ont une longueur non nulle, nous pouvons choisir l'un des paramètres à utiliser comme point de référence afin d'obtenir trois vecteurs:

x = 0
y = 1
p = A-C = [C[x]-A[x], C[y]-A[y]]
q = B-A = [B[x]-A[x], B[y]-A[y]]
r = D-C = [D[x]-C[x], D[y]-C[y]]

de là, nous pouvons chercher une intersection en calculant t et u dans p + t*r = u*q . Après avoir joué avec l'équation un peu, nous obtenons:

t = (q[y]*p[x] - q[x]*p[y])/(q[x]*r[y] - q[y]*r[x])
u = (p[x] + t*r[x])/q[x]

ainsi, la fonction est:

def intersects(a, b):
    p = [b[0][0]-a[0][0], b[0][1]-a[0][1]]
    q = [a[1][0]-a[0][0], a[1][1]-a[0][1]]
    r = [b[1][0]-b[0][0], b[1][1]-b[0][1]]

    t = (q[1]*p[0] - q[0]*p[1])/(q[0]*r[1] - q[1]*r[0]) \
        if (q[0]*r[1] - q[1]*r[0]) != 0 \
        else (q[1]*p[0] - q[0]*p[1])
    u = (p[0] + t*r[0])/q[0] \
        if q[0] != 0 \
        else (p[1] + t*r[1])/q[1]

    return t >= 0 and t <= 1 and u >= 0 and u <= 1
1
répondu Rogem 2017-11-22 19:38:53

si vos données définissent une ligne, vous n'avez qu'à prouver qu'elles ne sont pas parallèles. Pour ce faire, vous pouvez calculer

alpha = float(y2 - y1) / (x2 - x1).

si ce coefficient est égal pour la ligne 1 et la ligne 2, cela signifie que la ligne est parallèle. Sinon, ça veut dire qu'ils vont se croiser.

S'ils sont parallèles vous devez alors prouver qu'ils ne sont pas les mêmes. Pour cela, vous calculez

beta = y1 - alpha*x1

si beta est le même pour la ligne 1 et la ligne 2, Il signifie que vous ligne se croisent comme ils sont "égaux

si ce sont des segments, vous devez quand même calculer alpha et beta comme décrit ci-dessus pour chaque ligne. Ensuite, vous devez vérifier que (beta1-beta2) / (alpha1-alpha2) est supérieur à Min( x1_line1, x2_line1) et inférieur à Max (x1_line1, x2_line1)

0
répondu PierrOz 2010-10-01 10:40:11

calculez le point d'intersection des lignes posées sur vos segments (cela signifie essentiellement de résoudre un système d'équation linéaire), puis vérifiez s'il est entre les points de départ et de fin de vos segments.

0
répondu kosii 2010-10-01 12:54:27

C'est ce que j'ai pour AS3, Je ne sais pas grand chose sur python mais le concept est là

    public function getIntersectingPointF($A:Point, $B:Point, $C:Point, $D:Point):Number {
        var A:Point = $A.clone();
        var B:Point = $B.clone();
        var C:Point = $C.clone();
        var D:Point = $D.clone();
        var f_ab:Number = (D.x - C.x) * (A.y - C.y) - (D.y - C.y) * (A.x - C.x);

        // are lines parallel
        if (f_ab == 0) { return Infinity };

        var f_cd:Number = (B.x - A.x) * (A.y - C.y) - (B.y - A.y) * (A.x - C.x);
        var f_d:Number = (D.y - C.y) * (B.x - A.x) - (D.x - C.x) * (B.y - A.y);
        var f1:Number = f_ab/f_d
        var f2:Number = f_cd / f_d
        if (f1 == Infinity || f1 <= 0 || f1 >= 1) { return Infinity };
        if (f2 == Infinity || f2 <= 0 || f2 >= 1) { return Infinity };
        return f1;
    }

    public function getIntersectingPoint($A:Point, $B:Point, $C:Point, $D:Point):Point
    {
        var f:Number = getIntersectingPointF($A, $B, $C, $D);
        if (f == Infinity || f <= 0 || f >= 1) { return null };

        var retPoint:Point = Point.interpolate($A, $B, 1 - f);
        return retPoint.clone();
    }
0
répondu Daniel 2010-10-01 19:05:07

implémenté en JAVA. Toutefois, il semble qu'il ne fonctionne pas pour les lignes co-linéaires (aka segments de ligne qui existent dans l'autre L1 (0,0) (10,10) L2(1,1) (2,2)

public class TestCode
{

  public class Point
  {
    public double x = 0;
    public double y = 0;
    public Point(){}
  }

  public class Line
  {
    public Point p1, p2;
    public Line( double x1, double y1, double x2, double y2) 
    {
      p1 = new Point();
      p2 = new Point();
      p1.x = x1;
      p1.y = y1;
      p2.x = x2;
      p2.y = y2;
    }
  }

  //line segments
  private static Line s1;
  private static Line s2;

  public TestCode()
  {
    s1 = new Line(0,0,0,10);
    s2 = new Line(-1,0,0,10);
  }

  public TestCode(double x1, double y1, 
    double x2, double y2,
    double x3, double y3,
    double x4, double y4)
  {
    s1 = new Line(x1,y1, x2,y2);
    s2 = new Line(x3,y3, x4,y4);
  }

  public static void main(String args[])
  {
     TestCode code  = null;
////////////////////////////
     code = new TestCode(0,0,0,10,
                         0,1,0,5);
     if( intersect(code) )
     { System.out.println( "OK COLINEAR: INTERSECTS" ); }
     else
     { System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,0,10,
                         0,1,0,10);
     if( intersect(code) )
     { System.out.println( "OK COLINEAR: INTERSECTS" ); }
     else
     { System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,10,0,
                         5,0,15,0);
     if( intersect(code) )
     { System.out.println( "OK COLINEAR: INTERSECTS" ); }
     else
     { System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,10,0,
                         0,0,15,0);
     if( intersect(code) )
     { System.out.println( "OK COLINEAR: INTERSECTS" ); }
     else
     { System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }

////////////////////////////
     code = new TestCode(0,0,10,10,
                         1,1,5,5);
     if( intersect(code) )
     { System.out.println( "OK COLINEAR: INTERSECTS" ); }
     else
     { System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,0,10,
                         -1,-1,0,10);
     if( intersect(code) )
     { System.out.println( "OK SLOPE END: INTERSECTS" ); }
     else
     { System.out.println( "ERROR SLOPE END: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(-10,-10,10,10,
                         -10,10,10,-10);
     if( intersect(code) )
     { System.out.println( "OK SLOPE Intersect(0,0): INTERSECTS" ); }
     else
     { System.out.println( "ERROR SLOPE Intersect(0,0): DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(-10,-10,10,10,
                         -3,-2,50,-2);
     if( intersect(code) )
     { System.out.println( "OK SLOPE Line2 VERTIAL: INTERSECTS" ); }
     else
     { System.out.println( "ERROR SLOPE Line2 VERTICAL: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(-10,-10,10,10,
                         50,-2,-3,-2);
     if( intersect(code) )
     { System.out.println( "OK SLOPE Line2 (reversed) VERTIAL: INTERSECTS" ); }
     else
     { System.out.println( "ERROR SLOPE Line2 (reversed) VERTICAL: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,0,10,
                         1,0,1,10);
     if( intersect(code) )
     { System.out.println( "ERROR PARALLEL VERTICAL: INTERSECTS" ); }
     else
     { System.out.println( "OK PARALLEL VERTICAL: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,2,10,2,
                         0,10,10,10);
     if( intersect(code) )
     { System.out.println( "ERROR PARALLEL HORIZONTAL: INTERSECTS" ); }
     else
     { System.out.println( "OK PARALLEL HORIZONTAL: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,10,5,13.75,
                         0,18.75,10,15);
     if( intersect(code) )
     { System.out.println( "ERROR PARALLEL SLOPE=.75: INTERSECTS" ); }
     else
     { System.out.println( "OK PARALLEL SLOPE=.75: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,1,1,
                         2,-1,2,10);
     if( intersect(code) )
     { System.out.println( "ERROR SEPERATE SEGMENTS: INTERSECTS" ); }
     else
     { System.out.println( "OK SEPERATE SEGMENTS: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,1,1,
                         -1,-10,-5,10);
     if( intersect(code) )
     { System.out.println( "ERROR SEPERATE SEGMENTS 2: INTERSECTS" ); }
     else
     { System.out.println( "OK SEPERATE SEGMENTS 2: DO NOT INTERSECT" ); }
  }

  public static boolean intersect( TestCode code )
  {
    return intersect( code.s1, code.s2);
  }

  public static boolean intersect( Line line1, Line line2 )
  {
    double i1min = Math.min(line1.p1.x, line1.p2.x);
    double i1max = Math.max(line1.p1.x, line1.p2.x);
    double i2min = Math.min(line2.p1.x, line2.p2.x);
    double i2max = Math.max(line2.p1.x, line2.p2.x);

    double iamax = Math.max(i1min, i2min);
    double iamin = Math.min(i1max, i2max);

    if( Math.max(line1.p1.x, line1.p2.x) < Math.min(line2.p1.x, line2.p2.x) )
      return false;

    double m1 = (line1.p2.y - line1.p1.y) / (line1.p2.x - line1.p1.x );
    double m2 = (line2.p2.y - line2.p1.y) / (line2.p2.x - line2.p1.x );

    if( m1 == m2 )
        return false;

    //b1 = line1[0][1] - m1 * line1[0][0]
    //b2 = line2[0][1] - m2 * line2[0][0]
    double b1 = line1.p1.y - m1 * line1.p1.x;
    double b2 = line2.p1.y - m2 * line2.p1.x;
    double x1 = (b2 - b1) / (m1 - m2);
    if( (x1 < Math.max(i1min, i2min)) || (x1 > Math.min(i1max, i2max)) )
        return false;
    return true;
  }
}

sortie jusqu'à présent est

ERROR COLINEAR: DO NOT INTERSECT
ERROR COLINEAR: DO NOT INTERSECT
ERROR COLINEAR: DO NOT INTERSECT
ERROR COLINEAR: DO NOT INTERSECT
ERROR COLINEAR: DO NOT INTERSECT
OK SLOPE END: INTERSECTS
OK SLOPE Intersect(0,0): INTERSECTS
OK SLOPE Line2 VERTIAL: INTERSECTS
OK SLOPE Line2 (reversed) VERTIAL: INTERSECTS
OK PARALLEL VERTICAL: DO NOT INTERSECT
OK PARALLEL HORIZONTAL: DO NOT INTERSECT
OK PARALLEL SLOPE=.75: DO NOT INTERSECT
OK SEPERATE SEGMENTS: DO NOT INTERSECT
OK SEPERATE SEGMENTS 2: DO NOT INTERSECT
0
répondu Wanderer 2013-05-07 21:58:35

résolu mais pourquoi pas avec python... :)

def islineintersect(line1, line2):
    i1 = [min(line1[0][0], line1[1][0]), max(line1[0][0], line1[1][0])]
    i2 = [min(line2[0][0], line2[1][0]), max(line2[0][0], line2[1][0])]
    ia = [max(i1[0], i2[0]), min(i1[1], i2[1])]
    if max(line1[0][0], line1[1][0]) < min(line2[0][0], line2[1][0]):
        return False
    m1 = (line1[1][1] - line1[0][1]) * 1. / (line1[1][0] - line1[0][0]) * 1.
    m2 = (line2[1][1] - line2[0][1]) * 1. / (line2[1][0] - line2[0][0]) * 1.
    if m1 == m2:
        return False
    b1 = line1[0][1] - m1 * line1[0][0]
    b2 = line2[0][1] - m2 * line2[0][0]
    x1 = (b2 - b1) / (m1 - m2)
    if (x1 < max(i1[0], i2[0])) or (x1 > min(i1[1], i2[1])):
        return False
    return True

:

print islineintersect([(15, 20), (100, 200)], [(210, 5), (23, 119)])

sortie:

True

et ceci:

print islineintersect([(15, 20), (100, 200)], [(-1, -5), (-5, -5)])

sortie:

False
-2
répondu Love Sharma 2013-02-08 08:33:23