diff --git a/src/db/db/dbQuadTree.h b/src/db/db/dbQuadTree.h index 93674ea69..546c007ff 100644 --- a/src/db/db/dbQuadTree.h +++ b/src/db/db/dbQuadTree.h @@ -290,22 +290,26 @@ private: } box_type b = BC () (value); - int n = quad_for (b); - - if (n < 0) { - m_objects.push_back (value); - return; - } - if (b.inside (box (ucenter))) { - if (! m_q[n]) { - box_type bq = q (n, ucenter); - m_q[n] = new quad_tree_node (bq.center ()); + + int n = quad_for (b); + if (n < 0) { + m_objects.push_back (value); + } else { + if (! m_q[n]) { + box_type bq = q (n, ucenter); + m_q[n] = new quad_tree_node (bq.center ()); + } + m_q[n]->insert (value, m_center); } - m_q[n]->insert (value, m_center); + } else { - grow (m_center - (m_center - ucenter) * 2.0); - insert (value, ucenter); + + tl_assert (m_q[0] || m_q[1] || m_q[2] || m_q[3]); + point_type new_ucenter = m_center - (m_center - ucenter) * 2.0; + grow (new_ucenter); + insert (value, new_ucenter); + } } @@ -317,6 +321,7 @@ private: if (m_q[i]) { quad_tree_node *n = m_q[i]; m_q[i] = new quad_tree_node (q (i, ucenter).center ()); + m_q[i]->m_split = true; m_q[i]->m_q[3 - i] = n; } } @@ -470,6 +475,8 @@ public: while (! m_stack.empty ()) { + qn = m_stack.back ().first; + int &n = m_stack.back ().second; while (++n < 4) { box_type bq = qn->q_box (n); diff --git a/src/db/unit_tests/dbQuadTreeTests.cc b/src/db/unit_tests/dbQuadTreeTests.cc index 6d39ea49b..1866907d1 100644 --- a/src/db/unit_tests/dbQuadTreeTests.cc +++ b/src/db/unit_tests/dbQuadTreeTests.cc @@ -26,6 +26,8 @@ #include "tlUnitTest.h" #include "tlString.h" +#include + typedef db::quad_tree, size_t (1)> my_quad_tree; std::string find_all (const my_quad_tree &qt) @@ -256,6 +258,58 @@ TEST(remove) EXPECT_EQ (tree.levels (), size_t (1)); } +TEST(grow) +{ + my_quad_tree tree; + tree.insert (db::DBox (-1, -2, 3, 4)); + tree.insert (db::DBox (-1, -3, 3, 0)); + tree.insert (db::DBox (-1, -3, -0.5, -2)); + tree.insert (db::DBox (-1, -3, -0.5, 2)); + EXPECT_EQ (tree.levels (), size_t (2)); + tree.insert (db::DBox (-100, -3, -99, 2)); + EXPECT_EQ (tree.levels (), size_t (8)); + + EXPECT_EQ (tree.check (), true); + EXPECT_EQ (find_all (tree), "(-1,-2;3,4)/(-1,-3;-0.5,-2)/(-1,-3;-0.5,2)/(-1,-3;3,0)/(-100,-3;-99,2)"); + EXPECT_EQ (find_overlapping (tree, db::DBox (-100, -100, -90, 100)), "(-100,-3;-99,2)"); + + bool r = true; + while (r && ! tree.empty ()) { + r = tree.erase (*tree.begin ()); + EXPECT_EQ (r, true); + EXPECT_EQ (tree.check (), true); + } + + EXPECT_EQ (tree.size (), size_t (0)); + EXPECT_EQ (tree.levels (), size_t (1)); +} + +TEST(grow2) +{ + my_quad_tree tree; + tree.insert (db::DBox (-1, -2, 3, 4)); + tree.insert (db::DBox (-1, -3, 3, 0)); + tree.insert (db::DBox (-1, -3, -0.5, -2)); + tree.insert (db::DBox (-1, -3, -0.5, 2)); + EXPECT_EQ (tree.levels (), size_t (2)); + tree.insert (db::DBox (-100, -3, -99, -1)); + EXPECT_EQ (tree.levels (), size_t (8)); + + EXPECT_EQ (tree.check (), true); + EXPECT_EQ (find_all (tree), "(-1,-2;3,4)/(-1,-3;-0.5,-2)/(-1,-3;-0.5,2)/(-1,-3;3,0)/(-100,-3;-99,-1)"); + EXPECT_EQ (find_overlapping (tree, db::DBox (-100, -100, -90, 100)), "(-100,-3;-99,-1)"); + + bool r = true; + while (r && ! tree.empty ()) { + r = tree.erase (*tree.begin ()); + EXPECT_EQ (r, true); + EXPECT_EQ (tree.check (), true); + } + + EXPECT_EQ (tree.size (), size_t (0)); + EXPECT_EQ (tree.levels (), size_t (1)); +} + TEST(clear) { my_quad_tree tree; @@ -391,3 +445,33 @@ TEST(move_ctor) EXPECT_EQ (tree2.levels (), size_t (2)); } +static double rvalue () +{ + return ((rand () % 1000000) - 5000) * 0.001; +} + +static db::DBox rbox () +{ + return db::DBox (db::DPoint (rvalue (), rvalue ()), db::DPoint (rvalue (), rvalue ())); +} + +TEST(many) +{ + return; // @@@ + my_quad_tree tree; + + unsigned int n = 1000; + + for (unsigned int i = 0; i < n; ++i) { + tree.insert (rbox ()); + } + + EXPECT_EQ (tree.check (), true); + + bool r = true; + while (r && ! tree.empty ()) { + r = tree.erase (*tree.begin ()); + EXPECT_EQ (r, true); + EXPECT_EQ (tree.check (), true); + } +}