Hat çarpışmasında 2B hat nasıl algılanır?


13

Ben hem matematikte biraz geriye dönük bir flash actionscript oyun geliştiricisiyim, hem de fiziği ilginç ve havalı buluyorum.

Referans için bu benim yaptığımla benzer bir oyundur: Karışık olmayan flash oyun

Bu karışık olmayan oyunu neredeyse mantığın sonuna kadar tamamladım. Ancak, iki çizgi kesiştiğinde, kesişen veya 'karışık' çizgilere farklı bir renk göstermek için ihtiyacım var; kırmızı.

Hat segmenti çarpışmalarını tespit etmek için bir algoritma önerebilirseniz, gerçekten naziksiniz . Ben temelde 'aritmetik' den ziyade 'görsel' düşünmeyi seven biriyim :)

Düzenleme: Fikri daha açık bir şekilde iletmek için birkaç diyagram eklemek istiyorum

kavşak yok kavşak yok kesişim kavşak yok

PS: gibi bir işlev yapmaya çalışıyorum

private function isIntersecting(A:Point, B:Point, C:Point, D:Point):Boolean

Şimdiden teşekkürler.


6
Bu sorunun hayal kırıklığı görsel olmayan açıklama, ancak bir algoritma olduğunu ve onların matematik okumak için kendinize getirebilir eğer mantıklı mı: local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d O may vektör matematiğiniz zayıfsa ağır olun. Anlıyorum - görsel açıklamaları da tercih ediyorum. Bunu doodle için daha sonra zaman bulmaya çalışacağım, ancak sanatsal olarak eğimli biri bu bağlantıyı görürse ve benden önce zaman varsa, alın!
Anko

Yanıtlar:


18

Hemen hemen bu algoritmanın bir uygulaması olan aşağıdaki yöntemi kullanıyorum . C # 'dadır, ancak ActionScript'e tercüme etmek önemsiz olmalıdır.

bool IsIntersecting(Point a, Point b, Point c, Point d)
{
    float denominator = ((b.X - a.X) * (d.Y - c.Y)) - ((b.Y - a.Y) * (d.X - c.X));
    float numerator1 = ((a.Y - c.Y) * (d.X - c.X)) - ((a.X - c.X) * (d.Y - c.Y));
    float numerator2 = ((a.Y - c.Y) * (b.X - a.X)) - ((a.X - c.X) * (b.Y - a.Y));

    // Detect coincident lines (has a problem, read below)
    if (denominator == 0) return numerator1 == 0 && numerator2 == 0;

    float r = numerator1 / denominator;
    float s = numerator2 / denominator;

    return (r >= 0 && r <= 1) && (s >= 0 && s <= 1);
}

Algoritmada ince bir sorun var, bu da iki satırın çakıştığı, ancak örtüşmediği durum. Bu durumda algoritma yine de bir kesişim noktası döndürür. Bu vakayı önemsiyorsanız , stackoverflow'daki bu cevabın bunu ele alan daha karmaşık bir versiyona sahip olduğuna inanıyorum .

Düzenle

Bu algoritmadan bir sonuç alamadım, üzgünüm!

Bu garip, test ettim ve yukarıda tarif ettiğim tek bir durum dışında benim için çalışıyor. Yukarıda gönderdiğim aynı sürümü kullanarak bir test sürüşü için aldığımda bu sonuçları aldım:

resim açıklamasını buraya girin


Bu algoritmadan bir sonuç alamadım, üzgünüm!
Vishnu

4
@Vish Hangi sorunun var? Göndermeden önce algoritmanın bu tam kopyasını test ettim ve açıklanan tek durum dışında kusursuz bir şekilde çalıştı.
David Gouveia

Sonra tekrar deneyeyim, içinde biraz matematik karıştırmış olabilirim. Yakında size bildireceğim. Teşekkürler bir ton, nyways :)
Vishnu

1
İstediğiniz sonucu algoritmanızdan aldım, teşekkürler @DavidGouveia.
Vishnu

1
Ama şimdi başka bir sorunum var :)! Kesişen çizgileri kırmızı renk ve yeşil ile yapmam gerekiyor. Kavşak iyi çalışıyor. Ama şimdi anladığım gibi, (matematiksel olarak olmasa da) basit bir if-kesişen ve kesişmemiş çizgiler için kırmızı ve yeşil çizgiler koymak için işe yaramayacaktır. Sürüklediğim düğümün hem sol hem de sağ çizgisi var. Kesişen çizgilerin rengini yeşile çevirirken bir yerlerde bir şeyler ters gitti. Sanırım başka bir duruma da ihtiyacım var. Hmmm, neyse bir ton teşekkürler, bunu doğru cevap olarak işaretliyorum.
Vishnu

4

Bölümler Olmadan! Yani hassasiyetle veya sıfıra bölmeyle sorun değil.

Çizgi parçası 1 A ila B'dir Çizgi parçası 2 C ila D'dir

Bir çizgi hiç bitmeyen bir çizgidir, çizgi parçası o çizginin tanımlanmış bir parçasıdır.

İki sınırlayıcı kutunun kesişip kesişmediğini kontrol edin: kesişme yoksa -> Çapraz Yok! (hesaplama yapıldı, yanlış döndür)

Çizgi segmanı 1, çizgi segmanı 2 ile örtüşüp örtüşmediğini ve çizgi segmanı 2 çizgi segmanı 1 ile örtüşüp örtüşmediğini kontrol edin (yani, çizgi Segment 1, çizgi Segment 2 tarafından tanımlanan Hattın her iki tarafında mı).

Bu, tüm noktaları -A ile çevirerek yapılabilir (yani 2 çizgiyi A'nın origo (0,0) olacak şekilde hareket ettirin)

Ardından C ve D noktalarının 0,0 ile B arasında tanımlanan çizginin farklı tarafında olup olmadığını kontrol edersiniz

//Cross Product (hope I got it right here)
float fC= (B.x*C.y) - (B.y*C.x); //<0 == to the left, >0 == to the right
float fD= (B.x*D.y) - (B.y*D.x);

if( (fc<0) && (fd<0)) //both to the left  -> No Cross!
if( (fc>0) && (fd>0)) //both to the right -> No Cross!

Zaten bir "Çapraz Yok" a sahip değilseniz, A, B'ye karşı C, D değil C, D'ye karşı A, B'ye (aynı hesaplar, A ve C, B ve D'yi değiştirin) kullanmaya devam edin. "Çapraz Yok!" o zaman bir kavşak var!

Çapraz ürün için kesin hesaplamaları aradım ve yöntemi de açıklayan bu blog gönderisini buldum .


1
Üzgünüm ama vektör matematiği ile pek iyi değilim, bu algoritmayı böyle uyguladım ama sonuç alamadım, üzgünüm!
Vishnu

1
Bu yüzden belki bize kodunuzu gösterebilirseniz size yardımcı olabiliriz?
Valmond

Güzel! Ancak bağlantı kopuk
clabe45

Kesişim noktasını elde etmek için buna ekleyebileceğiniz bir şey var mı?
SeanRamey

1

Sadece şunu söylemek istiyorum, Gamemaker Studio oyunum için buna ihtiyacım vardı ve iyi çalışıyor:

///scr_line_collision(x1,y1,x2,y2,x3,y3,x4,y4)

var denominator= ((argument2 - argument0) * (argument7 - argument5)) - ((argument3 - argument1) * (argument6 - argument4));
var numerator1 = ((argument1 - argument5) * (argument6 - argument4)) - ((argument0 - argument4) * (argument7 - argument5));
var numerator2 = ((argument1 - argument5) * (argument2 - argument0)) - ((argument0 - argument4) * (argument3 - argument1));

// Detect coincident lines
if (denominator == 0) {return (numerator1 == 0 && numerator2 == 0)}

var r = numerator1 / denominator;
var s = numerator2 / denominator;

return ((r >= 0 && r <= 1) && (s >= 0 && s <= 1));

Kodun ne yaptığını açıkladıysanız bu cevabın gerçekten gelişebileceğini düşünüyorum.
TomTsagk

1

Bu durumda kabul edilen cevap yanlış bir cevap verdi:

x1 = 0;
y1 = 0;
x2 = 10;
y2 = 10;

x3 = 10.1;
y3 = 10.1;
x4 = 15;
y4 = 15;

Bu çizgiler açıkça kesişmez, ancak "doğru cevap" daki işleve göre çizgiler kesişir.

Ne kullanıyorum:

function do_lines_intersect(px1,py1,px2,py2,px3,py3,px4,py4) {
  var ua = 0.0;
  var ub = 0.0;
  var ud = (py4 - py3) * (px2 - px1) - (px4 - px3) * (py2 - py1);


  if (ud != 0) {
    ua = ((px4 - px3) * (py1 - py3) - (py4 - py3) * (px1 - px3)) / ud;
    ub = ((px2 - px1) * (py1 - py3) - (py2 - py1) * (px1 - px3)) / ud;
        if (ua < 0.0 || ua > 1.0 || ub < 0.0 || ub > 1.0) ua = 0.0;
  }

  return ua;
}

0 döndürür = çizgiler kesişmez

döndürür> 0 = çizgiler kesişir


Soruyu cevaplamak için güncelleyin:

Bu kodu kendim oluşturmadım. 5 yaşından büyük ve orijinal kaynağın ne olduğunu bilmiyorum. Fakat..

Ben dönüş değeri (onlar kötü açıklamak için) geçtikleri ilk satır göreli konum olduğunu düşünüyorum. Kavşak noktasını hesaplamak için muhtemelen lerp'i şu şekilde kullanabilirsiniz:

l = do_lines_intersect(...)
if (l > 0) {
    intersect_pos_x = l * (px2-px1);
    intersect_pos_y = l * (py2-py1);
} else {
    // lines do not cross
}

(Bunu test etmedim)


Bunun kavşak noktasını döndüren bir versiyonu var mı?
SeanRamey
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.