Làm cách nào để kiểm tra xem hai đoạn có giao nhau không?


Câu trả lời:


63

Phương trình của một đường là:

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

Đối với một đoạn, nó hoàn toàn giống nhau, ngoại trừ x nằm trên một khoảng I.

Nếu bạn có hai phân đoạn, được xác định như sau:

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

Xa abcisse của điểm giao nhau (Xa, Ya) phải được chứa trong cả khoảng I1 và I2, được xác định như sau:

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

Và chúng ta có thể nói rằng Xa được bao gồm trong:

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

Bây giờ, chúng ta cần kiểm tra xem khoảng Ia này có tồn tại không:

if (max(X1,X2) < min(X3,X4)):
    return False  # There is no mutual abcisses

Vì vậy, chúng ta có công thức hai dòng và một khoảng tương hỗ. Công thức đường của bạn là:

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

Khi chúng tôi có hai điểm theo phân đoạn, chúng tôi có thể xác định A1, A2, b1 và 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

Nếu các đoạn song song thì A1 == A2:

if (A1 == A2):
    return False  # Parallel segments

Một điểm (Xa, Ya) đứng trên cả hai đường thẳng phải xác định cả hai công thức f1 và 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

Điều cuối cùng cần làm là kiểm tra xem Xa có được đưa vào Ia không:

if ( (Xa < max( min(X1,X2), min(X3,X4) )) or
     (Xa > min( max(X1,X2), max(X3,X4) )) ):
    return False  # intersection is out of bound
else:
    return True

Ngoài ra, bạn có thể kiểm tra khi khởi động rằng hai trong bốn điểm được cung cấp không bằng nhau để tránh tất cả các thử nghiệm đó.


1
Các phân đoạn, chúng là các phân đoạn, xin lỗi. Bạn có thể cập nhật câu trả lời của mình cho các phân đoạn đã cho không?
aneuryzm

13
Điều này không quá phức tạp, tôi đã viết rất nhiều bước trung gian (không cần thiết?) Trong mục đích hiểu. Các điểm chính cần thực hiện chỉ là: Kiểm tra sự tồn tại của khoảng tương hỗ, tính A1, A2, b1, b2 và Xa, sau đó kiểm tra xem Xa có nằm trong khoảng tương hỗ hay không. Đó là tất cả :)
OMG_peanuts

3
A1 - A2 sẽ không bao giờ bằng 0 vì if (A1 == A2) sẽ trả về trước phép tính này trong trường hợp đó.
inkredibl 22/10/12

3
nếu A1 == A2 và b1 == b2, các đoạn nằm trên đầu nhau và có vô số giao điểm
lynxoid

5
Công thức A1 * x + b1 = y không xử lý các đường thẳng đứng, do đó các phân đoạn dọc nên được xử lý riêng biệt với phương pháp này.
dmitri

77

Người dùng @ i_4_got trỏ đến trang này với một giải pháp rất hiệu quả bằng Python. Tôi sao chép nó ở đây để thuận tiện (vì nó sẽ khiến tôi rất vui nếu có nó ở đây):

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)

8
Rất đơn giản và thanh lịch, nhưng nó không giải quyết tốt vấn đề thuộc tính, và do đó cần nhiều mã hơn cho mục đích đó.
charles

7
Đối với một giải pháp mà cũng xử lý séc cộng tuyến ra geeksforgeeks.org/check-if-two-given-line-segments-intersect
Zsolt Safrany

Thích giải pháp này. Rất đơn giản và ngắn gọn! Tôi đã tạo một chương trình wxPython để vẽ một đường thẳng và xem nó có giao nhau với một đường thẳng khác hay không. Tôi không thể đặt nó ở đây vì vậy nó ở đâu đó bên dưới bình luận này.
user1766438

33

Bạn không cần phải tính toán chính xác vị trí các đoạn cắt nhau mà chỉ cần hiểu liệu chúng có giao nhau hay không. Điều này sẽ đơn giản hóa giải pháp.

Ý tưởng là coi một phân đoạn là "mỏ neo" và tách phân đoạn thứ hai thành 2 điểm.
Bây giờ, bạn sẽ phải tìm vị trí tương đối của mỗi điểm đối với đoạn "được neo" (OnLeft, OnRight hoặc Collinear).
Sau khi làm như vậy cho cả hai điểm, hãy kiểm tra xem một trong các điểm là OnLeft và điểm còn lại là OnRight (hoặc có thể bao gồm vị trí Collinear, nếu bạn muốn bao gồm cả các giao điểm không phù hợp ).

Sau đó, bạn phải lặp lại quy trình với vai trò của các đoạn neo và các phân đoạn được tách biệt.

Một giao lộ tồn tại nếu và chỉ khi, một trong các điểm là OnLeft và điểm kia là OnRight. Xem liên kết này để được giải thích chi tiết hơn với hình ảnh ví dụ cho từng trường hợp có thể.

Việc thực hiện phương pháp này sẽ dễ dàng hơn nhiều so với việc thực hiện một phương pháp tìm giao điểm (với nhiều trường hợp góc mà bạn cũng sẽ phải xử lý).

Cập nhật

Các chức năng sau đây sẽ minh họa cho ý tưởng (nguồn: Hình học tính toán trong C ).
Lưu ý: Mẫu này giả định việc sử dụng số nguyên. Nếu bạn đang sử dụng một số biểu diễn dấu phẩy động thay thế (điều này rõ ràng có thể làm phức tạp mọi thứ), thì bạn nên xác định một số giá trị epsilon để chỉ ra "bình đẳng" (chủ yếu là để IsCollinearđánh giá).

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

Tất nhiên, khi sử dụng các hàm này, người ta phải nhớ kiểm tra xem mỗi đoạn có nằm "giữa" đoạn kia không (vì đây là các đoạn hữu hạn chứ không phải dòng vô hạn).

Ngoài ra, bằng cách sử dụng các hàm này, bạn có thể hiểu liệu bạn đã có một giao lộ thích hợp hay không .

  • Đúng : Không có điểm thẳng hàng. Các phân đoạn chéo nhau "từ bên này sang bên kia".
  • Không đúng : Một phân đoạn chỉ "chạm" vào phân đoạn kia (ít nhất một trong các điểm thẳng hàng với phân đoạn được cố định).

+1 Khá nhiều ý tưởng của tôi. Nếu bạn chỉ nghĩ về vị trí của các điểm trong mối quan hệ với nhau, bạn có thể quyết định xem các đoạn của chúng có phải cắt nhau hay không mà không cần tính toán gì cả.
Jochen Ritzel

và @ THC4k Uhm, nó thực sự không rõ ràng. Ví dụ FOr kiểm tra hình ảnh tôi đã thêm vào câu hỏi: 2 điểm là "OnLeft" và "OnRight" nhưng 2 đoạn không giao nhau.
aneuryzm

@Patrick, thực ra là không. Tùy thuộc vào phân đoạn nào là "neo", thì cả hai điểm đều là OnLeft hoặc OnRight trong trường hợp này. (Xem câu trả lời cập nhật của tôi).
Liran

1
+1 Tôi đã thấy hàng tá câu trả lời cho vấn đề này, nhưng đây là câu trả lời rõ ràng nhất, đơn giản nhất và hiệu quả nhất mà tôi đã thấy. :)
Miguel

16

Giả sử hai đoạn có điểm cuối là A, B và C, D. Cách mạnh mẽ về mặt số để xác định giao lộ là kiểm tra dấu hiệu của bốn yếu tố quyết định:

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

Đối với giao điểm, mỗi định thức ở bên trái phải có dấu hiệu ngược lại với dấu của định thức bên phải, nhưng không cần có bất kỳ mối quan hệ nào giữa hai đường. Về cơ bản, bạn đang kiểm tra từng điểm của một đoạn so với đoạn kia để đảm bảo rằng chúng nằm trên các phía đối diện của đường được xác định bởi đoạn kia.

Xem tại đây: http://www.cs.cmu.edu/~quake/robust.html


nó có hoạt động đối với các giao lộ không thích hợp, tức là khi giao điểm nằm trên một đoạn thẳng không?
Sayam Qazi

@SayamQazi Có vẻ như không thể giao nhau nếu bạn đang đi qua điểm cuối của đoạn thẳng. Đối với trường hợp bạn đang ở trên đoạn đường: Tôi cho rằng nó sẽ là so sánh 0 vs 1 / -1, vì vậy nó sẽ không phát hiện ra giao lộ.
Warty

1
Nhân tiện, để giải thích điều này: mỗi yếu tố quyết định đang tính toán tích chéo của hai điểm cuối vectơ của đoạn thẳng. Ví dụ trên cùng bên trái là CA x CB so với trên cùng bên phải DA x DB. Về cơ bản, điều này kiểm tra xem đỉnh nằm ở phía nào (xung nhịp). Vẫn đang cố gắng tìm ra cách nó hoạt động đối với các đoạn đường không kéo dài vô hạn.
Warty

7

Kiểm tra xem các đoạn thẳng có giao nhau hay không rất dễ dàng với thư viện Shapely bằng intersectsphương pháp:

from shapely.geometry import LineString

line = LineString([(0, 0), (1, 1)])
other = LineString([(0, 1), (1, 0)])
print(line.intersects(other))
# True

nhập mô tả hình ảnh ở đây

line = LineString([(0, 0), (1, 1)])
other = LineString([(0, 1), (1, 2)])
print(line.intersects(other))
# False

nhập mô tả hình ảnh ở đây


6

Dựa trên câu trả lời tuyệt vời của LiranGrumdrig, đây là một mã Python hoàn chỉnh để xác minh xem các phân đoạn đã đóng có giao nhau hay không. Hoạt động đối với các phân đoạn thẳng hàng, phân đoạn song song với trục Y, phân đoạn suy biến (chi tiết là ác quỷ). Giả sử tọa độ số nguyên. Tọa độ dấu chấm động yêu cầu sửa đổi để kiểm tra bình đẳng điểm.

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

"Phân đoạn đã đóng" chính xác nghĩa là gì?
Sam

@Sam Phân đoạn đã đóng chứa các điểm cuối của nó. Ví dụ một đoạn khép kín của các điểm từ R sẽ là [0, 1] (0 <= x <= 1) như trái ngược với nói] 0, 1] (0 <x <= 1)
Dmitri

5

Đây là một giải pháp sử dụng các sản phẩm chấm:

# assumes line segments are stored in the format [(x0,y0),(x1,y1)]
def intersects(s0,s1):
    dx0 = s0[1][0]-s0[0][0]
    dx1 = s1[1][0]-s1[0][0]
    dy0 = s0[1][1]-s0[0][1]
    dy1 = s1[1][1]-s1[0][1]
    p0 = dy1*(s1[1][0]-s0[0][0]) - dx1*(s1[1][1]-s0[0][1])
    p1 = dy1*(s1[1][0]-s0[1][0]) - dx1*(s1[1][1]-s0[1][1])
    p2 = dy0*(s0[1][0]-s1[0][0]) - dx0*(s0[1][1]-s1[0][1])
    p3 = dy0*(s0[1][0]-s1[1][0]) - dx0*(s0[1][1]-s1[1][1])
    return (p0*p1<=0) & (p2*p3<=0)

Đây là hình ảnh trực quan trong Desmos: Giao lộ đoạn đường


Điều này thật tuyệt vời, và tôi đã quên mất Desmos - nó hoàn hảo cho vấn đề này! Cảm ơn!
ponadto

Thích giải pháp của bạn nhưng có vẻ như nó không thành công nếu hai đoạn đường thẳng hàng
H. Pope

Rất đẹp. Đối với bất kỳ ai khác chuyển tệp này sang một ngôn ngữ khác, hãy đảm bảo sử dụng float hoặc int64 vì int32 sẽ tràn khá nhanh trên các số nhỏ hơn 1280x720
anh chàng kia

4

Bạn có hai đoạn thẳng. Xác định một phân đoạn theo điểm cuối A & B và phân đoạn thứ hai theo điểm cuối C & D. Có một mẹo hay để chỉ ra rằng chúng phải giao nhau, TRONG VÒNG giới hạn của các đoạn. (Lưu ý rằng bản thân các đường có thể giao nhau ngoài giới hạn của các phân đoạn, vì vậy bạn phải cẩn thận. Mã tốt cũng sẽ để ý các đường song song.)

Bí quyết là kiểm tra xem các điểm A và B phải nằm trên các cạnh đối diện của đoạn thẳng CD, VÀ rằng các điểm C và D phải nằm trên các cạnh đối diện của đoạn thẳng AB.

Vì đây là bài tập về nhà, tôi sẽ không cung cấp cho bạn một giải pháp rõ ràng. Nhưng một bài kiểm tra đơn giản để xem một điểm nằm ở phía nào của đường thẳng, là sử dụng sản phẩm chấm. Do đó, đối với một CD dòng nhất định, hãy tính vectơ pháp tuyến cho dòng đó (tôi sẽ gọi nó là N_C.) Bây giờ, chỉ cần kiểm tra các dấu hiệu của hai kết quả sau:

dot(A-C,N_C)

dot(B-C,N_C)

Nếu các kết quả đó có dấu trái dấu thì A và B là hai phía đối nhau của đoạn thẳng CD. Bây giờ hãy làm bài kiểm tra tương tự cho đoạn thẳng còn lại, AB. Nó có vector pháp tuyến N_A. So sánh các dấu hiệu của

dot(C-A,N_A)

dot(D-A,N_A)

Tôi sẽ giao nó cho bạn để tìm ra cách tính một vector thông thường. (Trong chế độ 2-d, điều đó thật tầm thường, nhưng mã của bạn sẽ lo lắng về việc liệu A và B có phải là điểm phân biệt hay không? Tương tự, C và D có khác biệt không?)

Bạn vẫn cần phải lo lắng về các đoạn thẳng nằm dọc theo cùng một đường thẳng vô hạn hoặc nếu một điểm thực sự nằm trên chính đoạn thẳng kia. Mã tốt sẽ phục vụ cho mọi vấn đề có thể xảy ra.


3

Đây là mã C để kiểm tra xem hai điểm có nằm ở phía đối diện của đoạn thẳng hay không. Sử dụng mã này, bạn có thể kiểm tra xem hai đoạn có cắt nhau hay không.

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

Đây là một mã python khác để kiểm tra xem các phân đoạn đã đóng có giao nhau hay không. Đây là phiên bản được viết lại của mã C ++ trong http://www.cdn.geeksforgeeks.org/check-if-two-given-line-searies-intersect/ . Việc triển khai này bao gồm tất cả các trường hợp đặc biệt (ví dụ: cột tất cả các điểm).

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

Dưới đây là một chức năng kiểm tra để xác minh rằng nó hoạt động.

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))

1
closed_segment_intersect()từ mã kiểm tra không được xác định.
hhquark

1
@hhquark Cảm ơn bạn. Bây giờ tôi đã xóa những dòng này. Tôi đã bao gồm những dòng này trong khi thử nghiệm để kiểm tra xem việc triển khai của tôi có đồng ý với việc triển khai từ một câu trả lời khác không ( tôi nghĩ là stackoverflow.com/a/18524383/7474256 ).
Fabian Ying

1

cho đoạn AB và CD, tìm hệ số góc của CD

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

kéo dài CD qua A và B, và đưa khoảng cách CD đi thẳng lên

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

kiểm tra xem chúng có ở hai phía đối diện nhau không

return dist1*dist2<0

Bạn có chắc chắn về các công thức? Vì không sử dụng tọa độ của B nên làm thế nào có thể tìm được giao điểm của AB và CD mà không xét cả 4 đỉnh?
mac13k,

1
Tôi nghĩ cần có: dist2 = dốc * (Dx-Bx) + By-Dy
mac13k

1

Vì bạn không đề cập rằng bạn muốn tìm giao điểm của đoạn thẳng, bài toán trở nên đơn giản hơn để giải quyết. Nếu bạn cần điểm giao nhau, thì câu trả lời của OMG_peanuts là cách tiếp cận nhanh hơn. Tuy nhiên, nếu bạn chỉ muốn tìm xem các đường có cắt nhau hay không, bạn có thể làm như vậy bằng cách sử dụng phương trình đường thẳng (ax + by + c = 0). Cách tiếp cận như sau:

  1. Hãy bắt đầu với hai đoạn thẳng: đoạn 1 và đoạn 2.

    segment1 = [[x1,y1], [x2,y2]]
    segment2 = [[x3,y3], [x4,y4]]
    
  2. Kiểm tra xem hai đoạn thẳng có phải là đoạn thẳng có độ dài khác 0 hay không và các đoạn phân biệt.

  3. Từ đây, tôi giả định rằng hai đoạn có độ dài khác 0 và khác nhau. Đối với mỗi đoạn thẳng, tính hệ số góc của đoạn thẳng và sau đó thu được phương trình của một đoạn thẳng dưới dạng ax + by + c = 0. Bây giờ, hãy tính giá trị của f = ax + by + c cho hai điểm của đoạn thẳng khác (lặp lại điều này cho cả đoạn thẳng khác).

    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. Bây giờ tất cả những gì còn lại là các trường hợp khác nhau. Nếu f = 0 đối với bất kỳ điểm nào thì hai đường thẳng tiếp xúc tại một điểm. Nếu f1_1 và f1_2 bằng nhau hoặc f2_1 và f2_2 bằng nhau thì các đường thẳng không cắt nhau. Nếu f1_1 và f1_2 không bằng nhau f2_1 và f2_2 không bằng nhau thì các đoạn thẳng cắt nhau. Tùy thuộc vào việc bạn muốn coi các đường chạm vào là "giao nhau" hay không, bạn có thể điều chỉnh các điều kiện của mình.


Mã này không tính toán a1và nó không hoạt động cho các đường trực giao.
Björn Lindqvist

1

Chúng tôi cũng có thể giải quyết vấn đề này bằng cách sử dụng vectơ.

Hãy xác định các phân đoạn là [start, end]. Cho hai đoạn như vậy [A, B][C, D]cả hai đều có độ dài khác 0, chúng ta có thể chọn một trong các điểm cuối được sử dụng làm điểm tham chiếu để chúng ta nhận được ba vectơ:

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]]

Từ đó, chúng ta có thể tìm giao điểm bằng cách tính t và u trong p + t*r = u*q. Sau khi xem xét phương trình một chút, chúng tôi nhận được:

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]

Do đó, chức năng là:

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

Đây là cách của tôi để kiểm tra nơi băng qua đường và nơi giao nhau. Cho phép sử dụng x1 đến x4 và y1 đến y4

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

Sau đó, chúng ta cần một số vectơ để đại diện cho chúng

dx1 = X2 - X1
dx2 = X4 - X4
dy1 = Y2 - Y1
dy2 = Y4 - Y3

Bây giờ chúng ta xem xét yếu tố quyết định

det = dx1 * dy2 - dx2 * dy1

Nếu định thức là 0,0 thì các đoạn thẳng song song với nhau. Điều này có thể có nghĩa là chúng chồng chéo lên nhau. Nếu chúng chỉ trùng nhau ở các điểm cuối, thì có một giải pháp giao điểm. Nếu không sẽ có vô số giải pháp. Với vô số giải pháp, điều gì nói lên điểm giao nhau của bạn? Vì vậy, đó là một trường hợp đặc biệt thú vị. Nếu bạn biết trước rằng các đường không thể chồng lên nhau thì bạn chỉ cần kiểm tra xem có det == 0.0hay không và chỉ cần nói rằng chúng không cắt nhau là xong. Nếu không, hãy tiếp tục

dx3 = X3 - X1
dy3 = Y3 - Y1

det1 = dx1 * dy3 - dx3 * dy1
det2 = dx2 * dy3 - dx3 * dy2

Bây giờ, nếu det, det1 và det2 đều bằng 0, thì các đường của bạn là đồng tuyến tính và có thể trùng nhau. Nếu det bằng 0 nhưng det1 hoặc det2 không thì chúng không đồng tuyến mà song song với nhau nên không có giao điểm. Vì vậy, những gì còn lại bây giờ nếu det là 0 là một vấn đề 1D thay vì 2D. Chúng ta sẽ cần phải kiểm tra một trong hai cách, tùy thuộc vào việc dx1 có bằng 0 hay không (vì vậy chúng ta có thể tránh chia cho số 0). Nếu dx1 bằng 0 thì chỉ cần thực hiện logic tương tự với các giá trị y thay vì x bên dưới.

s = X3 / dx1
t = X4 / dx1

Điều này tính toán hai tỷ lệ, sao cho nếu chúng ta chia tỷ lệ vectơ (dx1, dy1) theo s, chúng ta nhận được điểm (x3, y3) và theo t chúng ta nhận được (x4, y4). Vì vậy, nếu s hoặc t nằm trong khoảng từ 0,0 đến 1,0, thì điểm 3 hoặc 4 nằm trên dòng đầu tiên của chúng ta. Tiêu cực có nghĩa là điểm nằm sau đầu vectơ của chúng ta, trong khi> 1,0 có nghĩa là điểm đó nằm sau điểm cuối của vectơ của chúng ta. 0,0 có nghĩa là nó ở (x1, y1) và 1,0 có nghĩa là nó ở (x2, y2). Nếu cả s và t đều <0.0 hoặc cả hai đều> 1.0 thì chúng không cắt nhau. Và điều đó xử lý trường hợp đặc biệt của các đường song song.

Bây giờ, nếu det != 0.0sau đó

s = det1 / det
t = det2 / det
if (s < 0.0 || s > 1.0 || t < 0.0 || t > 1.0)
    return false  // no intersect

Điều này tương tự như những gì chúng tôi đã làm ở trên thực sự. Bây giờ nếu chúng ta vượt qua bài kiểm tra trên, thì các đoạn thẳng của chúng ta sẽ cắt nhau và chúng ta có thể tính toán giao điểm khá dễ dàng như sau:

Ix = X1 + t * dx1
Iy = Y1 + t * dy1

Nếu bạn muốn tìm hiểu sâu hơn về toán học đang làm gì, hãy xem Quy tắc Cramer.


1
Đánh máy: "dx2 = X4 - X4" phải là "dx2 = X4 - X3"
geowar

1

Cho đến nay, câu trả lời của Georgy là rõ ràng nhất để thực hiện. Phải giải quyết vấn đề này, vì ví dụ brycboe, mặc dù đơn giản nhưng cũng có vấn đề với thuộc tính.

Mã để thử nghiệm:

#!/usr/bin/python
#
# Notes on intersection:
#
# https://bryceboe.com/2006/10/23/line-segment-intersection-algorithm/
#
# /programming/3838329/how-can-i-check-if-two-segments-intersect

from shapely.geometry import LineString

class Point:
    def __init__(self,x,y):
        self.x = x
        self.y = y

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

def intersect(A,B,C,D):
    return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)


def ShapelyIntersect(A,B,C,D):
    return LineString([(A.x,A.y),(B.x,B.y)]).intersects(LineString([(C.x,C.y),(D.x,D.y)]))


a = Point(0,0)
b = Point(0,1)
c = Point(1,1)
d = Point(1,0)

'''
Test points:

b(0,1)   c(1,1)




a(0,0)   d(1,0)
'''

# F
print(intersect(a,b,c,d))

# T
print(intersect(a,c,b,d))
print(intersect(b,d,a,c))
print(intersect(d,b,a,c))

# F
print(intersect(a,d,b,c))

# same end point cases:
print("same end points")
# F - not intersected
print(intersect(a,b,a,d))
# T - This shows as intersected
print(intersect(b,a,a,d))
# F - this does not
print(intersect(b,a,d,a))
# F - this does not
print(intersect(a,b,d,a))

print("same end points, using shapely")
# T
print(ShapelyIntersect(a,b,a,d))
# T
print(ShapelyIntersect(b,a,a,d))
# T
print(ShapelyIntersect(b,a,d,a))
# T
print(ShapelyIntersect(a,b,d,a))

0

nếu dữ liệu của bạn xác định dòng, bạn chỉ cần chứng minh rằng chúng không song song. Để làm điều này, bạn có thể tính toán

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

Nếu hệ số này bằng nhau cho cả Line1 và Line2, điều đó có nghĩa là đường thẳng song song. Nếu không, nó có nghĩa là chúng sẽ giao nhau.

Nếu chúng song song thì bạn phải chứng minh rằng chúng không giống nhau. Đối với điều đó, bạn tính toán

beta = y1 - alpha*x1

Nếu beta giống nhau đối với Dòng1 và Dòng2, điều đó có nghĩa là dòng của bạn cắt nhau vì chúng bằng nhau

Nếu chúng là phân đoạn, bạn vẫn phải tính toán alpha và beta như mô tả ở trên cho mỗi Dòng. Sau đó, bạn phải kiểm tra xem (beta1 - beta2) / (alpha1 - alpha2) lớn hơn Min (x1_line1, x2_line1) và nhỏ hơn Max (x1_line1, x2_line1)


0

Tính toán giao điểm của các đường nằm trên các đoạn của bạn (về cơ bản có nghĩa là để giải hệ phương trình tuyến tính), sau đó kiểm tra xem nó có nằm giữa điểm bắt đầu và điểm kết thúc của các đoạn của bạn hay không.


0

Đây là những gì tôi có cho AS3, không biết nhiều về python nhưng khái niệm là có

    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

Thực hiện trong JAVA. Tuy nhiên Có vẻ như nó không hoạt động đối với các đường đồng tuyến tính (hay còn gọi là các đoạn thẳng tồn tại trong nhau 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;
  }
}

Đầu ra cho đến nay là

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

Tôi nghĩ rằng tôi sẽ đóng góp một giải pháp Swift hay:

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

}

0

Một trong những giải pháp ở trên đã hoạt động rất tốt, tôi quyết định viết một chương trình trình diễn hoàn chỉnh bằng cách sử dụng wxPython. Bạn sẽ có thể chạy chương trình này như sau: python " tên tệp của bạn "

# Click on the window to draw a line.
# The program will tell you if this and the other line intersect.

import wx

class Point:
    def __init__(self, newX, newY):
        self.x = newX
        self.y = newY

app = wx.App()
frame = wx.Frame(None, wx.ID_ANY, "Main")
p1 = Point(90,200)
p2 = Point(150,80)
mp = Point(0,0) # mouse point
highestX = 0


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)

def is_intersection(p1, p2, p3, p4):
    return intersect(p1, p2, p3, p4)

def drawIntersection(pc):
    mp2 = Point(highestX, mp.y)
    if is_intersection(p1, p2, mp, mp2):
        pc.DrawText("intersection", 10, 10)
    else:
        pc.DrawText("no intersection", 10, 10)

def do_paint(evt):
    pc = wx.PaintDC(frame)
    pc.DrawLine(p1.x, p1.y, p2.x, p2.y)
    pc.DrawLine(mp.x, mp.y, highestX, mp.y)
    drawIntersection(pc)

def do_left_mouse(evt):
    global mp, highestX
    point = evt.GetPosition()
    mp = Point(point[0], point[1])
    highestX = frame.Size[0]
    frame.Refresh()

frame.Bind(wx.EVT_PAINT, do_paint)
frame.Bind(wx.EVT_LEFT_DOWN, do_left_mouse)
frame.Show()
app.MainLoop()

0

Sử dụng giải pháp OMG_Peanuts , tôi đã dịch sang SQL. (Hàm vô hướng HANA)

Cảm ơn OMG_Peanuts, nó hoạt động rất tốt. Tôi đang sử dụng trái đất tròn, nhưng khoảng cách nhỏ, vì vậy tôi thấy nó ổn.

FUNCTION GA_INTERSECT" ( IN LAT_A1 DOUBLE,
         IN LONG_A1 DOUBLE,
         IN LAT_A2 DOUBLE,
         IN LONG_A2 DOUBLE,
         IN LAT_B1 DOUBLE,
         IN LONG_B1 DOUBLE,
         IN LAT_B2 DOUBLE,
         IN LONG_B2 DOUBLE) 
    
RETURNS RET_DOESINTERSECT DOUBLE
    LANGUAGE SQLSCRIPT
    SQL SECURITY INVOKER AS
BEGIN

    DECLARE MA DOUBLE;
    DECLARE MB DOUBLE;
    DECLARE BA DOUBLE;
    DECLARE BB DOUBLE;
    DECLARE XA DOUBLE;
    DECLARE MAX_MIN_X DOUBLE;
    DECLARE MIN_MAX_X DOUBLE;
    DECLARE DOESINTERSECT INTEGER;
    
    SELECT 1 INTO DOESINTERSECT FROM DUMMY;
    
    IF LAT_A2-LAT_A1 != 0 AND LAT_B2-LAT_B1 != 0 THEN
        SELECT (LONG_A2 - LONG_A1)/(LAT_A2 - LAT_A1) INTO MA FROM DUMMY; 
        SELECT (LONG_B2 - LONG_B1)/(LAT_B2 - LAT_B1) INTO MB FROM DUMMY;
        IF MA = MB THEN
            SELECT 0 INTO DOESINTERSECT FROM DUMMY;
        END IF;
    END IF;
    
    SELECT LONG_A1-MA*LAT_A1 INTO BA FROM DUMMY;
    SELECT LONG_B1-MB*LAT_B1 INTO BB FROM DUMMY;
    SELECT (BB - BA) / (MA - MB) INTO XA FROM DUMMY;
    
    -- Max of Mins
    IF LAT_A1 < LAT_A2 THEN         -- MIN(LAT_A1, LAT_A2) = LAT_A1
        IF LAT_B1 < LAT_B2 THEN        -- MIN(LAT_B1, LAT_B2) = LAT_B1
            IF LAT_A1 > LAT_B1 THEN       -- MAX(LAT_A1, LAT_B1) = LAT_A1
                SELECT LAT_A1 INTO MAX_MIN_X FROM DUMMY;
            ELSE                          -- MAX(LAT_A1, LAT_B1) = LAT_B1
                SELECT LAT_B1 INTO MAX_MIN_X FROM DUMMY;
            END IF;
        ELSEIF LAT_B2 < LAT_B1 THEN   -- MIN(LAT_B1, LAT_B2) = LAT_B2
            IF LAT_A1 > LAT_B2 THEN       -- MAX(LAT_A1, LAT_B2) = LAT_A1
                SELECT LAT_A1 INTO MAX_MIN_X FROM DUMMY;
            ELSE                          -- MAX(LAT_A1, LAT_B2) = LAT_B2
                SELECT LAT_B2 INTO MAX_MIN_X FROM DUMMY;
            END IF;
        END IF;
    ELSEIF LAT_A2 < LAT_A1 THEN     -- MIN(LAT_A1, LAT_A2) = LAT_A2
        IF LAT_B1 < LAT_B2 THEN        -- MIN(LAT_B1, LAT_B2) = LAT_B1
            IF LAT_A2 > LAT_B1 THEN       -- MAX(LAT_A2, LAT_B1) = LAT_A2
                SELECT LAT_A2 INTO MAX_MIN_X FROM DUMMY;
            ELSE                          -- MAX(LAT_A2, LAT_B1) = LAT_B1
                SELECT LAT_B1 INTO MAX_MIN_X FROM DUMMY;
            END IF;
        ELSEIF LAT_B2 < LAT_B1 THEN   -- MIN(LAT_B1, LAT_B2) = LAT_B2
            IF LAT_A2 > LAT_B2 THEN       -- MAX(LAT_A2, LAT_B2) = LAT_A2
                SELECT LAT_A2 INTO MAX_MIN_X FROM DUMMY;
            ELSE                          -- MAX(LAT_A2, LAT_B2) = LAT_B2
                SELECT LAT_B2 INTO MAX_MIN_X FROM DUMMY;
            END IF;
        END IF;
    END IF;
    
    -- Min of Max
    IF LAT_A1 > LAT_A2 THEN         -- MAX(LAT_A1, LAT_A2) = LAT_A1
        IF LAT_B1 > LAT_B2 THEN        -- MAX(LAT_B1, LAT_B2) = LAT_B1
            IF LAT_A1 < LAT_B1 THEN       -- MIN(LAT_A1, LAT_B1) = LAT_A1
                SELECT LAT_A1 INTO MIN_MAX_X FROM DUMMY;
            ELSE                          -- MIN(LAT_A1, LAT_B1) = LAT_B1
                SELECT LAT_B1 INTO MIN_MAX_X FROM DUMMY;
            END IF;
        ELSEIF LAT_B2 > LAT_B1 THEN   -- MAX(LAT_B1, LAT_B2) = LAT_B2
            IF LAT_A1 < LAT_B2 THEN       -- MIN(LAT_A1, LAT_B2) = LAT_A1
                SELECT LAT_A1 INTO MIN_MAX_X FROM DUMMY;
            ELSE                          -- MIN(LAT_A1, LAT_B2) = LAT_B2
                SELECT LAT_B2 INTO MIN_MAX_X FROM DUMMY;
            END IF;
        END IF;
    ELSEIF LAT_A2 > LAT_A1 THEN     -- MAX(LAT_A1, LAT_A2) = LAT_A2
        IF LAT_B1 > LAT_B2 THEN        -- MAX(LAT_B1, LAT_B2) = LAT_B1
            IF LAT_A2 < LAT_B1 THEN       -- MIN(LAT_A2, LAT_B1) = LAT_A2
                SELECT LAT_A2 INTO MIN_MAX_X FROM DUMMY;
            ELSE                          -- MIN(LAT_A2, LAT_B1) = LAT_B1
                SELECT LAT_B1 INTO MIN_MAX_X FROM DUMMY;
            END IF;
        ELSEIF LAT_B2 > LAT_B1 THEN   -- MAX(LAT_B1, LAT_B2) = LAT_B2
            IF LAT_A2 < LAT_B2 THEN       -- MIN(LAT_A2, LAT_B2) = LAT_A2
                SELECT LAT_A2 INTO MIN_MAX_X FROM DUMMY;
            ELSE                          -- MIN(LAT_A2, LAT_B2) = LAT_B2
                SELECT LAT_B2 INTO MIN_MAX_X FROM DUMMY;
            END IF;
        END IF;
    END IF;
        
    
    IF XA < MAX_MIN_X OR
       XA > MIN_MAX_X THEN  
       SELECT 0 INTO DOESINTERSECT FROM DUMMY;
    END IF;
    
    RET_DOESINTERSECT := :DOESINTERSECT;
END;

-2

Đã giải quyết nhưng vẫn không sao với 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

Điều này:

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

Đầu ra:

True

Và điều này:

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

Đầu ra:

False
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.