Some performance improvement by eliminating empty objects in the box scanner.

This commit is contained in:
Matthias Koefferlein 2019-01-21 22:37:02 +01:00
parent f83e1dae43
commit d79a448eaa
4 changed files with 108 additions and 0 deletions

View File

@ -273,6 +273,25 @@ public:
typedef bs_side_compare_vs_const_func<BoxConvert, Obj, Prop, box_top<Box> > below_func;
typedef bs_side_compare_vs_const_func<BoxConvert, Obj, Prop, box_right<Box> > left_func;
// sort out the entries with an empty bbox (we must not put that into sort)
typename container_type::iterator wi = m_pp.begin ();
for (typename container_type::iterator ri = m_pp.begin (); ri != m_pp.end (); ++ri) {
if (! bc (*ri->first).empty ()) {
if (wi != ri) {
*wi = *ri;
}
++wi;
} else {
// we call finish on empty elements though
rec.finish (ri->first, ri->second);
}
}
if (wi != m_pp.end ()) {
m_pp.erase (wi, m_pp.end ());
}
if (m_pp.size () <= m_scanner_thr) {
// below m_scanner_thr elements use the brute force approach which is faster in that case
@ -606,6 +625,42 @@ public:
typedef bs_side_compare_vs_const_func<BoxConvert2, Obj2, Prop2, box_top<Box> > below_func2;
typedef bs_side_compare_vs_const_func<BoxConvert2, Obj2, Prop2, box_right<Box> > left_func2;
// sort out the entries with an empty bbox (we must not put that into sort)
typename container_type1::iterator wi1 = m_pp1.begin ();
for (typename container_type1::iterator ri1 = m_pp1.begin (); ri1 != m_pp1.end (); ++ri1) {
if (! bc1 (*ri1->first).empty ()) {
if (wi1 != ri1) {
*wi1 = *ri1;
}
++wi1;
} else {
// we call finish on empty elements though
rec.finish1 (ri1->first, ri1->second);
}
}
if (wi1 != m_pp1.end ()) {
m_pp1.erase (wi1, m_pp1.end ());
}
typename container_type2::iterator wi2 = m_pp2.begin ();
for (typename container_type2::iterator ri2 = m_pp2.begin (); ri2 != m_pp2.end (); ++ri2) {
if (! bc2 (*ri2->first).empty ()) {
if (wi2 != ri2) {
*wi2 = *ri2;
}
++wi2;
} else {
// we call finish on empty elements though
rec.finish2 (ri2->first, ri2->second);
}
}
if (wi2 != m_pp2.end ()) {
m_pp2.erase (wi2, m_pp2.end ());
}
if (m_pp1.empty () || m_pp2.empty ()) {
// trivial case

View File

@ -283,6 +283,28 @@ TEST(1f)
EXPECT_EQ (tr.str, "");
}
TEST(1g)
{
// empty elements
db::box_scanner<db::Box, size_t> bs;
std::vector<db::Box> bb;
bb.push_back (db::Box (0, 0, 101, 100));
bb.push_back (db::Box (200, 0, 300, 100));
bb.push_back (db::Box ());
bb.push_back (db::Box (100, 0, 200, 100));
bb.push_back (db::Box ());
for (std::vector<db::Box>::const_iterator b = bb.begin (); b != bb.end (); ++b) {
bs.insert (&*b, b - bb.begin ());
}
BoxScannerTestRecorder tr;
bs.set_fill_factor (0.0);
db::box_convert<db::Box> bc;
bs.process (tr, 0, bc);
EXPECT_EQ (tr.str, "<2><4>(0-3)<0><1><3>");
}
void run_test2 (tl::TestBase *_this, size_t n, double ff, db::Coord spread, bool touch = true)
{
std::vector<db::Box> bb;
@ -985,6 +1007,37 @@ TEST(two_1b)
EXPECT_EQ (trstop.str, "(1-12)");
}
TEST(two_1c)
{
// some empty elements
db::box_scanner2<db::Box, size_t, db::SimplePolygon, int> bs;
std::vector<db::Box> bb;
bb.push_back (db::Box ());
bb.push_back (db::Box (0, 0, 100, 100));
bb.push_back (db::Box (100, 10, 200, 110));
std::vector<db::SimplePolygon> bb2;
bb2.push_back (db::SimplePolygon (db::Box ()));
bb2.push_back (db::SimplePolygon (db::Box (50, 50, 150, 150)));
bb2.push_back (db::SimplePolygon (db::Box (10, 10, 110, 110)));
for (std::vector<db::Box>::const_iterator b = bb.begin (); b != bb.end (); ++b) {
bs.insert1 (&*b, b - bb.begin ());
}
for (std::vector<db::SimplePolygon>::const_iterator b = bb2.begin (); b != bb2.end (); ++b) {
bs.insert2 (&*b, int (b - bb2.begin ()) + 10);
}
BoxScannerTestRecorderTwo tr;
bs.set_fill_factor (0.0);
db::box_convert<db::Box> bc1;
db::box_convert<db::SimplePolygon> bc2;
bs.set_scanner_threshold (0);
EXPECT_EQ (bs.process (tr, 1, bc1, bc2), true);
EXPECT_EQ (tr.str, "<0><10>(1-12)(2-12)(1-11)(2-11)<1><2><12><11>");
}
void run_test2_two (tl::TestBase *_this, size_t n, double ff, db::Coord spread, bool touch = true)
{
std::vector<db::Box> bb;