From 6a47d0f50741759e25a6d2f02c766770c1557801 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Tue, 14 Jan 2020 00:30:15 -0800 Subject: [PATCH] RTree: Fix iterator in single branch trees In a single branch tree, we need to verify that all leaves do not match the input search before returning. Fixes #3764 | https://gitlab.com/kicad/code/kicad/issues/3764 --- qa/eeschema/test_sch_rtree.cpp | 30 ++++++++++++++++++++++++++++++ thirdparty/rtree/geometry/rtree.h | 15 +++++++-------- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/qa/eeschema/test_sch_rtree.cpp b/qa/eeschema/test_sch_rtree.cpp index dfa69afe43..5ce1f6535e 100644 --- a/qa/eeschema/test_sch_rtree.cpp +++ b/qa/eeschema/test_sch_rtree.cpp @@ -241,4 +241,34 @@ BOOST_AUTO_TEST_CASE( MixedElements ) BOOST_CHECK_EQUAL( count, 1 ); } +// This tests the case where the tree has no branches but we want to iterator over a subset +// where the first case may or may not match +BOOST_AUTO_TEST_CASE( SingleElementTree ) +{ + SCH_JUNCTION* junction = new SCH_JUNCTION( wxPoint( Mils2iu( 100 ), Mils2iu( 100 ) ) ); + m_tree.insert( junction ); + + SCH_NO_CONNECT* nc = new SCH_NO_CONNECT( wxPoint( Mils2iu( 150 ), Mils2iu( 150 ) ) ); + m_tree.insert( nc ); + + int count = 0; + + for( auto item : m_tree.OfType( SCH_JUNCTION_T ) ) + { + static_cast( item ); + count++; + } + + BOOST_CHECK_EQUAL( count, 1 ); + + count = 0; + for( auto item : m_tree.OfType( SCH_NO_CONNECT_T ) ) + { + static_cast( item ); + count++; + } + + BOOST_CHECK_EQUAL( count, 1 ); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/thirdparty/rtree/geometry/rtree.h b/thirdparty/rtree/geometry/rtree.h index dd8d1344be..6c920d28df 100644 --- a/thirdparty/rtree/geometry/rtree.h +++ b/thirdparty/rtree/geometry/rtree.h @@ -404,18 +404,17 @@ public: { iterator retval( aRect ); - // Only a single element in the tree - if( m_root->IsLeaf() ) - { - if( m_root->m_count && Overlap( &aRect, &m_root->m_branch[0].m_rect ) ) - retval.Push( m_root, 0 ); - + if( !m_root->m_count ) return retval; - } retval.Push( m_root, 0 ); - ++retval; + // If the first leaf matches, return the root pointer, otherwise, + // increment to the first match or empty if none. + if( m_root->IsLeaf() && Overlap( &aRect, &m_root->m_branch[0].m_rect ) ) + return retval; + + ++retval; return retval; }