2012-07-13 211 views
2

我正在自定義UIView中創建多個自定義UIView's。自定義子視圖的創建是可以的。他們是這樣的:多個UIView的重疊

enter image description here

Draw方法非常簡單:

[[UIColor brownColor] set]; 

CGContextRef ctx = UIGraphicsGetCurrentContext(); 
CGContextSetLineWidth(ctx, 
         5.0f); 
CGContextBeginPath(ctx); 
CGContextMoveToPoint(ctx, 0.0f, 0.0f); 
CGContextAddLineToPoint(ctx, 100.0f, 0.0); 
CGContextAddLineToPoint(ctx, 130.0f, 25.0f); 
CGContextAddLineToPoint(ctx, 100.0f, 50.0f); 
CGContextAddLineToPoint(ctx, 0.0f, 50.0f); 
CGContextClosePath(ctx); 
CGContextStrokePath(ctx); 
[super drawRect:rect]; 

它添加到超級視圖也非常簡單:

ITContextFigure *view = [[ITContextFigure alloc] initWithFrame:CGRectMake(location.x, location.y, 135.0f, 50.0f)]; 
    [view setBackgroundColor:[UIColor yellowColor]]; 
    [self addSubview:view]; 

所以我的問題是:

1)Ho我可以檢測到一個與另一個重疊嗎?

我看到這個解決方案:

if (CGRectContainsRect([myImageView1 frame], [myImageView2 frame])) { 
     NSLog(@"Overlaped, it's working!"); 
} 

但是,如果我有多個UIViews,做對super view一個for和檢查每一個單個子視圖似乎並沒有很好的解決方案給我。

2)在這種情況下,可以做些什麼?

enter image description here

我的主要目標是檢測當這種情況發生:

enter image description here


更新1.0

打算嘗試什麼已經顯示爲here,因爲沒有更優雅的方式。如果我能夠實現它,我會在Github上發佈代碼,如果有人需要的話。

+0

我想你可能想要搜索算法來檢測相交多邊形(這涉及每對線段和線段相交的蠻力)。 – nhahtdh 2012-07-13 15:12:13

+0

我猜你在2)的情況是邊界矩形重疊,但視圖的主要內容不? – 2012-07-13 15:12:25

+0

@nhahtdh不總是一個蠻力,你可以做分離軸定理檢測任意(凸)多邊形上的交點 – 2012-07-13 15:13:16

回答

3

通過巧妙地對數據進行排序(這些稱爲掃描線或滲透線算法),您可以顯着減少您需要執行的碰撞​​檢測次數。以下是您如何將這種技術應用於您的情況的大綱。

將您的子視圖按y升序排序。如果兩個子視圖共享相同的y,則按升序x排序。這是您的非活動列表,它構成了算法的主要輸入。

算法進行如下。

  1. 雖然有不活動的子視圖,請選擇active_y。這是非活動列表中第一個子視圖的y座標。

  2. 將所有具有active_y行上的原點的子視圖移動到工作列表,按升序x排序。這是活動列表。

  3. 通過活動列表衝突測試每個子視圖與列表中的後續列表。你可以在列表中使用兩個索引(我們稱之爲leftright)。只要您看到right子視圖不能與left相交,就可以提前輸入left索引。

  4. 在進行碰撞檢測時,您還要檢查子視圖是否現在完全低於active_y。一旦它,你應該從活動列表中刪除它。

算法在非活動列表上的所有子視圖都已被佔用並且最終運行通過活動列表完成時完成。

該算法大大減少了您需要執行的碰撞​​檢測次數,大致爲O(n log n),但它也可以簡化碰撞檢測本身。

由於活動列表是從左到右排序的,因此您總是知道您在做什麼檢測例程,哪一個在左邊,哪個在右邊。因此,例如,在比較示例中的箭頭形狀時,只需檢查右側形狀的兩個最左側頂點是否落在左側形狀內。你可能會發現CGPathContainsPoint有用。

如果您正在處理的不同形狀的數量增加,那麼您可能需要考慮將碰撞檢測推入掃描線算法本身。這有點棘手,但基本上,而不是持有子視圖指針的列表,他們將持有構成形狀(不包括水平)的線段。

+0

idz是否可以刪除多餘的黃色部分? – Peres 2012-07-19 08:47:18

+1

是的,不是設置背景顏色,而是用黃色填充路徑,然後用棕色填充。將UIView的背景顏色設置爲clearColor,並確保視圖的opaque屬性爲NO。檢出'CGContextFillPath',你也可能需要'CGContextSetRGBFillColor'(我不記得是否通過'UIColor'設置了填充顏色)。 – idz 2012-07-19 18:01:26