1

親キャンバスに複数の子キャンバスをランダムに配置しようとしています。兄弟キャンバスをオーバーラップ (または衝突) させたくないので、衝突検出を使用しています。

衝突があるため、明らかに何か間違ったことをしていますが、指を置くことはできません。

私の draw メソッド (毎秒呼び出されます)

    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));
    }

Canvas に x/y 位置を指定し、衝突をチェックできる Canvas から派生したクラス:

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

1 に答える 1

2

衝突が発生したときにランダムな位置を変更すると、すべての子に対して再度チェックするのを忘れてしまいparent.Childrenます....そうしないと、イテレータがすでにそのアイテムを通過しているため、検出されない衝突が発生する可能性があります.

以下のコードのようなものが必要です。

注意が必要なので注意してください....

あなたの/私のコードを何らかの方法で変更して、あなたの子供を占有されていない場所に置くことが不可能な場合、つまり空き部屋が残っていない場合に対処する必要があります.

最終的に「自由な」位置を見つけるために「ランダムな」数の生成に依存しているため.....これが領域を発見するのにかかる時間と「運」は、あなたを過度または無限にかかる状況に陥らせる可能性があります時間...空き領域を「見つける」より良いアルゴリズムが望ましいでしょう。

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);
        }
    }
于 2012-10-17T12:11:10.997 に答える