2012-10-15 4 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); 
     } 
    } 

커플 (매초 호출되는) 내 연신 방법

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

충돌이 발생할 때 임의의 위치를 ​​변경하면 parent.Children에있는 모든 아이들을 다시 확인하는 것을 잊었습니다 .... 만약 당신이하지 않는다면, 당신의 반복자가 이미 그 아이템을 지나치고 있기 때문에 당신은 발견되지 않은 충돌을 가질 것입니다.

아래 코드와 같은 것이 필요합니다.

주 당신이 조심해야 ....

당신은 않은 occuppied 지역에 자녀를 배치하는 것은 불가능 경우를 처리 할 수있는 방법에/내 코드를 변경해야 필요 즉, 그냥 거기 외설 여유 공간이 남지 않았습니다.

"무작위"숫자 생성을 사용하여 결국 "자유로운"위치를 찾으려면 .....이 시간을 가져다가 "운"을 취하면 영역을 발견하는 데 걸리는 시간이 소요될 수 있습니다 과도하거나 무한한 시간 ... 자유 지역을 "발견"하는 더 나은 알고리즘이 바람직합니다.

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 "풀 HD 디스플레이에서 실행되며 50 개 이상의 상자는 모두 작지만 이상하게 들리지만 직장에서 요구되는 진정한 솔루션의 출발점입니다. – bobble14988