2012-10-15 67 views
1

我想在父畫布上隨機放置多個孩子畫布。我不希望兄弟畫布重疊(或相撞),所以我使用了一些碰撞檢測。WPF畫布和碰撞檢測

我顯然做錯了,因爲有碰撞,但不能把我的手指放在它上面。

我的畫法(被稱爲每秒)

private void draw(int args) 
    { 
     parent.Children.Clear(); 

     List<MyCanvas> children = fetchManyChildren(100); 
     Random rand = new Random(); 

     foreach (MyCanvas child in children) 
     { 
      child.xPos = nextDouble(rand, 0, parent.ActualWidth - child.Width); 
      child.yPos = nextDouble(rand, 0, parent.ActualHeight - child.Height); 

      foreach (MyCanvas sibling in parent.Children) 
      { 
       while (child.collidesWith(sibling)) 
       { 
        child.xPos = nextDouble(rand, 0, parent.ActualWidth - child.Width); 
        child.yPos = nextDouble(rand, 0, parent.ActualHeight - child.Height); 
       } 
      } 

      Canvas.SetLeft(child, child.xPos); 
      Canvas.SetTop(child, child.yPos); 

      parent.Children.Add(child); 
     } 
    } 

的helper方法:

private List<MyCanvas> fetchManyChildren(int amount) 
    { 
     List<MyCanvas> children = new List<MyCanvas>(amount); 

     Random rand = new Random(); 

     for (int i = 1; i <= amount; i++) 
     { 
      double size = nextDouble(rand, 1, MAX_SIZE); 

      MyCanvas child = new MyCanvas(0, 0, size, size); 

      child.Background = randomBrush(rand); 

      children.Add(child); 
     } 

     return children; 
    } 

    private double nextDouble(Random rand, double min, double max) 
    { 
     return min + (rand.NextDouble() * (max - min)); 
    } 

一類從畫布派生,讓我給X/Y位置到畫布並檢查碰撞:

public class MyCanvas : Canvas 
{ 
    public double xPos = 0; 
    public double yPos = 0; 

    public MyCanvas(double x, double y, double w, double h) 
    { 
     this.xPos = x; 
     this.yPos = y; 
     this.Width = w; 
     this.Height = h; 
    } 

    public bool collidesWith(MyCanvas p) 
    { 
     double bottom = this.yPos + this.Height; 
     double top = this.yPos; 
     double left = this.xPos; 
     double right = this.xPos + this.Width; 

     return !((bottom < p.yPos) || 
       (top > p.yPos + p.Height) || 
       (left > p.xPos + p.Width) || 
       (right < p.xPos)); 
    } 
} 

回答

2

當碰撞發生時你改變隨機位置你ha我忘了回去檢查parent.Children中的所有孩子......如果你不這樣做,那麼你可能會碰到一個未被發現的碰撞,因爲你的迭代器已經超過了這個項目。

您需要類似下面的代碼。

注意,你必須要小心....

你應該改變你的/我的代碼以某種方式來處理它不可能把你的孩子在未occuppied區域的情況下,即存在只是ISN沒有任何剩餘的房間。

由於您依賴於「隨機」數字生成最終找到「自由」位置.....這需要發現區域的時間量和「運氣」可能會使您處於需要的狀態一個無序的或無限的時間......一個更好的算法,「找到」自由區域將是可取的。

private void draw(int args) 
    { 
     parent.Children.Clear(); 

     List<MyCanvas> children = fetchManyChildren(100); 
     Random rand = new Random(); 

     foreach (MyCanvas child in children) 
     { 
      while(true) 
      { 
       // Choose a random place on Canvas we would like to place child 

       child.xPos = nextDouble(rand, 0, parent.ActualWidth - child.Width); 
       child.yPos = nextDouble(rand, 0, parent.ActualHeight - child.Height); 

       // Now see if it collides with ones already on Canvas 

       bool bCollisionDetected = false; 

       foreach (MyCanvas sibling in parent.Children) 
       { 
        bCollisionDetected = child.collidesWith(sibling); 

        if (bCollisionDetected) 
         break; 
       } 

       if (!bCollisionDetected) // Was able to place child in free position 
        break; 
      } 

      Canvas.SetLeft(child, child.xPos); 
      Canvas.SetTop(child, child.yPos); 

      parent.Children.Add(child); 
     } 
    } 
+1

感謝您的回答。現在這一切都很清楚。也感謝你們警告說沒有更多的自由空間;我已經考慮過了。最終的應用程序將在32英寸全高清顯示屏上運行,並且不會超過50個盒子,都相對較小。這聽起來很奇怪,但這是我工作場所所需的真正解決方案的起點。 – bobble14988