İki çizgi parçasının kesiştiği yeri nasıl tespit edersiniz? [kapalı]


518

İki çizginin kesişip kesişmediğini ve eğer yaparsa, hangi x, y noktasında nasıl belirlerim?


Dikdörtgenin kenarlarını tam çokgen yerine ayrı çizgiler olarak düşünmek yardımcı olabilir.
Ryan Graham

Moderatör notu : Bu yazının konuyla ilgili olup olmadığına dair tartışma Meta Stack Overflow'a ait. Burada daha fazla yorum silinecek.
Martijn Pieters

Yanıtlar:


659

Vektör çapraz ürünler kullanan bu soruna hoş bir yaklaşım var. 2-boyutlu bir vektör çapraz ürün tanımlama v  x  ağırlık olarak hacim x  w y  -  v y  w , x .

İki hat segmentleri varsayın p için p  +  r ve gelen q için q  +  s . Daha sonra ilk satırdaki herhangi bir nokta p  +  t  r (skaler parametre  t için ) ve ikinci satırdaki herhangi bir nokta q  +  u  s (skaler parametre  u için ) olarak temsil edilebilir.

Kesişen iki çizgi parçası

İki çizgi t ve u'yu bulabilirsek kesişir :

p + t  r = q + u  s

Kavşak noktası formülleri

S ile her iki tarafı çapraz , elde

( p + t  r ) × s = ( q + u  s ) × s

Ve s  ×  s = 0 olduğu için bu

t  ( r × s ) = ( q - p ) × s

Ve bu nedenle, t için çözme :

t = ( q - p ) × s / ( r × s )

Aynı şekilde, biz u için çözebilir :

( p + t  r ) × r = ( q + u  s ) × r

u  ( s × r ) = ( p - q ) × r

u = ( p - q ) × r / ( s × r )

Hesaplama adımlarının sayısını azaltmak için, bunu aşağıdaki gibi yeniden yazmak uygundur ( s  ×  r = -  r  ×  s'yi hatırlamak ):

u = ( q - p ) × r / ( r × s )

Şimdi dört vaka var:

  1. Eğer R  x  s  = 0 ve ( q  -  p ) x  r  = 0 ise, o zaman iki hat kolineerdir.

    Bu durumda, ikinci segmentin uç noktalarını ( q ve q  +  s ) ilk çizgi segmentinin denklemi ( p + t r ) cinsinden ifade edin :

    t 0 = ( q - p ) ·  r / ( r  ·  r )

    t 1 = ( q + s - p ) ·  r / ( r  ·  r ) = t 0 + s  ·  r / ( r  ·  r )

    Eğer arasındaki aralık t 0 ve t 1 kesişen aralığı [0, 1] daha sonra hat kesimleri ile eşdoğrusal ve birbiriyle örtüşen; Aksi takdirde, eşdoğrusal ve ayrıktırlar.

    Eğer s ve r ters yönleri gösteriyorsa, s  ·  r <0 ve dolayısıyla kontrol edilecek aralığın [ t 0 , t 1 ] yerine [ t 1 , t 0 ] olduğunu unutmayın .

  2. Eğer R  x  s  = 0 ve ( q  -  p ) x  R  ≠ 0 olduğunda, iki hat paralel ve birbiri ile kesişmez.

  3. Eğer R  x  s  ≠ 0 ve 0 ≤  t  ≤ 1 ve 0 ≤  u  ≤ 1, iki çizgi parçası noktasında araya p + t  r = q + u  s .

  4. Aksi takdirde, iki çizgi parçası paralel değildir ancak kesişmez.

Kredi: Bu yöntem, Grafik Taşlar , sayfa 304'de yayınlanan Ronald Goldman'ın "Üç uzayda iki çizginin kesişmesi" makalesinden 3B çizgi kesişme algoritmasının 2 boyutlu uzmanlaşmasıdır. Üç boyutta, olağan durum çizgiler eğridir (ne paralel ne de kesişen), bu durumda yöntem iki çizgiye en yakın yaklaşım noktalarını verir.


5
@myrkos: Hayır. İlk çizgi segmenti "p'den p + r'ye" çalışır, bu nedenle "p + tr" olarak parametrik olarak temsil edildiğinde segment 0 0 t ≤ 1'e karşılık gelir. Diğer segment için benzer şekilde.
Gareth Rees

7
Gareth, bir şeyi kaçırmam gerektiğini hissediyorum, ama (vektör) bir vektöre nasıl bölüyorsun? Sizin için çözümler t ve u ile sona / (r × s)ama (r × s)bir vektör, doğru mu? Bir vektör (0, 0, rx * sy - ry * sx). Ve sol taraf da benzer şekilde z eksenine paralel bir vektördür. Yani ... sadece z bileşenini diğer z bileşenine böler miyim? T için formül aslında |(q − p) × s| / |(r × s)|mi?
LarsH

7
@LarsH: ilk paragrafa bakınız.
Gareth Rees

35
İlgilenenler için, işte görünen satırlar için PointF başlangıç ​​ve bitiş koordinatlarını alan basit bir C # uygulaması: ideone.com/PnPJgb
Matt

24
@Matt'ın ardından bir JavaScript uygulaması oluşturdum. Tekito'nun işaret ettiği hataları düzelttim.
pgkelley

230

FWIW, aşağıdaki işlev (C'de) hem çizgi kesişimlerini algılar hem de kesişim noktasını belirler. Andre LeMothe'nin " Windows Game Programming Gurus'un Püf Noktaları " ndaki bir algoritmaya dayanmaktadır . Diğer cevaplardaki bazı algoritmalardan farklı değildir (örneğin Gareth's). LeMothe daha sonra denklemleri kendileri çözmek için Cramer Kuralı'nı (bana sorma) kullanır.

Benim zayıf asteroitler klonumda çalıştığını ve Elemental, Dan ve Wodzu'nun diğer cevaplarında açıklanan son vakalarla doğru bir şekilde başa çıktığını düşünüyorum. Muhtemelen KingNestor tarafından yayınlanan koddan daha hızlıdır, çünkü hepsi çarpma ve bölme, karekök yok!

Benim durumumda bir sorun olmasa da, orada sıfıra bölme potansiyeli olduğunu düşünüyorum. Zaten kazayı önlemek için değiştirmek için yeterince kolay.

// Returns 1 if the lines intersect, otherwise 0. In addition, if the lines 
// intersect the intersection point may be stored in the floats i_x and i_y.
char get_line_intersection(float p0_x, float p0_y, float p1_x, float p1_y, 
    float p2_x, float p2_y, float p3_x, float p3_y, float *i_x, float *i_y)
{
    float s1_x, s1_y, s2_x, s2_y;
    s1_x = p1_x - p0_x;     s1_y = p1_y - p0_y;
    s2_x = p3_x - p2_x;     s2_y = p3_y - p2_y;

    float s, t;
    s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
    t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);

    if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
    {
        // Collision detected
        if (i_x != NULL)
            *i_x = p0_x + (t * s1_x);
        if (i_y != NULL)
            *i_y = p0_y + (t * s1_y);
        return 1;
    }

    return 0; // No collision
}

BTW, LeMothe'nin kitabında, görünüşe göre algoritmayı doğru bulmasına rağmen, somut örneğin fişleri yanlış numaralarda gösterdiğini ve hesaplamaları yanlış yaptığını söylemeliyim. Örneğin:

(4 * (4-1) + 12 * (7-1)) / (17 * 4 + 12 * 10)

= 844 / 0,88

= 0,44

Bu beni saatlerce karıştırdı . :(


9
getLineIntersection işlevi (p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y) {var s1_x, s1_y, s2_x, s2_y; s1_x = p1_x - p0_x; s1_y = p1_y - p0_y; s2_x = p3_x - p2_x; s2_y = p3_y - p2_y; var s, t; s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y); t = (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
cortijon

5
eğer (s> = 0 && s <= 1 && t> = 0 && t <= 1) {// Çarpışma tespit edildi var intX = p0_x + (t * s1_x); var intY = p0_y + (t * s1_y); dönüş [intX, intY]; boş döndür; // Çarpışma yok}
cortijon

13
iyi algoritma, ancak belirleyici 0 olduğu durumları işlemez. (yukarıdaki -s2_x * s1_y + s1_x * s2_y). 0 ise (veya 0'a yakınsa) çizgiler paralel veya doğrusaldır. Eşdoğrusalsa, kavşak başka bir çizgi parçası olabilir.
seand

16
Hız için iki bölme işleminden kaçınılabilir (bölme maliyeti çarpma işleminden daha fazladır); eğer çizgiler kesişiyorsa bir bölüme ihtiyacınız varsa, kesişmedikleri takdirde sıfıra ihtiyacınız vardır. Kişi önce paydayı hesaplamalı ve sıfır ise erken durmalıdır (muhtemelen doğrusallığı saptamak için kod ekler.) Daha sonra, iki pay ve payda arasındaki ilişkiyi hesaplamak sve tdoğrudan test etmek yerine . Yalnızca çizgilerin kesiştiği onaylanırsa, aslında değerini hesaplamanız gerekir t(ancak değil s).
Qwertie

18
Burada yayınlanan tüm algoritmalar üzerinde performans testi yaptım ve bu, diğerlerinden en az iki kat daha hızlı. Gönderdiğiniz için teşekkürler!
lajos

63

Sorun şu soruya indirgeniyor: A'dan B'ye ve C'den D'ye iki çizgi kesişiyor mu? Sonra dört kez sorabilirsiniz (çizgi ile dikdörtgenin dört kenarının her biri arasında).

İşte bunu yapmak için vektör matematiği. A'dan B'ye doğru çizginin söz konusu çizgi ve C'den D'ye doğru çizginin dikdörtgen çizgilerden biri olduğunu varsayıyorum. Benim işaretim, Ax"A'nın x koordinatı" ve Cy"C'nin y koordinatı" dır. Ve " *" nokta çarpımı anlamına gelir A*B = Ax*Bx + Ay*By;

E = B-A = ( Bx-Ax, By-Ay )
F = D-C = ( Dx-Cx, Dy-Cy ) 
P = ( -Ey, Ex )
h = ( (A-C) * P ) / ( F * P )

Bu hsayı anahtardır. Eğer harasındadır 0ve 1, çizgilerin kesiştiği, aksi takdirde yok. Eğer F*PTabii hesaplama yapamazsınız de sıfırdır, ancak bu durumda çizgileri paralel ve bu nedenle sadece kesiştiği bariz durumlarda vardır.

Kesişme noktası kesin C + F*h.

Daha fazla eğlence:

Eğer hbir tam 0 veya 1satırlar bir son noktada dokunun. Uygun gördüğünüz gibi bunu bir "kavşak" olarak değerlendirebilirsiniz.

Özellikle, hdiğer çizgiye tam olarak dokunmak için çizginin uzunluğunu çarpmanız gerekir.

Bu nedenle, h<0bu, dikdörtgen çizginin verilen çizginin "arkasında" olduğu anlamına gelir ("yön" A'dan B'ye ") ve h>1dikdörtgen çizginin belirtilen çizginin" önünde "olması anlamına gelir.

derivasyon:

A ve C, çizginin başlangıcına işaret eden vektörlerdir; E ve F, çizgiyi oluşturan A ve C uçlarından vektörlerdir.

Düzlemdeki iki paralel olmayan çizgi için, tam olarak bir çift skaler olmalı gve hbu denklemin taşıyacağı şekilde:

A + E*g = C + F*h

Neden? İki paralel olmayan çizginin kesişmesi gerektiğinden, her iki çizgiyi de bir miktar ölçeklendirebilir ve birbirine dokunabilirsiniz.

( İki bilinmeyenli bir denklem gibi ilk olarak bu görünüyor anda! Ama bu gerçekten de denklemlerin bir çift anlamına gelen bir 2D vektör denklemi olduğunu göz önüne aldığımızda değil xve y.)

Bu değişkenlerden birini ortadan kaldırmalıyız. Kolay bir yol Esıfır terimini yapmaktır . Bunu yapmak için, denklemin her iki tarafının nokta çarpımını E ile sıfıra noktalanacak bir vektör kullanarak alın. PYukarıda çağırdığım vektör ve E'nin belirgin dönüşümünü yaptım.

Artık sizde:

A*P = C*P + F*P*h
(A-C)*P = (F*P)*h
( (A-C)*P ) / (F*P) = h

29
Bu algoritma güzel. Ancak Dan @ stackoverflow.com/questions/563198/… & Elemental @ stackoverflow.com/questions/563198/… tarafından işaret edildiği gibi bir delik var . Cevabınızı gelecekteki referansınız için güncellemeniz güzel olurdu. Teşekkürler.
Chantz

2
Bu algoritma sayısal olarak kararlı mı? Ben similliar bir yaklaşım denedim ve şamandıralar üzerinde çalışırken garip sonuçlar verdi.
milosz

3
Bu algoritma ile ilgili başka bir sorun var gibi görünüyor. Noktalar beslendiğinde A = {1, 0} B = {2, 0} C = {0, 0} D = {1,0} olmasına rağmen, çizgi segmentleri bir uçta açıkça dokunsa da, F P (ve ayrıca E Q, aşağıdaki düzeltmeye uygun olarak) her ikisinin de 0 olması dolayısıyla 0 ile bölünmenin h ve g'yi bulmasına neden olur. Hala bunun için çözüm üzerinde çalışıyoruz, ama sorunun işaret etmeye değer olduğunu düşündüm.
candrews

12
Bu cevap basitçe yanlış. A = {0,0}, B = {0,1}, C = {0,2} D = {2,0}
Tim Cooper

6
A + E*g = C + F*hİki satır kesiştiği ancak ve ancak bu denklemin çözeltisi (bunlar paralel değildir varsayılarak) sahiptir , her ikisi de gveh 0 ile 1 arasında (bir son noktasında dokunmadan sayısı bağlı olarak, giriş veya hariç).
Daniel Fischer

46

Yukarıda Jason tarafından bu kadar zarif bir şekilde açıklanan algoritmayı uygulamaya çalıştım; ne yazık ki hata ayıklama matematik olsa da çalışırken onun işe yaramaz birçok durumda buldum.

Örneğin A (10,10) B (20,20) C (10,1) D (1,10) noktalarının h = .5 verdiğini ve yine de bu segmentlerin birbirine yakın olmadığı açıktır. diğer.

Bunu grafiğe dökmek, 0 <h <1 kriterlerinin yalnızca kesme noktasının varsa CD'de olacağını gösterir, ancak bu noktanın AB üzerinde olup olmadığına dair hiçbir şey söylemez. Bir çapraz nokta olduğundan emin olmak için g değişkeni için simetrik hesaplamayı yapmanız ve müdahale gereksinimi: 0 <g <1 VE 0 <h <1


2
Kabul edilen cevabın benim için neden işe yaramadığını anlamaya çalışarak saçımı çekiyorum. Çok teşekkürler!
Matt Bridges

1
Ayrıca, bu durumda sınır koşullarının işe yaradığı da dikkate değer (yani, h = 0 veya h = 1 veya g = 0 veya g = 1 için 'sadece' dokunma çizgileri
Elemental


45

İşte Gavin'in cevabında bir gelişme. marcp'nin çözümü de benzerdir, ancak ikisi de bölünmeyi ertelemez.

Bu aslında Gareth Rees'in cevabının pratik bir uygulaması olduğu ortaya çıkıyor, çünkü çapraz ürünün 2D'deki eşdeğeri, bu kodun üçünü kullandığı perp-nokta ürünüdür. 3D'ye geçmek ve çapraz ürünü kullanmak, sonunda s ve t'yi enterpolasyonlamak, 3D'deki çizgiler arasında en yakın iki noktayı verir. Her neyse, 2D çözümü:

int get_line_intersection(float p0_x, float p0_y, float p1_x, float p1_y, 
    float p2_x, float p2_y, float p3_x, float p3_y, float *i_x, float *i_y)
{
    float s02_x, s02_y, s10_x, s10_y, s32_x, s32_y, s_numer, t_numer, denom, t;
    s10_x = p1_x - p0_x;
    s10_y = p1_y - p0_y;
    s32_x = p3_x - p2_x;
    s32_y = p3_y - p2_y;

    denom = s10_x * s32_y - s32_x * s10_y;
    if (denom == 0)
        return 0; // Collinear
    bool denomPositive = denom > 0;

    s02_x = p0_x - p2_x;
    s02_y = p0_y - p2_y;
    s_numer = s10_x * s02_y - s10_y * s02_x;
    if ((s_numer < 0) == denomPositive)
        return 0; // No collision

    t_numer = s32_x * s02_y - s32_y * s02_x;
    if ((t_numer < 0) == denomPositive)
        return 0; // No collision

    if (((s_numer > denom) == denomPositive) || ((t_numer > denom) == denomPositive))
        return 0; // No collision
    // Collision detected
    t = t_numer / denom;
    if (i_x != NULL)
        *i_x = p0_x + (t * s10_x);
    if (i_y != NULL)
        *i_y = p0_y + (t * s10_y);

    return 1;
}

Temel olarak bölünmeyi son ana kadar erteler ve testlerin çoğunu belirli hesaplamalar yapılmadan önce hareket ettirir, böylece erken çıkışlar ekler. Son olarak, çizgiler paralel olduğunda oluşan sıfır durumuna bölünmeyi de önler.

Ayrıca sıfıra kıyasla bir epsilon testi kullanmayı düşünebilirsiniz. Paralelliğe çok yakın olan çizgiler, biraz kapalı sonuçlar verebilir. Bu bir hata değil, kayan nokta matematiği ile ilgili bir sınırlamadır.


1
Bazı noktaların değeri 0 ise başarısız olur. Bu doğru olmamalı mı?
hfossli

1
Bölmeyi ertelerken ortaya çıkan bir hata için düzeltme yaptım. Sayı ve payın her ikisi de negatif olduğunda pozitif olabilir.
iMalc

2
P0-p1 dikey ve p2-p3 yataysa ve iki segment kesişiyorsa çalışmaz. (ilk dönüş yapılır)
Fabio Dalla Libera

Coolinear kasanın iki olasılığı vardır: örtüşmeyen ve örtüşmeyen. İlk omuz ikinci yanlış olanı döndürür. Kodunuzda bu test edilmemiştir. burada çoğu cevap olarak her zaman yanlış döndürür. Hiçbir çözümün gerçekten işe yaramadığı bir utanç.
AlexWien

3
Tüm bunların neden s32_yneye benzediğini açıklayan bir şey yerine bu kadar belirsiz değişken adları kullandığını bana aydınlatabilir misiniz point2YDifference?
Supuhstar

40

Soru C: İki çizgi parçasının kesişip kesişmediğini nasıl tespit ediyorsunuz?

Aynı konuyu araştırdım ve cevaplardan memnun değildim. Bu yüzden, iki çizgi parçasının çok sayıda görüntü ile kesişip kesişmediğini nasıl kontrol edeceğimizi açıklayan bir makale yazdım . Tam (ve test edilmiş) Java kodu var.

İşte en önemli bölümlere kırpılmış makale:

A çizgi segmentinin b çizgi segmentiyle kesişip kesişmediğini kontrol eden algoritma şöyle görünür:

Resim açıklamasını buraya girin

Sınırlayıcı kutular nedir? İki çizgi parçasının iki sınırlayıcı kutusu:

resim açıklamasını buraya girin

Her iki sınırlayıcı kutunun kesişimi varsa, çizgi parçasını a bir nokta (0 | 0) olacak şekilde taşırsınız. Şimdi a ile tanımlanan başlangıç ​​noktasında bir çizginiz var. Şimdi çizgi parçasını b aynı şekilde hareket ettirin ve çizgi parçasının b yeni noktalarının a çizgisinin farklı tarafında olup olmadığını kontrol edin. Bu durumda, tam tersini kontrol edin. Bu durumda, çizgi segmentleri kesişir. Aksi takdirde kesişmezler.

Soru A: İki çizgi parçası nerede kesişiyor?

İki çizgi parçasının a ve b kesiştiğini biliyorsunuz. Bunu bilmiyorsanız, "Soru C" de verdiğim araçlarla kontrol edin.

Şimdi bazı durumlarda geçebilir ve 7. sınıf matematik ile çözüm alabilirsiniz ( kod ve interaktif örnek bakınız ).

Soru B: İki çizginin kesişip kesişmediğini nasıl tespit ediyorsunuz?

Senin noktası diyelim A = (x1, y1), gelin B = (x2, y2), C = (x_3, y_3), D = (x_4, y_4). İlk satırınız AB (A! = B ile) ve ikincisi CD (C! = D ile) ile tanımlanır.

function doLinesIntersect(AB, CD) {
    if (x1 == x2) {
        return !(x3 == x4 && x1 != x3);
    } else if (x3 == x4) {
        return true;
    } else {
        // Both lines are not parallel to the y-axis
        m1 = (y1-y2)/(x1-x2);
        m2 = (y3-y4)/(x3-x4);
        return m1 != m2;
    }
}

Soru D: İki çizgi nerede kesişiyor?

Kesişip kesmediklerini Soru B ile kontrol edin.

A ve b çizgileri her çizgi için iki nokta ile tanımlanır. Temel olarak Soru A'da kullanılan aynı mantığı uygulayabilirsiniz.


15
Açıkça söylemek gerekirse, bu cevaptaki Soru B, çizgi kesimleriyle değil, kesişen iki çizgi ile ilgilidir. Şikayet etmiyorum; bu yanlış değil. Sadece kimsenin yanıltılmasını istemiyorum.
phord

1
"C sorusu" yok. Ve Soru D sadece Soru A'ya geri döner
Konrad Viltersten

21

Bir zamanlar burada kabul edilen cevap yanlıştır (o zamandan beri kabul edilmedi, bu yüzden yaşasın!). Tüm kavşakları doğru şekilde ortadan kaldırmaz. Önemsiz olarak işe yarıyor gibi görünebilir, ancak özellikle 0 ve 1'in h için geçerli kabul edilmesi durumunda başarısız olabilir.

Aşağıdaki durumu düşünün:

(4,1) - (5,1) ve (0,0) - (0,2) 'deki hatlar

Bunlar açıkça örtüşmeyen dik çizgilerdir.

A = (4,1)
B = (5,1)
C = (0,0)
D = (0,2)
E = (5,1) - (4,1) = (- 1,0)
F = (0,2) - (0,0) = (0, -2)
P = (0,1)
h = ((4,1) - (0,0)) nokta (0,1) / ((0 , -2) nokta (0,1)) = 0

Yukarıdaki cevaba göre, bu iki çizgi parçası bir bitiş noktasında (0 ve 1 değerleri) buluşuyor. Bu son nokta şöyle olacaktır:

(0,0) + (0, -2) 0 = (0,0)

Yani, görünüşe göre iki çizgi parçası, hat CD'sinde olan, ancak AB hattı üzerinde olmayan (0,0) 'da buluşuyor. Peki yanlış olan ne? Cevap, 0 ve 1 değerlerinin geçerli olmadığı ve sadece bazen uç nokta kavşağını doğru tahmin etmek için HAPPEN olmasıdır. Bir çizginin uzantısı (diğerinin değil) çizgi parçasını karşıladığında, algoritma çizgi parçalarının kesişimini tahmin eder, ancak bu doğru değildir. AB vs CD ile başlayıp daha sonra CD vs AB ile test ederek bu sorunun ortadan kaldırılacağını hayal ediyorum. Sadece her ikisi de 0 ile 1 arasındaysa kesiştiği söylenebilir.

Uç noktaları tahmin etmeniz gerekiyorsa vektör çapraz ürün yöntemini kullanmanızı öneririm.

-Dan


4
"Kabul edilen" cevap değişebilir, bu yüzden başka bir şey demelisiniz. (Aslında, yorumundan bu yana değiştiğini düşünüyorum)
Johannes Hoff

14

İMalc'in cevabının Python sürümü:

def find_intersection( p0, p1, p2, p3 ) :

    s10_x = p1[0] - p0[0]
    s10_y = p1[1] - p0[1]
    s32_x = p3[0] - p2[0]
    s32_y = p3[1] - p2[1]

    denom = s10_x * s32_y - s32_x * s10_y

    if denom == 0 : return None # collinear

    denom_is_positive = denom > 0

    s02_x = p0[0] - p2[0]
    s02_y = p0[1] - p2[1]

    s_numer = s10_x * s02_y - s10_y * s02_x

    if (s_numer < 0) == denom_is_positive : return None # no collision

    t_numer = s32_x * s02_y - s32_y * s02_x

    if (t_numer < 0) == denom_is_positive : return None # no collision

    if (s_numer > denom) == denom_is_positive or (t_numer > denom) == denom_is_positive : return None # no collision


    # collision detected

    t = t_numer / denom

    intersection_point = [ p0[0] + (t * s10_x), p0[1] + (t * s10_y) ]


    return intersection_point

Numaralarınızı yüzer hale getirmeniz veya kullanmak için 8. satırı değiştirmeniz gerektiğini unutmayındenom = float(...)
Jonno_FTW

11

İki çizgi parçasının doğru kesişim noktasını bulmak, çok sayıda kenar durumu olan önemsiz bir görevdir. İşte Java'da iyi belgelenmiş, çalışan ve test edilmiş bir çözüm.

Özünde, iki çizgi parçasının kesişimini bulurken olabilecek üç şey vardır:

  1. Segmentler kesişmiyor

  2. Eşsiz bir kavşak noktası var

  3. Kavşak başka bir segmenttir

NOT : Kodda, x1 = x2 ve y1 = y2 olan bir çizgi parçasının (x1, y1), (x2, y2) geçerli bir çizgi parçası olduğunu varsayıyorum. Matematiksel olarak konuşursak, bir çizgi segmenti farklı noktalardan oluşur, ancak segmentlerin bu uygulamada bütünlük için nokta olmasına izin veriyorum.

Kod github deposumdan alındı

/**
 * This snippet finds the intersection of two line segments.
 * The intersection may either be empty, a single point or the
 * intersection is a subsegment there's an overlap.
 */

import static java.lang.Math.abs;
import static java.lang.Math.max;
import static java.lang.Math.min;

import java.util.ArrayList;
import java.util.List;

public class LineSegmentLineSegmentIntersection {

  // Small epsilon used for double value comparison.
  private static final double EPS = 1e-5;

  // 2D Point class.
  public static class Pt {
    double x, y;
    public Pt(double x, double y) {
      this.x = x; 
      this.y = y;
    }
    public boolean equals(Pt pt) {
      return abs(x - pt.x) < EPS && abs(y - pt.y) < EPS;
    }
  }

  // Finds the orientation of point 'c' relative to the line segment (a, b)
  // Returns  0 if all three points are collinear.
  // Returns -1 if 'c' is clockwise to segment (a, b), i.e right of line formed by the segment.
  // Returns +1 if 'c' is counter clockwise to segment (a, b), i.e left of line
  // formed by the segment.
  public static int orientation(Pt a, Pt b, Pt c) {
    double value = (b.y - a.y) * (c.x - b.x) - 
                   (b.x - a.x) * (c.y - b.y);
    if (abs(value) < EPS) return 0;
    return (value > 0) ? -1 : +1;
  }

  // Tests whether point 'c' is on the line segment (a, b).
  // Ensure first that point c is collinear to segment (a, b) and
  // then check whether c is within the rectangle formed by (a, b)
  public static boolean pointOnLine(Pt a, Pt b, Pt c) {
    return orientation(a, b, c) == 0 && 
           min(a.x, b.x) <= c.x && c.x <= max(a.x, b.x) && 
           min(a.y, b.y) <= c.y && c.y <= max(a.y, b.y);
  }

  // Determines whether two segments intersect.
  public static boolean segmentsIntersect(Pt p1, Pt p2, Pt p3, Pt p4) {

    // Get the orientation of points p3 and p4 in relation
    // to the line segment (p1, p2)
    int o1 = orientation(p1, p2, p3);
    int o2 = orientation(p1, p2, p4);
    int o3 = orientation(p3, p4, p1);
    int o4 = orientation(p3, p4, p2);

    // If the points p1, p2 are on opposite sides of the infinite
    // line formed by (p3, p4) and conversly p3, p4 are on opposite
    // sides of the infinite line formed by (p1, p2) then there is
    // an intersection.
    if (o1 != o2 && o3 != o4) return true;

    // Collinear special cases (perhaps these if checks can be simplified?)
    if (o1 == 0 && pointOnLine(p1, p2, p3)) return true;
    if (o2 == 0 && pointOnLine(p1, p2, p4)) return true;
    if (o3 == 0 && pointOnLine(p3, p4, p1)) return true;
    if (o4 == 0 && pointOnLine(p3, p4, p2)) return true;

    return false;
  }

  public static List<Pt> getCommonEndpoints(Pt p1, Pt p2, Pt p3, Pt p4) {

    List<Pt> points = new ArrayList<>();

    if (p1.equals(p3)) {
      points.add(p1);
      if (p2.equals(p4)) points.add(p2);

    } else if (p1.equals(p4)) {
      points.add(p1);
      if (p2.equals(p3)) points.add(p2);

    } else if (p2.equals(p3)) {
      points.add(p2);
      if (p1.equals(p4)) points.add(p1);

    } else if (p2.equals(p4)) {
      points.add(p2);
      if (p1.equals(p3)) points.add(p1);
    }

    return points;
  }

  // Finds the intersection point(s) of two line segments. Unlike regular line 
  // segments, segments which are points (x1 = x2 and y1 = y2) are allowed.
  public static Pt[] lineSegmentLineSegmentIntersection(Pt p1, Pt p2, Pt p3, Pt p4) {

    // No intersection.
    if (!segmentsIntersect(p1, p2, p3, p4)) return new Pt[]{};

    // Both segments are a single point.
    if (p1.equals(p2) && p2.equals(p3) && p3.equals(p4))
      return new Pt[]{p1};

    List<Pt> endpoints = getCommonEndpoints(p1, p2, p3, p4);
    int n = endpoints.size();

    // One of the line segments is an intersecting single point.
    // NOTE: checking only n == 1 is insufficient to return early
    // because the solution might be a sub segment.
    boolean singleton = p1.equals(p2) || p3.equals(p4);
    if (n == 1 && singleton) return new Pt[]{endpoints.get(0)};

    // Segments are equal.
    if (n == 2) return new Pt[]{endpoints.get(0), endpoints.get(1)};

    boolean collinearSegments = (orientation(p1, p2, p3) == 0) && 
                                (orientation(p1, p2, p4) == 0);

    // The intersection will be a sub-segment of the two
    // segments since they overlap each other.
    if (collinearSegments) {

      // Segment #2 is enclosed in segment #1
      if (pointOnLine(p1, p2, p3) && pointOnLine(p1, p2, p4))
        return new Pt[]{p3, p4};

      // Segment #1 is enclosed in segment #2
      if (pointOnLine(p3, p4, p1) && pointOnLine(p3, p4, p2))
        return new Pt[]{p1, p2};

      // The subsegment is part of segment #1 and part of segment #2.
      // Find the middle points which correspond to this segment.
      Pt midPoint1 = pointOnLine(p1, p2, p3) ? p3 : p4;
      Pt midPoint2 = pointOnLine(p3, p4, p1) ? p1 : p2;

      // There is actually only one middle point!
      if (midPoint1.equals(midPoint2)) return new Pt[]{midPoint1};

      return new Pt[]{midPoint1, midPoint2};
    }

    /* Beyond this point there is a unique intersection point. */

    // Segment #1 is a vertical line.
    if (abs(p1.x - p2.x) < EPS) {
      double m = (p4.y - p3.y) / (p4.x - p3.x);
      double b = p3.y - m * p3.x;
      return new Pt[]{new Pt(p1.x, m * p1.x + b)};
    }

    // Segment #2 is a vertical line.
    if (abs(p3.x - p4.x) < EPS) {
      double m = (p2.y - p1.y) / (p2.x - p1.x);
      double b = p1.y - m * p1.x;
      return new Pt[]{new Pt(p3.x, m * p3.x + b)};
    }

    double m1 = (p2.y - p1.y) / (p2.x - p1.x);
    double m2 = (p4.y - p3.y) / (p4.x - p3.x);
    double b1 = p1.y - m1 * p1.x;
    double b2 = p3.y - m2 * p3.x;
    double x = (b2 - b1) / (m1 - m2);
    double y = (m1 * b2 - m2 * b1) / (m1 - m2);

    return new Pt[]{new Pt(x, y)};
  }

}

İşte basit bir kullanım örneği:

  public static void main(String[] args) {

    // Segment #1 is (p1, p2), segment #2 is (p3, p4)
    Pt p1, p2, p3, p4;

    p1 = new Pt(-2, 4); p2 = new Pt(3, 3);
    p3 = new Pt(0, 0);  p4 = new Pt(2, 4);
    Pt[] points = lineSegmentLineSegmentIntersection(p1, p2, p3, p4);
    Pt point = points[0];

    // Prints: (1.636, 3.273)
    System.out.printf("(%.3f, %.3f)\n", point.x, point.y);

    p1 = new Pt(-10, 0); p2 = new Pt(+10, 0);
    p3 = new Pt(-5, 0);  p4 = new Pt(+5, 0);
    points = lineSegmentLineSegmentIntersection(p1, p2, p3, p4);
    Pt point1 = points[0], point2 = points[1];

    // Prints: (-5.000, 0.000) (5.000, 0.000)
    System.out.printf("(%.3f, %.3f) (%.3f, %.3f)\n", point1.x, point1.y, point2.x, point2.y);
  }

coğrafi koordinat sistemim için çalıştı! Teşekkürler! Ama bu sonsuz çizgi kesişimi için ve ben daha sonlu çizgi kesişimi arıyorum.
M. Usman Khan

8

Sadece Sayısal Tarifler serisinde iyi bir açıklama ve açık bir çözüm bulunabileceğini belirtmek istedim. 3. baskıyı aldım ve cevap sayfa 1117, bölüm 21.4'te. Farklı bir isimlendirmeye sahip başka bir çözüm Marina Gavrilova Güvenilir Hat Kesitli Kesişim Testi ile bir makalede bulunabilir . Onun çözümü, bence, biraz daha basit.

Uygulamam aşağıda:

bool NuGeometry::IsBetween(const double& x0, const double& x, const double& x1){
   return (x >= x0) && (x <= x1);
}

bool NuGeometry::FindIntersection(const double& x0, const double& y0, 
     const double& x1, const double& y1,
     const double& a0, const double& b0, 
     const double& a1, const double& b1, 
     double& xy, double& ab) {
   // four endpoints are x0, y0 & x1,y1 & a0,b0 & a1,b1
   // returned values xy and ab are the fractional distance along xy and ab
   // and are only defined when the result is true

   bool partial = false;
   double denom = (b0 - b1) * (x0 - x1) - (y0 - y1) * (a0 - a1);
   if (denom == 0) {
      xy = -1;
      ab = -1;
   } else {
      xy = (a0 * (y1 - b1) + a1 * (b0 - y1) + x1 * (b1 - b0)) / denom;
      partial = NuGeometry::IsBetween(0, xy, 1);
      if (partial) {
         // no point calculating this unless xy is between 0 & 1
         ab = (y1 * (x0 - a1) + b1 * (x1 - x0) + y0 * (a1 - x1)) / denom; 
      }
   }
   if ( partial && NuGeometry::IsBetween(0, ab, 1)) {
      ab = 1-ab;
      xy = 1-xy;
      return true;
   }  else return false;
}

P1 = (0,0), p2 = (10,0), p3 = (9,0), p4 = (20,0)
padmalcom

"Çalışmıyor" tanımınıza bağlı sanırım. Denom 0'dır, bu yüzden kesişmediği için bana doğru görünen yanlış döndürür. Colinear kesişme ile aynı şey değildir.
marcp

8

Yukarıda çok sayıda çözüm mevcuttur, ancak aşağıda çözümün oldukça basit ve anlaşılması kolay olduğunu düşünüyorum.

İki segment Vektör AB ve Vektör CD'si yalnızca ve yalnızca

  1. A ve b uç noktaları, segment CD'sinin karşı taraflarındadır.
  2. C ve d uç noktaları AB segmentinin karşı tarafındadır.

Daha spesifik olarak a ve b, sadece iki üçlü a, c, d ve b, c, d saatlerinin tam olarak saatin tersi yönde olması halinde segment CD'sinin karşı tarafındadır.

Intersect(a, b, c, d)
 if CCW(a, c, d) == CCW(b, c, d)
    return false;
 else if CCW(a, b, c) == CCW(a, b, d)
    return false;
 else
    return true;

Burada CCW saat yönünün tersini temsil eder, bu da noktaların yönüne bağlı olarak true / false döndürür.

Kaynak: http://compgeom.cs.uiuc.edu/~jeffe/teaching/373/notes/x06-sweepline.pdf Sayfa 2


2
Bence biraz daha spesifik olmalısın: CCWTest nasıl tanımlanır? Dış ürünün işareti ile?
ocramz

Teşekkürler; bu sahte kod Scratch'ta çok basit bir uygulamaya izin verdi; bu projeye bakın: scratch.mit.edu/projects/129319027
Ruud Helderman

8

C ve Amaç-C

Gareth Rees'ın cevabına dayanarak

const AGKLine AGKLineZero = (AGKLine){(CGPoint){0.0, 0.0}, (CGPoint){0.0, 0.0}};

AGKLine AGKLineMake(CGPoint start, CGPoint end)
{
    return (AGKLine){start, end};
}

double AGKLineLength(AGKLine l)
{
    return CGPointLengthBetween_AGK(l.start, l.end);
}

BOOL AGKLineIntersection(AGKLine l1, AGKLine l2, CGPoint *out_pointOfIntersection)
{
    // http://stackoverflow.com/a/565282/202451

    CGPoint p = l1.start;
    CGPoint q = l2.start;
    CGPoint r = CGPointSubtract_AGK(l1.end, l1.start);
    CGPoint s = CGPointSubtract_AGK(l2.end, l2.start);

    double s_r_crossProduct = CGPointCrossProductZComponent_AGK(r, s);
    double t = CGPointCrossProductZComponent_AGK(CGPointSubtract_AGK(q, p), s) / s_r_crossProduct;
    double u = CGPointCrossProductZComponent_AGK(CGPointSubtract_AGK(q, p), r) / s_r_crossProduct;

    if(t < 0 || t > 1.0 || u < 0 || u > 1.0)
    {
        if(out_pointOfIntersection != NULL)
        {
            *out_pointOfIntersection = CGPointZero;
        }
        return NO;
    }
    else
    {
        if(out_pointOfIntersection != NULL)
        {
            CGPoint i = CGPointAdd_AGK(p, CGPointMultiply_AGK(r, t));
            *out_pointOfIntersection = i;
        }
        return YES;
    }
}

CGFloat CGPointCrossProductZComponent_AGK(CGPoint v1, CGPoint v2)
{
    return v1.x * v2.y - v1.y * v2.x;
}

CGPoint CGPointSubtract_AGK(CGPoint p1, CGPoint p2)
{
    return (CGPoint){p1.x - p2.x, p1.y - p2.y};
}

CGPoint CGPointAdd_AGK(CGPoint p1, CGPoint p2)
{
    return (CGPoint){p1.x + p2.x, p1.y + p2.y};
}

CGFloat CGPointCrossProductZComponent_AGK(CGPoint v1, CGPoint v2)
{
    return v1.x * v2.y - v1.y * v2.x;
}

CGPoint CGPointMultiply_AGK(CGPoint p1, CGFloat factor)
{
    return (CGPoint){p1.x * factor, p1.y * factor};
}

İşlevlerin ve yapıların birçoğu özeldir, ancak neler olduğunu bilmeniz oldukça kolay olmalıdır. Bu repoda herkese açıktır https://github.com/hfossli/AGGeometryKit/


Bu kodda AGPointZero nereden geliyor?
seanicus

1
@seanicus bunun yerine CGPoint kullanmak için güncellenmiş örnek
hfossli

6

Bu benim için iyi çalışıyor. Buradan alındı .

 // calculates intersection and checks for parallel lines.  
 // also checks that the intersection point is actually on  
 // the line segment p1-p2  
 Point findIntersection(Point p1,Point p2,  
   Point p3,Point p4) {  
   float xD1,yD1,xD2,yD2,xD3,yD3;  
   float dot,deg,len1,len2;  
   float segmentLen1,segmentLen2;  
   float ua,ub,div;  

   // calculate differences  
   xD1=p2.x-p1.x;  
   xD2=p4.x-p3.x;  
   yD1=p2.y-p1.y;  
   yD2=p4.y-p3.y;  
   xD3=p1.x-p3.x;  
   yD3=p1.y-p3.y;    

   // calculate the lengths of the two lines  
   len1=sqrt(xD1*xD1+yD1*yD1);  
   len2=sqrt(xD2*xD2+yD2*yD2);  

   // calculate angle between the two lines.  
   dot=(xD1*xD2+yD1*yD2); // dot product  
   deg=dot/(len1*len2);  

   // if abs(angle)==1 then the lines are parallell,  
   // so no intersection is possible  
   if(abs(deg)==1) return null;  

   // find intersection Pt between two lines  
   Point pt=new Point(0,0);  
   div=yD2*xD1-xD2*yD1;  
   ua=(xD2*yD3-yD2*xD3)/div;  
   ub=(xD1*yD3-yD1*xD3)/div;  
   pt.x=p1.x+ua*xD1;  
   pt.y=p1.y+ua*yD1;  

   // calculate the combined length of the two segments  
   // between Pt-p1 and Pt-p2  
   xD1=pt.x-p1.x;  
   xD2=pt.x-p2.x;  
   yD1=pt.y-p1.y;  
   yD2=pt.y-p2.y;  
   segmentLen1=sqrt(xD1*xD1+yD1*yD1)+sqrt(xD2*xD2+yD2*yD2);  

   // calculate the combined length of the two segments  
   // between Pt-p3 and Pt-p4  
   xD1=pt.x-p3.x;  
   xD2=pt.x-p4.x;  
   yD1=pt.y-p3.y;  
   yD2=pt.y-p4.y;  
   segmentLen2=sqrt(xD1*xD1+yD1*yD1)+sqrt(xD2*xD2+yD2*yD2);  

   // if the lengths of both sets of segments are the same as  
   // the lenghts of the two lines the point is actually  
   // on the line segment.  

   // if the point isn’t on the line, return null  
   if(abs(len1-segmentLen1)>0.01 || abs(len2-segmentLen2)>0.01)  
     return null;  

   // return the valid intersection  
   return pt;  
 }  

 class Point{  
   float x,y;  
   Point(float x, float y){  
     this.x = x;  
     this.y = y;  
   }  

   void set(float x, float y){  
     this.x = x;  
     this.y = y;  
   }  
 }  

8
Bu kodla ilgili birkaç sorun var. Sıfıra bölme nedeniyle bir istisna oluşturabilir; yavaştır, çünkü kare kökleri alır; ve bazen bir fudge faktörü kullandığından yanlış pozitif döndürür. Bundan daha iyisini yapabilirsin!
Gareth Rees

Bir çözüm olarak tamam ama Jason tarafından verilen bu kesinlikle hesaplama açısından daha hızlı ve bu çözümle ilgili birçok sorunu önlüyor
Elemental

6

Bu cevaplardan bazılarını denedim, ama benim için çalışmadılar (üzgünüm çocuklar); Biraz daha net arama yaptıktan sonra buldum bu .

Onun kodunda küçük bir değişiklik ile ben şimdi kavşak noktasını döndürecek bu işlevi var ya da hiçbir kavşak bulunamazsa -1, -1 dönecektir.

    Public Function intercetion(ByVal ax As Integer, ByVal ay As Integer, ByVal bx As Integer, ByVal by As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal dx As Integer, ByVal dy As Integer) As Point
    '//  Determines the intersection point of the line segment defined by points A and B
    '//  with the line segment defined by points C and D.
    '//
    '//  Returns YES if the intersection point was found, and stores that point in X,Y.
    '//  Returns NO if there is no determinable intersection point, in which case X,Y will
    '//  be unmodified.

    Dim distAB, theCos, theSin, newX, ABpos As Double

    '//  Fail if either line segment is zero-length.
    If ax = bx And ay = by Or cx = dx And cy = dy Then Return New Point(-1, -1)

    '//  Fail if the segments share an end-point.
    If ax = cx And ay = cy Or bx = cx And by = cy Or ax = dx And ay = dy Or bx = dx And by = dy Then Return New Point(-1, -1)

    '//  (1) Translate the system so that point A is on the origin.
    bx -= ax
    by -= ay
    cx -= ax
    cy -= ay
    dx -= ax
    dy -= ay

    '//  Discover the length of segment A-B.
    distAB = Math.Sqrt(bx * bx + by * by)

    '//  (2) Rotate the system so that point B is on the positive X axis.
    theCos = bx / distAB
    theSin = by / distAB
    newX = cx * theCos + cy * theSin
    cy = cy * theCos - cx * theSin
    cx = newX
    newX = dx * theCos + dy * theSin
    dy = dy * theCos - dx * theSin
    dx = newX

    '//  Fail if segment C-D doesn't cross line A-B.
    If cy < 0 And dy < 0 Or cy >= 0 And dy >= 0 Then Return New Point(-1, -1)

    '//  (3) Discover the position of the intersection point along line A-B.
    ABpos = dx + (cx - dx) * dy / (dy - cy)

    '//  Fail if segment C-D crosses line A-B outside of segment A-B.
    If ABpos < 0 Or ABpos > distAB Then Return New Point(-1, -1)

    '//  (4) Apply the discovered position to line A-B in the original coordinate system.
    '*X=Ax+ABpos*theCos
    '*Y=Ay+ABpos*theSin

    '//  Success.
    Return New Point(ax + ABpos * theCos, ay + ABpos * theSin)
End Function

6

Gavin'in cevabına , cortijon'un yorumlarda bir javascript sürümü önerdiği ve iMalc'ın biraz daha az hesaplama içeren bir sürüm sağladığı bazı ilgileri var gibi görünüyor . Bazıları çeşitli kod önerileriyle ilgili eksikliklere dikkat çekerken, diğerleri bazı kod önerilerinin etkinliği hakkında yorum yaptı.

Gavin cevabı aracılığıyla iMalc tarafından sağlanan algoritma şu anda bir javascript projesinde kullanıyorum ve ben sadece kimseye yardımcı olabilir eğer burada temiz bir versiyonu sağlamak istedim.

// Some variables for reuse, others may do this differently
var p0x, p1x, p2x, p3x, ix,
    p0y, p1y, p2y, p3y, iy,
    collisionDetected;

// do stuff, call other functions, set endpoints...

// note: for my purpose I use |t| < |d| as opposed to
// |t| <= |d| which is equivalent to 0 <= t < 1 rather than
// 0 <= t <= 1 as in Gavin's answer - results may vary

var lineSegmentIntersection = function(){
    var d, dx1, dx2, dx3, dy1, dy2, dy3, s, t;

    dx1 = p1x - p0x;      dy1 = p1y - p0y;
    dx2 = p3x - p2x;      dy2 = p3y - p2y;
    dx3 = p0x - p2x;      dy3 = p0y - p2y;

    collisionDetected = 0;

    d = dx1 * dy2 - dx2 * dy1;

    if(d !== 0){
        s = dx1 * dy3 - dx3 * dy1;
        if((s <= 0 && d < 0 && s >= d) || (s >= 0 && d > 0 && s <= d)){
            t = dx2 * dy3 - dx3 * dy2;
            if((t <= 0 && d < 0 && t > d) || (t >= 0 && d > 0 && t < d)){
                t = t / d;
                collisionDetected = 1;
                ix = p0x + t * dx1;
                iy = p0y + t * dy1;
            }
        }
    }
};

Böyle çizgilerle neler olduğunu nasıl anlayabileceğinizi anlamıyorum t = dx2 * dy3 - dx3 * dy2;...
Supuhstar

@Supuhstar Vektör matematiği ve nokta çarpımı ve çapraz çarpım tanımı ile ilgilidir. Örneğin, gönderdiğiniz kod bir çapraz ürün işlemini temsil eder. Bu, bir çizgi parçasını diğerinin üzerine, diğer çizgi parçasının neresinde düştüğünü belirlemek için, ortada veya çizgiden sonraki başlangıç ​​noktasından önce yansıtmanın bir yoludur. Yani t normalleştirilmiş bir değerdir. 0 ile 1 arasındaysa, iki segment kesişir. 0'dan küçük veya birden büyükse, yapmazlar.
Nolo

@Supuhstar Ayrıca, projeksiyonun gerçek noktayı bulabilmesi için sonucun ölçeklendirilmesi gerektiğini unutmayın. İşte t/d
devreye

1
Yani böyle değişken isimlerle neler olduğunu bir bakışta nasıl anlıyorsunuz? Neden bir şey gibi crossProduct = (line1XDifference * line2YDifference) - (line2XDifference * line1YDifference)ve scaledResult = crossProduct / dotProduct?
Supuhstar

1
@Supuhstar Ah, ne demek istediğini anlıyorum. Ee, sanırım verimlilik konusunda takıntı yapmanın ötesinde konuşmak için gerçekten iyi bir neden yok, ama bu kendi başına çok iyi bir neden değil çünkü derleyiciler onlara verdiğiniz herhangi bir kodu almak ve onu verimli hale getirmek için oldukça iyi bir iş çıkarıyor ne değişmezken mümkün hesaplamak gerekir. Öte yandan, isimler p1x, p1yvb yüzden, onların x ve y değerleri ile noktalarını açıklamak içindir p1xkısaltmasıdır point1xaynı şekilde, d1xzihnim Yunan harfi için bir kısaltmadır içinde, deltaXya da diyebiliriz differenceInX. (diğer)
Nolo

5

Bu sorun için çok daha basit bir çözüm olduğunu düşünüyorum. Bugün başka bir fikir buldum ve gayet iyi çalışıyor gibi görünüyor (en azından şimdilik 2D). Yapmanız gereken tek şey, iki çizgi arasındaki kesişmeyi hesaplamak, ardından hesaplanan kesişme noktasının her iki çizgi parçasının sınır kutuları içinde olup olmadığını kontrol etmektir. Öyleyse, çizgi segmentleri kesişir. Bu kadar.

DÜZENLE:

Bu kavşak hesaplamak nasıl (artık bu kod snippet'i nerede buldum bilmiyorum)

Point3D

gelen

System.Windows.Media.Media3D

public static Point3D? Intersection(Point3D start1, Point3D end1, Point3D start2, Point3D end2) {

        double a1 = end1.Y - start1.Y;
        double b1 = start1.X - end1.X;
        double c1 = a1 * start1.X + b1 * start1.Y;

        double a2 = end2.Y - start2.Y;
        double b2 = start2.X - end2.X;
        double c2 = a2 * start2.X + b2 * start2.Y;

        double det = a1 * b2 - a2 * b1;
        if (det == 0) { // lines are parallel
            return null;
        }

        double x = (b2 * c1 - b1 * c2) / det;
        double y = (a1 * c2 - a2 * c1) / det;

        return new Point3D(x, y, 0.0);
    }

ve bu benim (cevap amacıyla basitleştirilmiş) BoundingBox sınıfı:

public class BoundingBox {
    private Point3D min = new Point3D();
    private Point3D max = new Point3D();

    public BoundingBox(Point3D point) {
        min = point;
        max = point;
    }

    public Point3D Min {
        get { return min; }
        set { min = value; }
    }

    public Point3D Max {
        get { return max; }
        set { max = value; }
    }

    public bool Contains(BoundingBox box) {
        bool contains =
            min.X <= box.min.X && max.X >= box.max.X &&
            min.Y <= box.min.Y && max.Y >= box.max.Y &&
            min.Z <= box.min.Z && max.Z >= box.max.Z;
        return contains;
    }

    public bool Contains(Point3D point) {
        return Contains(new BoundingBox(point));
    }

}

3

Bu çözüm yardımcı olabilir

public static float GetLineYIntesept(PointF p, float slope)
    {
        return p.Y - slope * p.X;
    }

    public static PointF FindIntersection(PointF line1Start, PointF line1End, PointF line2Start, PointF line2End)
    {

        float slope1 = (line1End.Y - line1Start.Y) / (line1End.X - line1Start.X);
        float slope2 = (line2End.Y - line2Start.Y) / (line2End.X - line2Start.X);

        float yinter1 = GetLineYIntesept(line1Start, slope1);
        float yinter2 = GetLineYIntesept(line2Start, slope2);

        if (slope1 == slope2 && yinter1 != yinter2)
            return PointF.Empty;

        float x = (yinter2 - yinter1) / (slope1 - slope2);

        float y = slope1 * x + yinter1;

        return new PointF(x, y);
    }

3

Kris'in yukarıdaki cevabını JavaScript'e taşıdım. Çok sayıda farklı cevap denedikten sonra, doğru puanları verdi. İhtiyacım olan puanları alamadığım için delirdiğimi sanıyordum.

function getLineLineCollision(p0, p1, p2, p3) {
    var s1, s2;
    s1 = {x: p1.x - p0.x, y: p1.y - p0.y};
    s2 = {x: p3.x - p2.x, y: p3.y - p2.y};

    var s10_x = p1.x - p0.x;
    var s10_y = p1.y - p0.y;
    var s32_x = p3.x - p2.x;
    var s32_y = p3.y - p2.y;

    var denom = s10_x * s32_y - s32_x * s10_y;

    if(denom == 0) {
        return false;
    }

    var denom_positive = denom > 0;

    var s02_x = p0.x - p2.x;
    var s02_y = p0.y - p2.y;

    var s_numer = s10_x * s02_y - s10_y * s02_x;

    if((s_numer < 0) == denom_positive) {
        return false;
    }

    var t_numer = s32_x * s02_y - s32_y * s02_x;

    if((t_numer < 0) == denom_positive) {
        return false;
    }

    if((s_numer > denom) == denom_positive || (t_numer > denom) == denom_positive) {
        return false;
    }

    var t = t_numer / denom;

    var p = {x: p0.x + (t * s10_x), y: p0.y + (t * s10_y)};
    return p;
}

2

Çok yol denedim ve sonra kendi yolumu yazmaya karar verdim. İşte burada:

bool IsBetween (float x, float b1, float b2)
{
   return ( ((x >= (b1 - 0.1f)) && 
        (x <= (b2 + 0.1f))) || 
        ((x >= (b2 - 0.1f)) &&
        (x <= (b1 + 0.1f))));
}

bool IsSegmentsColliding(   POINTFLOAT lineA,
                POINTFLOAT lineB,
                POINTFLOAT line2A,
                POINTFLOAT line2B)
{
    float deltaX1 = lineB.x - lineA.x;
    float deltaX2 = line2B.x - line2A.x;
    float deltaY1 = lineB.y - lineA.y;
    float deltaY2 = line2B.y - line2A.y;

    if (abs(deltaX1) < 0.01f && 
        abs(deltaX2) < 0.01f) // Both are vertical lines
        return false;
    if (abs((deltaY1 / deltaX1) -
        (deltaY2 / deltaX2)) < 0.001f) // Two parallel line
        return false;

    float xCol = (  (   (deltaX1 * deltaX2) * 
                        (line2A.y - lineA.y)) - 
                    (line2A.x * deltaY2 * deltaX1) + 
                    (lineA.x * deltaY1 * deltaX2)) / 
                 ((deltaY1 * deltaX2) - (deltaY2 * deltaX1));
    float yCol = 0;
    if (deltaX1 < 0.01f) // L1 is a vertical line
        yCol = ((xCol * deltaY2) + 
                (line2A.y * deltaX2) - 
                (line2A.x * deltaY2)) / deltaX2;
    else // L1 is acceptable
        yCol = ((xCol * deltaY1) +
                (lineA.y * deltaX1) -
                (lineA.x * deltaY1)) / deltaX1;

    bool isCol =    IsBetween(xCol, lineA.x, lineB.x) &&
            IsBetween(yCol, lineA.y, lineB.y) &&
            IsBetween(xCol, line2A.x, line2B.x) &&
            IsBetween(yCol, line2A.y, line2B.y);
    return isCol;
}

Bu iki formüle dayanarak: (Onları çizgi ve diğer formüllerin denkleminden sadeleştirdim)

x için formül

y için formül


Çalışır, ancak bu koordinatı girmeye çalışın (eğer doğrusal / çakışıyorsa yanlış sonuç döndürür): PointA1 = (0,0) PointA2 = (0,2) ve PointB1 = (0,1) PointB2 = (0,5)
dns

@dns Bunun nedeni, kodun paralel çizgiler için false döndürmesi. Sorunu görüyorum, ancak sonsuz sayıda cevap olduğu için fonksiyonun ne dönmesi gerektiğini hala bilmiyorum.
Soroush Falahati

2

Bu Gareth Ree'nin cevabına dayanıyor. Ayrıca, satır segmentlerinin çakışmasını da döndürür. C ++ ile kodlanan V, basit bir vektör sınıfıdır. 2D'de iki vektörün çapraz çarpımı tek bir skaler döndürür. Okullarım otomatik test sistemi tarafından test edildi ve geçti.

//Required input point must be colinear with the line
bool on_segment(const V& p, const LineSegment& l)
{
    //If a point is on the line, the sum of the vectors formed by the point to the line endpoints must be equal
    V va = p - l.pa;
    V vb = p - l.pb;
    R ma = va.magnitude();
    R mb = vb.magnitude();
    R ml = (l.pb - l.pa).magnitude();
    R s = ma + mb;
    bool r = s <= ml + epsilon;
    return r;
}

//Compute using vector math
// Returns 0 points if the lines do not intersect or overlap
// Returns 1 point if the lines intersect
//  Returns 2 points if the lines overlap, contain the points where overlapping start starts and stop
std::vector<V> intersect(const LineSegment& la, const LineSegment& lb)
{
    std::vector<V> r;

    //http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
    V oa, ob, da, db; //Origin and direction vectors
    R sa, sb; //Scalar values
    oa = la.pa;
    da = la.pb - la.pa;
    ob = lb.pa;
    db = lb.pb - lb.pa;

    if (da.cross(db) == 0 && (ob - oa).cross(da) == 0) //If colinear
    {
        if (on_segment(lb.pa, la) && on_segment(lb.pb, la))
        {
            r.push_back(lb.pa);
            r.push_back(lb.pb);
            dprintf("colinear, overlapping\n");
            return r;
        }

        if (on_segment(la.pa, lb) && on_segment(la.pb, lb))
        {
            r.push_back(la.pa);
            r.push_back(la.pb);
            dprintf("colinear, overlapping\n");
            return r;
        }

        if (on_segment(la.pa, lb))
            r.push_back(la.pa);

        if (on_segment(la.pb, lb))
            r.push_back(la.pb);

        if (on_segment(lb.pa, la))
            r.push_back(lb.pa);

        if (on_segment(lb.pb, la))
            r.push_back(lb.pb);

        if (r.size() == 0)
            dprintf("colinear, non-overlapping\n");
        else
            dprintf("colinear, overlapping\n");

        return r;
    }

    if (da.cross(db) == 0 && (ob - oa).cross(da) != 0)
    {
        dprintf("parallel non-intersecting\n");
        return r;
    }

    //Math trick db cross db == 0, which is a single scalar in 2D.
    //Crossing both sides with vector db gives:
    sa = (ob - oa).cross(db) / da.cross(db);

    //Crossing both sides with vector da gives
    sb = (oa - ob).cross(da) / db.cross(da);

    if (0 <= sa && sa <= 1 && 0 <= sb && sb <= 1)
    {
        dprintf("intersecting\n");
        r.push_back(oa + da * sa);
        return r;
    }

    dprintf("non-intersecting, non-parallel, non-colinear, non-overlapping\n");
    return r;
}

2

C # 'daki bir çizgi parçasının karşılık gelen kavşak algılama koduyla temel bir uygulaması. Bu, adlandırılan bir 2B vektör / nokta yapısı gerektirir Vector2f, ancak bunu X / Y özelliklerine sahip başka herhangi bir türle değiştirebilirsiniz. Ayrıca yerini alabilir floatiledouble bu takım elbise eğer ihtiyaçlarınız daha iyi.

Bu kod, .NET fizik kütüphanem Boing'de kullanılıyor .

public struct LineSegment2f
{
    public Vector2f From { get; }
    public Vector2f To { get; }

    public LineSegment2f(Vector2f @from, Vector2f to)
    {
        From = @from;
        To = to;
    }

    public Vector2f Delta => new Vector2f(To.X - From.X, To.Y - From.Y);

    /// <summary>
    /// Attempt to intersect two line segments.
    /// </summary>
    /// <remarks>
    /// Even if the line segments do not intersect, <paramref name="t"/> and <paramref name="u"/> will be set.
    /// If the lines are parallel, <paramref name="t"/> and <paramref name="u"/> are set to <see cref="float.NaN"/>.
    /// </remarks>
    /// <param name="other">The line to attempt intersection of this line with.</param>
    /// <param name="intersectionPoint">The point of intersection if within the line segments, or empty..</param>
    /// <param name="t">The distance along this line at which intersection would occur, or NaN if lines are collinear/parallel.</param>
    /// <param name="u">The distance along the other line at which intersection would occur, or NaN if lines are collinear/parallel.</param>
    /// <returns><c>true</c> if the line segments intersect, otherwise <c>false</c>.</returns>
    public bool TryIntersect(LineSegment2f other, out Vector2f intersectionPoint, out float t, out float u)
    {
        var p = From;
        var q = other.From;
        var r = Delta;
        var s = other.Delta;

        // t = (q − p) × s / (r × s)
        // u = (q − p) × r / (r × s)

        var denom = Fake2DCross(r, s);

        if (denom == 0)
        {
            // lines are collinear or parallel
            t = float.NaN;
            u = float.NaN;
            intersectionPoint = default(Vector2f);
            return false;
        }

        var tNumer = Fake2DCross(q - p, s);
        var uNumer = Fake2DCross(q - p, r);

        t = tNumer / denom;
        u = uNumer / denom;

        if (t < 0 || t > 1 || u < 0 || u > 1)
        {
            // line segments do not intersect within their ranges
            intersectionPoint = default(Vector2f);
            return false;
        }

        intersectionPoint = p + r * t;
        return true;
    }

    private static float Fake2DCross(Vector2f a, Vector2f b)
    {
        return a.X * b.Y - a.Y * b.X;
    }
}

1

Verilen iki çizgi parçasının kesişip kesişmediğini kontrol etmek için bir C ++ programı

#include <iostream>
using namespace std;

struct Point
{
    int x;
    int y;
};

// Given three colinear points p, q, r, the function checks if
// point q lies on line segment 'pr'
bool onSegment(Point p, Point q, Point r)
{
    if (q.x <= max(p.x, r.x) && q.x >= min(p.x, r.x) &&
        q.y <= max(p.y, r.y) && q.y >= min(p.y, r.y))
       return true;

    return false;
}

// To find orientation of ordered triplet (p, q, r).
// The function returns following values
// 0 --> p, q and r are colinear
// 1 --> Clockwise
// 2 --> Counterclockwise
int orientation(Point p, Point q, Point r)
{
    // See 10th slides from following link for derivation of the formula
    // http://www.dcs.gla.ac.uk/~pat/52233/slides/Geometry1x1.pdf
    int val = (q.y - p.y) * (r.x - q.x) -
              (q.x - p.x) * (r.y - q.y);

    if (val == 0) return 0;  // colinear

    return (val > 0)? 1: 2; // clock or counterclock wise
}

// The main function that returns true if line segment 'p1q1'
// and 'p2q2' intersect.
bool doIntersect(Point p1, Point q1, Point p2, Point q2)
{
    // Find the four orientations needed for general and
    // special cases
    int o1 = orientation(p1, q1, p2);
    int o2 = orientation(p1, q1, q2);
    int o3 = orientation(p2, q2, p1);
    int o4 = orientation(p2, q2, q1);

    // General case
    if (o1 != o2 && o3 != o4)
        return true;

    // Special Cases
    // p1, q1 and p2 are colinear and p2 lies on segment p1q1
    if (o1 == 0 && onSegment(p1, p2, q1)) return true;

    // p1, q1 and p2 are colinear and q2 lies on segment p1q1
    if (o2 == 0 && onSegment(p1, q2, q1)) return true;

    // p2, q2 and p1 are colinear and p1 lies on segment p2q2
    if (o3 == 0 && onSegment(p2, p1, q2)) return true;

     // p2, q2 and q1 are colinear and q1 lies on segment p2q2
    if (o4 == 0 && onSegment(p2, q1, q2)) return true;

    return false; // Doesn't fall in any of the above cases
}

// Driver program to test above functions
int main()
{
    struct Point p1 = {1, 1}, q1 = {10, 1};
    struct Point p2 = {1, 2}, q2 = {10, 2};

    doIntersect(p1, q1, p2, q2)? cout << "Yes\n": cout << "No\n";

    p1 = {10, 0}, q1 = {0, 10};
    p2 = {0, 0}, q2 = {10, 10};
    doIntersect(p1, q1, p2, q2)? cout << "Yes\n": cout << "No\n";

    p1 = {-5, -5}, q1 = {0, 0};
    p2 = {1, 1}, q2 = {10, 10};
    doIntersect(p1, q1, p2, q2)? cout << "Yes\n": cout << "No\n";

    return 0;
}

1

@Gareth Rees yanıtına göre, Python sürümü:

import numpy as np

def np_perp( a ) :
    b = np.empty_like(a)
    b[0] = a[1]
    b[1] = -a[0]
    return b

def np_cross_product(a, b):
    return np.dot(a, np_perp(b))

def np_seg_intersect(a, b, considerCollinearOverlapAsIntersect = False):
    # /programming/563198/how-do-you-detect-where-two-line-segments-intersect/565282#565282
    # http://www.codeproject.com/Tips/862988/Find-the-intersection-point-of-two-line-segments
    r = a[1] - a[0]
    s = b[1] - b[0]
    v = b[0] - a[0]
    num = np_cross_product(v, r)
    denom = np_cross_product(r, s)
    # If r x s = 0 and (q - p) x r = 0, then the two lines are collinear.
    if np.isclose(denom, 0) and np.isclose(num, 0):
        # 1. If either  0 <= (q - p) * r <= r * r or 0 <= (p - q) * s <= * s
        # then the two lines are overlapping,
        if(considerCollinearOverlapAsIntersect):
            vDotR = np.dot(v, r)
            aDotS = np.dot(-v, s)
            if (0 <= vDotR  and vDotR <= np.dot(r,r)) or (0 <= aDotS  and aDotS <= np.dot(s,s)):
                return True
        # 2. If neither 0 <= (q - p) * r = r * r nor 0 <= (p - q) * s <= s * s
        # then the two lines are collinear but disjoint.
        # No need to implement this expression, as it follows from the expression above.
        return None
    if np.isclose(denom, 0) and not np.isclose(num, 0):
        # Parallel and non intersecting
        return None
    u = num / denom
    t = np_cross_product(v, s) / denom
    if u >= 0 and u <= 1 and t >= 0 and t <= 1:
        res = b[0] + (s*u)
        return res
    # Otherwise, the two line segments are not parallel but do not intersect.
    return None

0

Dikdörtgenin her iki tarafı da bir çizgi segmentiyse ve kullanıcı tarafından çizilen kısım bir çizgi segmentiyse, kullanıcının çizdiği segmenti dört yan çizgi dilimi ile kesişme açısından kontrol etmeniz yeterlidir. Her bölümün başlangıç ​​ve bitiş noktaları göz önüne alındığında, bu oldukça basit bir egzersiz olmalıdır.


3
Bunun orijinal olarak çerçevelendiği gibi soruya makul bir cevap olduğunu, ancak sorunun yoğun bir şekilde düzenlendiğine göre, bu çok mantıklı değil.
GS - Monica için özür

0

T3chb0t'ın cevabına dayanarak:

int intersezione_linee(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int& p_x, int& p_y)
{
   //L1: estremi (x1,y1)(x2,y2) L2: estremi (x3,y3)(x3,y3)
   int d;
   d = (x1-x2)*(y3-y4) - (y1-y2)*(x3-x4);
   if(!d)
       return 0;
   p_x = ((x1*y2-y1*x2)*(x3-x4) - (x1-x2)*(x3*y4-y3*x4))/d;
   p_y = ((x1*y2-y1*x2)*(y3-y4) - (y1-y2)*(x3*y4-y3*x4))/d;
   return 1;
}

int in_bounding_box(int x1, int y1, int x2, int y2, int p_x, int p_y)
{
    return p_x>=x1 && p_x<=x2 && p_y>=y1 && p_y<=y2;

}

int intersezione_segmenti(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int& p_x, int& p_y)
{
    if (!intersezione_linee(x1,y1,x2,y2,x3,y3,x4,y4,p_x,p_y))
        return 0;

    return in_bounding_box(x1,y1,x2,y2,p_x,p_y) && in_bounding_box(x3,y3,x4,y4,p_x,p_y);
}

0

Bu algoritmayı "çoklu görüntü geometrisi" kitabından okudum

kullanarak metni takip etmek

'devrik işareti olarak

* nokta ürün olarak

operatör olarak kullanılırken x çapraz ürün olarak

1. satır tanımı

x_vec = (x, y) 'noktası balta + + c = 0 ile yatar

L = (a, b, c) ', noktayı (x, y, 1)' olarak homojen koordinatlar olarak belirtiriz

çizgi denklemi şu şekilde yazılabilir:

(x, y, 1) (a, b, c) '= 0 veya x' * L = 0

2. çizgilerin kesişimi

iki satırımız var L1 = (a1, b1, c1) ', L2 = (a2, b2, c2)'

x'in bir nokta, bir vektör ve x = L1 x L2 (L1 çapraz ürün L2) olduğunu varsayalım.

dikkatli olun, x her zaman 2B'lık bir noktadır, (L1xL2) üç elementli bir vektör ve x 2B'lik bir koordinattır.

üçlü ürüne göre, biliyoruz ki

L1 * (L1 x L2) = 0 ve L2 * (L1 x L2) = 0, L1, L2 ko-düzlemi nedeniyle

(L1xL2) 'yi x vektörü ile değiştiriyoruz, o zaman L1 * x = 0, L2 * x = 0 var, bu x'in hem L1 hem de L2 üzerinde yattığı anlamına gelir, x kesişim noktasıdır.

dikkatli olun, burada x homojen koordinatlardır, eğer x'in son elemanı sıfırsa, L1 ve L2'nin paralel olduğu anlamına gelir.


0

Birçok cevap tüm hesaplamaları tek bir fonksiyonda topladı. Kodunuzun başka bir yerinde kullanmak için çizgi eğimlerini, y kesişimlerini veya x kesişimlerini hesaplamanız gerekiyorsa, bu hesaplamaları fazladan yapmanız gerekir. İlgili işlevleri ayırdım, belirgin değişken isimleri kullandım ve takip etmeyi kolaylaştırmak için kodumu yorumladım. Çizgilerin uç noktalarının ötesinde kesişip kesişmediğini bilmem gerekiyordu, bu yüzden JavaScript'te:

http://jsfiddle.net/skibulk/evmqq00u/

var point_a = {x:0, y:10},
    point_b = {x:12, y:12},
    point_c = {x:10, y:0},
    point_d = {x:0, y:0},
    slope_ab = slope(point_a, point_b),
    slope_bc = slope(point_b, point_c),
    slope_cd = slope(point_c, point_d),
    slope_da = slope(point_d, point_a),
    yint_ab = y_intercept(point_a, slope_ab),
    yint_bc = y_intercept(point_b, slope_bc),
    yint_cd = y_intercept(point_c, slope_cd),
    yint_da = y_intercept(point_d, slope_da),
    xint_ab = x_intercept(point_a, slope_ab, yint_ab),
    xint_bc = x_intercept(point_b, slope_bc, yint_bc),
    xint_cd = x_intercept(point_c, slope_cd, yint_cd),
    xint_da = x_intercept(point_d, slope_da, yint_da),
    point_aa = intersect(slope_da, yint_da, xint_da, slope_ab, yint_ab, xint_ab),
    point_bb = intersect(slope_ab, yint_ab, xint_ab, slope_bc, yint_bc, xint_bc),
    point_cc = intersect(slope_bc, yint_bc, xint_bc, slope_cd, yint_cd, xint_cd),
    point_dd = intersect(slope_cd, yint_cd, xint_cd, slope_da, yint_da, xint_da);

console.log(point_a, point_b, point_c, point_d);
console.log(slope_ab, slope_bc, slope_cd, slope_da);
console.log(yint_ab, yint_bc, yint_cd, yint_da);
console.log(xint_ab, xint_bc, xint_cd, xint_da);
console.log(point_aa, point_bb, point_cc, point_dd);

function slope(point_a, point_b) {
  var i = (point_b.y - point_a.y) / (point_b.x - point_a.x);
  if (i === -Infinity) return Infinity;
  if (i === -0) return 0;
  return i;
}

function y_intercept(point, slope) {
    // Horizontal Line
    if (slope == 0) return point.y;
  // Vertical Line
    if (slope == Infinity)
  {
    // THE Y-Axis
    if (point.x == 0) return Infinity;
    // No Intercept
    return null;
  }
  // Angled Line
  return point.y - (slope * point.x);
}

function x_intercept(point, slope, yint) {
    // Vertical Line
    if (slope == Infinity) return point.x;
  // Horizontal Line
    if (slope == 0)
  {
    // THE X-Axis
    if (point.y == 0) return Infinity;
    // No Intercept
    return null;
  }
  // Angled Line
  return -yint / slope;
}

// Intersection of two infinite lines
function intersect(slope_a, yint_a, xint_a, slope_b, yint_b, xint_b) {
  if (slope_a == slope_b)
  {
    // Equal Lines
    if (yint_a == yint_b && xint_a == xint_b) return Infinity;
    // Parallel Lines
    return null;
  }
  // First Line Vertical
    if (slope_a == Infinity)
  {
    return {
        x: xint_a,
      y: (slope_b * xint_a) + yint_b
    };
  }
  // Second Line Vertical
    if (slope_b == Infinity)
  {
    return {
        x: xint_b,
      y: (slope_a * xint_b) + yint_a
    };
  }
  // Not Equal, Not Parallel, Not Vertical
  var i = (yint_b - yint_a) / (slope_a - slope_b);
  return {
    x: i,
    y: (slope_a * i) + yint_a
  };
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.