अगर दो सेगमेंट इंटरसेक्ट करते हैं तो मैं कैसे जांच सकता हूं?


93

अगर 2 खंडों को आपस में जोड़ते हैं तो मैं कैसे जांच कर सकता हूं?

मेरे पास निम्न डेटा है:

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

मुझे पता लगाने की आवश्यकता है कि पायथन में एक छोटी सी एल्गोरिथ्म का पता लगाने के लिए कि क्या 2 रेखाएं प्रतिच्छेदन हैं।


वैकल्पिक शब्द


जवाबों:


64

एक पंक्ति का समीकरण है:

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

एक खंड के लिए, यह बिल्कुल वैसा ही है, सिवाय इसके कि x एक अंतराल I पर शामिल है।

यदि आपके पास दो खंड हैं, तो निम्नानुसार परिभाषित करें:

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

चौराहे के संभावित बिंदु (एक्सए, हां) के एब्सिस एक्सए को अंतराल I1 और I2 दोनों में समाहित किया जाना चाहिए, जिसे निम्नानुसार परिभाषित किया गया है:

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

और हम कह सकते हैं कि Xa में शामिल है:

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

अब, हमें यह जाँचने की आवश्यकता है कि यह अंतराल Ia मौजूद है:

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

तो, हमारे पास दो लाइन सूत्र हैं, और एक पारस्परिक अंतराल है। आपकी लाइन सूत्र हैं:

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

जैसा कि हमें खंड द्वारा दो अंक मिले हैं, हम A1, A2, b1 और 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

यदि खंड समानांतर हैं, तो A1 == A2:

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

दोनों लाइन पर खड़े एक बिंदु (Xa, Ya) को सूत्र 1 और 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

अंतिम बात यह जांचना है कि Xa Ia में शामिल है:

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

इसके अतिरिक्त, आप स्टार्टअप पर जांच कर सकते हैं कि चार में से दो प्रदान किए गए बिंदु उस परीक्षण से बचने के लिए बराबर नहीं हैं।


1
खंड, वे खंड हैं, क्षमा करें। क्या आप अपने जवाब दिए गए सेगमेंट को अपडेट कर सकते हैं?
aeuryzm

13
यह इतना जटिल नहीं है, मैंने एक व्यापक उद्देश्य में बहुत सारे (अनसुने?) मध्यवर्ती कदम लिखे। लागू करने के लिए मुख्य बिंदु बस हैं: पारस्परिक अंतराल के अस्तित्व की जांच करें, A1, A2, b1, b2 और Xa की गणना करें, और फिर जांचें कि Xa पारस्परिक अंतराल में शामिल है। वह सब है :)
OMG_peanuts

3
A1 - A2 कभी शून्य नहीं होगा क्योंकि अगर (A1 == A2) उस स्थिति में इस गणना से पहले वापस आ जाता।
इंक्रेडिबल

3
यदि A1 == A2 और b1 == b2, खंड एक दूसरे के ऊपर हैं और असीम रूप से कई चौराहों पर हैं
lynxoid

6
फॉर्मूला A1 * x + b1 = y वर्टिकल लाइनों को हैंडल नहीं करता है इसलिए वर्टिकल सेगमेंट को इस विधि से अलग से हैंडल किया जाना चाहिए।
dmitri

78

पायथन में बहुत ही प्रभावशाली समाधान के साथ इस पृष्ठ पर उपयोगकर्ता @ i_4_got अंक । मैं इसे यहां सुविधा के लिए पुन: पेश करता हूं (क्योंकि इसने मुझे यहां आने के लिए खुश किया होगा):

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
बहुत सरल और सुरुचिपूर्ण, लेकिन यह कॉलिनैरिटी के साथ अच्छी तरह से व्यवहार नहीं करता है, और इस प्रकार उस उद्देश्य के लिए अधिक कोड की आवश्यकता होती है।
चार्ल्स

7
एक समाधान के लिए जो कोलीनियरिटी की
Zsolt Safrany

इस घोल से प्यार करें। बहुत ही सरल और संक्षिप्त! मैंने एक wxPython प्रोग्राम बनाया, जो एक रेखा खींचता है और देखता है कि क्या वह दूसरी रेखा के साथ जुड़ता है या नहीं। मैं इसे यहाँ नहीं रख सकता इसलिए यह इस टिप्पणी के नीचे है।
user1766438

33

आपको वास्तव में यह गणना करने की आवश्यकता नहीं है कि सेगमेंट्स कहां से इंटरसेक्ट होते हैं, लेकिन केवल यह समझें कि वे बिल्कुल इंटरसेक्ट करते हैं या नहीं । यह समाधान को सरल करेगा।

एक खंड को "लंगर" के रूप में माना जाता है और दूसरे खंड को 2 बिंदुओं में अलग करना है।
अब, आपको "एंकर" खंड (OnLeft, OnRight या Collinear) के प्रत्येक बिंदु की सापेक्ष स्थिति का पता लगाना होगा।
दोनों बिंदुओं के लिए ऐसा करने के बाद, जांच लें कि एक अंक OnLeft है और दूसरा OnRight (या शायद Collinear स्थिति शामिल है, यदि आप अनुचित चौराहों को भी शामिल करना चाहते हैं )।

फिर आपको एंकर और अलग सेगमेंट की भूमिकाओं के साथ प्रक्रिया को दोहराना होगा।

एक चौराहा मौजूद है अगर, और केवल अगर, एक बिंदु OnLeft है और दूसरा OnRight है। प्रत्येक संभावित मामले के लिए उदाहरण छवियों के साथ अधिक विस्तृत विवरण के लिए इस लिंक को देखें ।

इस तरह की विधि को लागू करना वास्तव में एक विधि को लागू करने की तुलना में बहुत आसान होगा जो चौराहे बिंदु को ढूंढता है (कई कोने के मामलों को दिया जाता है जिन्हें आपको भी संभालना होगा)।

अपडेट करें

निम्नलिखित कार्यों को विचार को स्पष्ट करना चाहिए (स्रोत: कम्प्यूटेशनल ज्यामिति सी में )।
टिप्पणी: यह नमूना पूर्णांक के उपयोग को मानता है। यदि आप इसके बजाय कुछ फ्लोटिंग-पॉइंट प्रतिनिधित्व का उपयोग कर रहे हैं (जो स्पष्ट रूप से चीजों को जटिल कर सकते हैं), तो आपको "समानता" (ज्यादातर IsCollinearमूल्यांकन के लिए) को इंगित करने के लिए कुछ एप्सिलॉन मान का निर्धारण करना चाहिए ।

बेशक, इन कार्यों का उपयोग करते समय, किसी को यह जांचना याद रखना चाहिए कि प्रत्येक खंड "अन्य खंडों के बीच" (क्योंकि ये परिमित खंड हैं, और अनंत रेखाएं नहीं हैं)।

इसके अलावा, इन कार्यों का उपयोग करके आप समझ सकते हैं कि आपको उचित या अनुचित चौराहा मिला है या नहीं

  • उचित : कोई मिलीभगत अंक नहीं हैं। खंड एक दूसरे को "पक्ष की ओर से" पार करते हैं।
  • अनुचित : एक खंड केवल "छूता है" दूसरे (कम से कम एक अंक एंकर वाले खंड से टकराता है)।

+1 बहुत सुंदर मेरा विचार है। यदि आप सिर्फ इस बारे में सोचते हैं कि अंक एक-दूसरे के संबंध में कहां हैं, तो आप यह तय कर सकते हैं कि उनके खंडों को किसी चीज़ की गणना किए बिना, अंतर करना चाहिए या नहीं।
जोहान रिट्जेल

और @ THC4k उह, यह वास्तव में स्पष्ट नहीं है। उदाहरण के लिए, मैंने सवाल में जो छवि जोड़ी है, उसकी जांच करें: 2 अंक "ओनलीफ्ट" और "ऑनराइट" हैं, लेकिन 2 खंडों को परस्पर नहीं जोड़ रहे हैं।
aneuryzm

@ पैट्रिक, वास्तव में नहीं। इस पर निर्भर करता है कि कौन सा सेगमेंट "एंकर" है, तो इस मामले में दोनों बिंदु या तो ओनलीफ्ट या ऑनराइट हैं। (मेरा अद्यतन जवाब देखें)।
लीरान

1
+1 मैंने इस समस्या के दर्जनों उत्तर देखे हैं, लेकिन यह सबसे स्पष्ट, सबसे सरल और सबसे कुशल है जो मैंने देखा है। :)
मिगेल

16

मान लीजिए कि दो खंडों में ए, बी और सी, डी हैं। चौराहे का निर्धारण करने के लिए संख्यात्मक रूप से मजबूत तरीका चार निर्धारकों के संकेत की जांच करना है:

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

चौराहे के लिए, बाईं ओर के प्रत्येक निर्धारक के पास एक से दाएं का विपरीत चिन्ह होना चाहिए, लेकिन दोनों रेखाओं के बीच कोई संबंध नहीं होना चाहिए। आप मूल रूप से दूसरे खंड के खिलाफ खंड के प्रत्येक बिंदु की जांच कर रहे हैं ताकि यह सुनिश्चित हो सके कि वे दूसरे खंड द्वारा परिभाषित रेखा के विपरीत दिशा में झूठ बोलते हैं।

यहां देखें: http://www.cs.cmu.edu/~quake/robust.html


क्या यह अनुचित चौराहों के लिए काम करता है यानी जब चौराहे का बिंदु एक पंक्ति खंड पर स्थित है?
सईम काज़ी

@SyamQazi यह लगता है कि यदि आप कम से कम एक लाइन सेगमेंट के समापन बिंदु को पार कर रहे हैं, तो चौराहा विफल हो जाता है। यदि आप खंड पर हैं, तो: मुझे लगता है कि यह एक 0 बनाम 1 / -1 की तुलना होगी, इसलिए यह बिना किसी अंतर के पता लगाएगी।
2

1
वैसे, यह समझाने के लिए: प्रत्येक निर्धारक दो लाइन खंडों के वैक्टर एंडपॉइंट्स के क्रॉस-उत्पाद की गणना कर रहा है। शीर्ष बाएँ उदाहरण के लिए CA x CB बनाम शीर्ष दायाँ x x DB है। यह अनिवार्य रूप से परीक्षण करता है कि किस तरफ एक शिखर है (क्लॉकनेस)। अभी भी यह पता लगाने की कोशिश की जा रही है कि यह लाइन सेगमेंट के लिए कैसे काम करता है जो असीम रूप से विस्तारित नहीं होते हैं।
वार्टी

8

अगर विधि का उपयोग करके शाॅपली लाइब्रेरी के साथ लाइन सेगमेंट प्रतिच्छेद करना बहुत आसान है, तो यह जांचना intersects:

from shapely.geometry import LineString

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

यहाँ छवि विवरण दर्ज करें

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

यहाँ छवि विवरण दर्ज करें


6

के आधार पर Liran की और Grumdrig के उत्कृष्ट जवाब यहां यदि सत्यापित करने के लिए एक पूरा अजगर कोड है बंद खंडों एक दूसरे को काटना है। कोलियर सेगमेंट के लिए काम करता है, अक्ष Y के समानांतर खंड, पतित सेगमेंट (शैतान विवरण में है)। पूर्णांक निर्देशांक मानता है। फ्लोटिंग पॉइंट कोऑर्डिनेट्स के लिए समानता परीक्षण के बिंदुओं में संशोधन की आवश्यकता होती है।

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

"बंद सेगमेंट" का क्या मतलब है?
सैम

@Sam बंद खंड में इसके समापन बिंदु होते हैं। उदाहरण के लिए, R से अंकों का एक बंद खंड होगा [0, 1] (0 <= x <= 1) कहने के लिए विपरीत] 0, 1] (0 <x <= 1)
dmitri

6

यहाँ डॉट उत्पादों का उपयोग कर एक समाधान दिया गया है:

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

यहाँ डेसमोस में एक दृश्य है: लाइन सेगमेंट इंटरसेक्शन


यह भयानक है, और मैं डेसमोस के बारे में भूल गया हूं - यह इस समस्या के लिए एकदम सही है! धन्यवाद!
पोनदतो

अपने समाधान से प्यार करें लेकिन ऐसा लगता है जैसे यह विफल हो जाता है अगर दो लाइन खंड लाइन में हैं
एच। पोप

बहुत अच्छा। किसी और को इसे एक अलग भाषा में पोर्ट करने के लिए, फ़्लोट या इंट 64 का उपयोग करना सुनिश्चित करें क्योंकि एक इंट 32 पर 1280x720 से कम संख्या पर बहुत जल्दी ओवरफ्लो हो जाएगा
जो कि अन्य लड़के

4

आपके पास दो लाइन सेगमेंट हैं। एंडपॉइंट ए एंड बी द्वारा एक सेगमेंट को परिभाषित करें और एंडपॉइंट्स सी एंड डी द्वारा दूसरा सेगमेंट। यह दिखाने के लिए एक अच्छी चाल है कि उन्हें खंडों की सीमा के साथ अंतर करना चाहिए। (ध्यान दें कि रेखाएँ स्वयं खंडों की सीमा से परे हो सकती हैं, इसलिए आपको सावधान रहना चाहिए। अच्छा कोड भी नई लाइनों के लिए देखेगा।)

ट्रिक यह परखने के लिए है कि बिंदु A और B को लाइन CD के विपरीत दिशा में लाइन करना चाहिए, और यह इंगित करता है कि C और D को लाइन AB के विपरीत दिशा में लेटना चाहिए।

चूंकि यह होमवर्क है, इसलिए मैं आपको एक स्पष्ट समाधान नहीं दूंगा। लेकिन एक साधारण परीक्षण यह देखने के लिए कि एक बिंदु पर एक रेखा के किस तरफ एक डॉट उत्पाद का उपयोग करना है। इस प्रकार, एक दी गई सीडी सीडी के लिए, उस रेखा के सामान्य वेक्टर की गणना करें (मैं इसे N_C कहूंगा।) अब, बस इन दो परिणामों के संकेतों का परीक्षण करें:

dot(A-C,N_C)

तथा

dot(B-C,N_C)

यदि उन परिणामों के विपरीत संकेत हैं, तो ए और बी लाइन सीडी के विपरीत पक्ष हैं। अब दूसरी पंक्ति के लिए भी यही परीक्षण करें, एबी। इसमें सामान्य वेक्टर N_A है। के संकेतों की तुलना करें

dot(C-A,N_A)

तथा

dot(D-A,N_A)

मैं आपको यह जानने के लिए छोड़ दूंगा कि सामान्य वेक्टर की गणना कैसे करें। (2-डी में, यह तुच्छ है, लेकिन क्या आपका कोड इस बारे में चिंता करेगा कि क्या ए और बी अलग-अलग बिंदु हैं? इसी तरह, क्या सी और डी अलग हैं?)

आपको अभी भी लाइन सेगमेंट के बारे में चिंता करने की ज़रूरत है जो एक ही अनंत रेखा के साथ स्थित हैं, या यदि एक बिंदु वास्तव में दूसरे लाइन सेगमेंट पर पड़ता है। अच्छा कोड हर संभव समस्या को पूरा करेगा।


3

यहां यह जांचने के लिए सी कोड है कि क्या लाइन सेगमेंट के विपरीत छोर पर दो बिंदु हैं। इस कोड का उपयोग करके आप देख सकते हैं कि क्या दो सेगमेंट भी इंटरसेक्ट करते हैं।

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

यहां यह जांचने के लिए एक और अजगर कोड है कि बंद खंडों को काटना है या नहीं। यह http://www.cdn.geeksforgeeks.org/check-if-two-given-line-seolution-intersect/ में C ++ कोड का पुनर्लेखन संस्करण है । यह कार्यान्वयन सभी विशेष मामलों को शामिल करता है (उदाहरण के लिए सभी बिंदु कॉलिनियर)।

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

नीचे सत्यापित करने के लिए एक परीक्षण फ़ंक्शन है कि यह काम करता है।

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()परीक्षण कोड से परिभाषित नहीं है।
hhquark

1
@hhquark धन्यवाद। मैंने अब इन लाइनों को हटा दिया है। मैंने यह जाँचने के लिए इन पंक्तियों को शामिल किया है कि मेरा कार्यान्वयन एक और उत्तर ( stackoverflow.com/a/18524383/7474256 , मुझे लगता है) के कार्यान्वयन से सहमत है ।
फेबियन यिंग

1

एबी और सीडी खंडों के लिए, सीडी की ढलान का पता लगाएं

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

CD को A और B से बढ़ाएं, और सीधे ऊपर जाने वाली CD की दूरी लें

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

जांचें कि क्या वे विपरीत पक्षों पर हैं

return dist1*dist2<0

1
क्या आप सूत्रों के बारे में निश्चित हैं? क्योंकि B के निर्देशांक का उपयोग नहीं किया जाता है, इसलिए आप सभी 4 शीर्षों पर विचार किए बिना AB और CD का प्रतिच्छेदन कैसे खोज सकते हैं?
mac13k

1
मुझे लगता है कि वहाँ होना चाहिए: dist2 = ढलान * (Dx-Bx) + By-Dy
mac13k

1

चूंकि आप यह उल्लेख नहीं करते हैं कि आप लाइन के चौराहे बिंदु को ढूंढना चाहते हैं, इसलिए समस्या को हल करना सरल हो जाता है। यदि आपको चौराहे के बिंदु की आवश्यकता है, तो OMG_peanuts द्वारा उत्तर एक तेज़ तरीका है। हालाँकि, यदि आप केवल यह पता लगाना चाहते हैं कि रेखाएँ प्रतिच्छेद करती हैं या नहीं, तो आप ऐसा कर सकते हैं कि रेखा समीकरण (कुल्हाड़ी + द्वारा + ग = ०) का उपयोग कर सकें। दृष्टिकोण इस प्रकार है:

  1. चलो दो लाइन खंडों के साथ शुरू करते हैं: खंड 1 और खंड 2।

    segment1 = [[x1,y1], [x2,y2]]
    segment2 = [[x3,y3], [x4,y4]]
    
  2. जांचें कि क्या दो लाइन खंड गैर शून्य लंबाई लाइन और अलग-अलग खंड हैं।

  3. यहां से, मैं मानता हूं कि दो खंड गैर-शून्य लंबाई और अलग हैं। प्रत्येक पंक्ति खंड के लिए, रेखा के ढलान की गणना करें और फिर कुल्हाड़ी के रूप में रेखा का समीकरण + c = 0. से प्राप्त करें। अब, दो बिंदुओं के लिए f = ax + by + 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. अब जो कुछ बचा है वह अलग-अलग मामले हैं। यदि किसी बिंदु के लिए f = 0 है, तो दो बिंदु एक बिंदु पर स्पर्श करते हैं। यदि f1_1 और f1_2 समान हैं या f2_1 और f2_2 समान हैं, तो लाइनें प्रतिच्छेद नहीं करती हैं। यदि f1_1 और f1_2 असमान हैं और f2_1 और f2_2 असमान हैं, तो लाइन सेगमेंट प्रतिच्छेद करते हैं। इस पर निर्भर करते हुए कि आप उन पंक्तियों पर विचार करना चाहते हैं जो "इंटरसेक्टिंग" के रूप में स्पर्श करती हैं या नहीं, आप अपनी शर्तों को अनुकूलित कर सकते हैं।


यह कोड गणना नहीं करता है a1और यह ऑर्थोगोनल लाइनों के लिए काम नहीं करता है।
ब्योर्न लिंडक्विस्ट

1

हम इस उपयोगी वैक्टर को भी हल कर सकते हैं।

के रूप में खंडों को परिभाषित करते हैं [start, end]। ऐसे दो सेगमेंट को देखते हुए [A, B]और [C, D]जिसमें दोनों की गैर-शून्य लंबाई है, हम एक संदर्भ बिंदु के रूप में उपयोग किए जाने वाले समापन बिंदुओं में से एक चुन सकते हैं ताकि हमें तीन वैक्टर मिलें:

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

वहां से, हम टी और यू की गणना करके एक चौराहे की तलाश कर सकते हैं p + t*r = u*q। थोड़ी सी समीकरण के साथ खेलने के बाद, हमें मिलता है:

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]

इस प्रकार, कार्य है:

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

यह लाइन क्रॉसिंग और जहां चौराहा होता है, के लिए जाँच का मेरा तरीका है। X4 और y1 के माध्यम से y4 के माध्यम से X1 का उपयोग करें

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

तब हमें उनका प्रतिनिधित्व करने के लिए कुछ वैक्टर चाहिए

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

अब हम निर्धारक को देखते हैं

det = dx1 * dy2 - dx2 * dy1

यदि निर्धारक 0.0 है, तो रेखा खंड समानांतर हैं। इसका मतलब यह हो सकता है कि वे ओवरलैप करते हैं। यदि वे केवल समापन बिंदु पर ओवरलैप करते हैं, तो एक चौराहा समाधान है। अन्यथा अनंत उपाय होंगे। असीम रूप से कई समाधानों के साथ, आपका क्या कहना है? तो यह एक दिलचस्प विशेष मामला है। यदि आप समय से पहले जानते हैं कि लाइनें ओवरलैप नहीं हो सकती हैं, तो आप बस यह देख सकते हैं कि क्या det == 0.0और यदि ऐसा है तो वे कहते हैं कि वे अंतर नहीं करते हैं और किया जा सकता है। अन्यथा, पर जारी रखने देता है

dx3 = X3 - X1
dy3 = Y3 - Y1

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

अब, यदि det, det1 और det2 सभी शून्य हैं, तो आपकी लाइनें सह-रैखिक हैं और ओवरलैप हो सकती हैं। यदि det जीरो है, लेकिन या तो det1 या det2 नहीं है, तो वे सह-रैखिक नहीं हैं, लेकिन समानांतर हैं, इसलिए कोई चौराहा नहीं है। तो क्या अब बचा है अगर हिरासत शून्य है 2 डी के बजाय 1 डी समस्या है। हमें दो तरीकों में से एक की जांच करने की आवश्यकता होगी, यह निर्भर करता है कि dx1 शून्य है या नहीं (इसलिए हम शून्य से विभाजन से बच सकते हैं)। यदि dx1 शून्य है, तो केवल x मानों के बजाय y मानों के साथ तर्क करें।

s = X3 / dx1
t = X4 / dx1

यह दो स्केलर्स की गणना करता है, जैसे कि अगर हम सदिश (dx1, dy1) को स्केल करते हैं, तो हमें पॉइंट (x3, y3) मिलता है, और t से हमें मिलता है (x4, y4)। इसलिए यदि या तो s या t 0.0 और 1.0 के बीच है, तो बिंदु 3 या 4 हमारी पहली पंक्ति पर स्थित है। नकारात्मक का मतलब होगा कि बिंदु हमारे वेक्टर की शुरुआत के पीछे है, जबकि> 1.0 का मतलब है कि यह हमारे वेक्टर के अंत से आगे है। 0.0 का मतलब है कि यह (X1, y1) और 1.0 का मतलब है कि यह (x2, y2) पर है। यदि दोनों s और t <0.0 हैं या दोनों ही 1.0 हैं, तो वे प्रतिच्छेद नहीं करते हैं। और वह समानांतर रेखा विशेष मामले को संभालता है।

अब, अगर det != 0.0तब

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

यह वही है जो हम वास्तव में ऊपर कर रहे थे। अब यदि हम उपर्युक्त परीक्षा पास करते हैं, तो हमारी लाइन सेगमेंट इंटरसेक्ट होती है, और हम चौराहे की गणना बहुत आसानी से कर सकते हैं:

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

यदि आप गणित में जो कर रहे हैं, उसमें गहराई से खुदाई करना चाहते हैं, तो Cramer के नियम पर गौर करें।


1
टाइपो: "dx2 = X4 - X4" 19x में "dx2 = X4 - X3" होना चाहिए
geowar

1

उत्तर जिओर्जी द्वारा को लागू करने के लिए सबसे साफ है। यह नीचे का पीछा करने के लिए किया था, brycboe उदाहरण के बाद से, जबकि सरल, साथ ही कॉलिनरिटी के साथ मुद्दे थे।

परीक्षण के लिए कोड:

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

यदि आपका डेटा लाइन परिभाषित करता है तो आपको यह साबित करना होगा कि वे समानांतर नहीं हैं। ऐसा करने के लिए आप गणना कर सकते हैं

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

यदि यह गुणांक लाइन 1 और लाइन 2 दोनों के लिए बराबर है, तो इसका मतलब है कि लाइन समानांतर हैं। यदि नहीं, तो इसका मतलब है कि वे अंतर करेंगे।

यदि वे समानांतर हैं तो आपको यह साबित करना होगा कि वे समान नहीं हैं। उसके लिए, आप गणना करते हैं

beta = y1 - alpha*x1

यदि बीटा लाइन 1 और लाइन 2 के लिए समान है, तो इसका मतलब है कि आप पंक्ति को एक समान बनाते हैं

यदि वे खंड हैं, तो आपको अभी भी प्रत्येक पंक्ति के लिए ऊपर वर्णित अल्फा और बीटा की गणना करनी होगी। फिर आपको यह जांचना होगा कि (Beta1 - Beta2) / (Alpha1 - Alpha2) Min (X1_line1, x2_line1) से बड़ा है और Max (X1_line1, x2_line1) से कम है


0

अपने सेगमेंट पर बिछाई जाने वाली रेखाओं के प्रतिच्छेदन बिंदु की गणना करें (इसका अर्थ मूल रूप से एक रेखीय समीकरण प्रणाली को हल करने के लिए है), फिर जांचें कि क्या यह आपके सेगमेंट के शुरुआती और अंतिम बिंदुओं के बीच है।


0

यह वही है जो मैंने AS3 के लिए प्राप्त किया है, अजगर के बारे में ज्यादा नहीं जानता, लेकिन अवधारणा वहां है

    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

जावेद में लागू किया गया। हालाँकि ऐसा लगता है कि यह सह-रेखीय लाइनों (उर्फ लाइन खंडों के लिए काम नहीं करता है जो एक दूसरे 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;
  }
}

इस प्रकार आउटपुट बहुत दूर है

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

मैंने सोचा था कि मैं एक अच्छा स्विफ्ट समाधान योगदान दूंगा:

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

उपरोक्त समाधानों में से एक ने इतनी अच्छी तरह से काम किया कि मैंने wxPython का उपयोग करके एक पूर्ण प्रदर्शन कार्यक्रम लिखने का फैसला किया। आपको इस प्रोग्राम को इस तरह से चलाने में सक्षम होना चाहिए: अजगर " आपका फ़ाइल नाम "

# 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

OMG_Peanuts का उपयोग करना समाधान , मैंने SQL में अनुवाद किया। (हाना स्केलर फंक्शन)

धन्यवाद OMG_Peanuts, यह बहुत अच्छा काम करता है। मैं गोल पृथ्वी का उपयोग कर रहा हूं, लेकिन दूरियां छोटी हैं, इसलिए मैं इसका ठीक आंकलन करता हूं।

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

हल किया गया लेकिन फिर भी अजगर के साथ क्यों नहीं ... :)

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

आउटपुट:

True

और इस:

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

आउटपुट:

False
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.