2016-04-12 19 views
-1

Hat bölümünün başlangıç ​​ve bitiş koordinatlarını içeren bir sözlüğe sahibim. Satır segmentlerinin bir kesişme olup olmadığını kontrol etmek için sözlükteki iki anahtarın tüm olası kombinasyonlarını karşılaştırmak istiyorum. Bunu nasıl yapabilirim ?Bir sözlükten anahtar çiftlerinin kombinasyonunu seçme

v = {1:[(2,3),(10,12)],2:[(22,25),(14,42)],3:[(-8,10),(3,21)]} 

bir çarpışma olup olmadığını belirlemek için fonksiyon hangi olur Sen (2,1)if x < y kısım sadece (1,2) olsun emin olur

comb = ((v[x], v[y]) for x in v for y in v if x < y) 

yazmak ama olmayabilir bu

def segment_intersect(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 
+0

, kabul etmelisiniz (uygun cevabın yanındaki onay işaretine tıklayın). Bu iki şey yapar. Sorununuzu çözdüğünüze herkesin memnun olduğunu bildirir ve size yardım için kredi vermenize yardımcı olan kişiye verir. Tam bir açıklama için [burada] (http://meta.stackexchange.com/a/5235) adresine bakın. –

cevap

2

gibidir aynı olmayacak ve anlam ifade etmeyecek olan (1,1).

Sen kombinasyonlarıyla bir yineleyici almak ve yazabilirsiniz:

for line1, line2 in comb: 
    segment_intersect(line1, line2) 

Not Bunun yerine bir dict tuşları ise 1, 2, 3, ...

+0

Cevabınız sağlam ve mükemmel bir alternatif. Bunun yerine duplikasyondan kaçınabilirsiniz diye düşünüyorum! = <(X ile y arasındaki karşılaştırmada) kullanırsınız. Bazen cevabın değerinin pedagojik değerden ziyade performansa bağlı olmadığına dikkat edin. Uygulamanız daha gelişmiş bir kullanıcının kullanmakta tereddüt etmeyeceği bir şeydir (yinelenen anlamanın yanı sıra şu anda çok moda) :) – armatita

+0

@armatita İyi nokta. '<'Kullanmak için cevabımı düzenledim. Cevabım pedagojik bir ilgiye sahip olabilir ama sanırım "itertools.combinations" ın yolu olduğunu düşünüyorum. –

+0

Anlaşmalı. En uygun gözüküyor. – armatita

2

daha list kullanmalıdır Sen çift ​​elemanların her biri için yuvalanmış döngüler yapabilir. Aşağıdaki örnek sadece bunu yapar ve sonuçları bir grafikle test eder.

[1, 2, 3, 4] 
1 2 False 
1 3 False 
1 4 True 
2 3 False 
2 4 False 
3 4 False 

ve:

import matplotlib.pyplot as plt 
v = {1:[(2,3),(10,12)],2:[(22,25),(14,42)],3:[(-8,10),(3,21)],4:[(10,3),(2,12)]} 
keys = list(v.keys()) 
print(keys) 
for i in range(len(keys)): 
    for j in range(i+1,len(keys)): 
     print(keys[i],keys[j],segment_intersect(v[keys[i]], v[keys[j]])) 
    plt.plot(*v[keys[i]],label=str(keys[i])) 
plt.legend() 
plt.show() 

, sonucudur

lines and interceptions

+0

Yanıt @armatita için teşekkürler. Grafik açıklaması gerçekten çok iyiydi. –

2

Sen kombinasyonları oluşturmak için standart itertools.combinations işlevini kullanabilirsiniz.

Ör

from itertools import combinations 

for k1, k2 in combinations(v, 2): 
    print(k1, k2, segment_intersect(v[k1], v[k2])) 

itertools.combinations kullanarak istiyorsanız, özellikle daha verimli ve iç içe for döngüler kullanmaktan daha okunabilir uzunlukta kombinasyonları> 2. aşağıya sorunu giderir cevaplar birinin

İlgili konular