Пример #1
0
        [Test] public void QuadTree()
        {
            var qtree = new QuadTree <Watzit>(-10, -5, 20, 10);

            // just inside quad0 at the root level
            var w0 = new Watzit(-0.5f * qtree.CellSizeX(15), -0.5f * qtree.CellSizeY(15), 0);
            var n0 = qtree.Insert(w0, w0.pos, w0.radius);

            Assert.Equal(2, qtree.Nodes.Count);
            Assert.Equal(15U, n0.m_level);
            Assert.Equal(0x4000U - 1, n0.m_x);
            Assert.Equal(0x4000U - 1, n0.m_y);

            // somewhere in quad3 at the root level
            var w1 = new Watzit(2.5f, 2.5f, 0.2f);
            var n1 = qtree.Insert(w1, w1.pos, w1.radius);

            Assert.Equal(3, qtree.Nodes.Count);
            Assert.Equal(4U, n1.m_level);
            Assert.Equal(10U, n1.m_x);
            Assert.Equal(12U, n1.m_y);

            // Outside the region but within the overhang at level 1
            var w2 = new Watzit(-14.99f, -7.2499f, 0);
            var n2 = qtree.Insert(w2, w2.pos, w2.radius);

            Assert.Equal(4, qtree.Nodes.Count);
            Assert.Equal(1U, n2.m_level);
            Assert.Equal(0U, n2.m_x);
            Assert.Equal(0U, n2.m_y);

            // Outside the region on y but within on x
            var w3 = new Watzit(6.5f, 7.24449f, 0);
            var n3 = qtree.Insert(w3, w3.pos, w3.radius);

            Assert.Equal(5, qtree.Nodes.Count);
            Assert.Equal(1U, n3.m_level);
            Assert.Equal(1U, n3.m_x);
            Assert.Equal(1U, n3.m_y);

            var rand = new Random();
            Func <float, float, float> fltc = (avr, d) => rand.FloatC(avr, d);
            Func <float, float, float> fltr = (mn, mx) => rand.Float(mn, mx);

            for (int i = 0; i != 10000; ++i)
            {
                var w = new Watzit(fltc(0.0f, qtree.Size.Width), fltc(0.0f, qtree.Size.Height), 0.2f * fltr(0.0f, 0.5f * Math_.Len2(qtree.Size.Width, qtree.Size.Height)));
                var n = qtree.Insert(w, w.pos, w.radius);

                // the root node can have arbitrarily large objects in it
                if (n.m_level != 0)
                {
                    float[] min, max;
                    qtree.NodeBounds(n, true, out min, out max);
                    Assert.True(w.pos[0] - w.radius >= min[0]);
                    Assert.True(w.pos[1] - w.radius >= min[1]);
                    Assert.True(w.pos[0] + w.radius < max[0]);
                    Assert.True(w.pos[1] + w.radius < max[1]);
                }
            }

            // Sanity check
            int count = 0;

            foreach (var node in qtree.Nodes)
            {
                Assert.True(qtree.SanityCheck(node));
                count += node.m_items.Count;
            }
            Assert.Equal(qtree.Count, count);

            for (int i = 0; i != 100; ++i)
            {
                // reset flags
                foreach (var node in qtree.Nodes)
                {
                    foreach (var item in node.m_items)
                    {
                        item.flag = false;
                    }
                }

                var W = new Watzit(fltc(0.0f, qtree.Size.Width), fltc(0.0f, qtree.Size.Height), 0.2f * fltr(0.0f, 0.5f * Math_.Len2(qtree.Size.Width, qtree.Size.Height)));
                qtree.Traverse(W.pos, W.radius, (w, n) =>
                {
                    w.flag = Collide(W, w);
                    return(true);
                });

                // All flagged should collide, not flagged should not
                foreach (var node in qtree.Nodes)
                {
                    foreach (var item in node.m_items)
                    {
                        Assert.Equal(item.flag, Collide(W, item));
                    }
                }
            }
        }