1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2020 KiCad Developers, see AUTHORS.TXT for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 3
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-3.0.html
19  * or you may search the http://www.gnu.org website for the version 3 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
22  */
23 
24 /**
25  * @file
26  * Test suite for SCH_SHEET
27  */
28 
29 #include <convert_to_biu.h>
30 #include <ignore.h>
31 #include <sch_junction.h>
32 #include <sch_no_connect.h>
33 #include <qa_utils/wx_utils/unit_test_utils.h>
34 
35 // Code under test
36 #include <sch_rtree.h>
37 
38 #include "uuid_test_utils.h"
39 
40 #include <qa_utils/wx_utils/wx_assert.h>
41 
42 class TEST_SCH_RTREE_FIXTURE
43 {
44 public:
TEST_SCH_RTREE_FIXTURE()45     TEST_SCH_RTREE_FIXTURE() : m_tree()
46     {
47     }
48 
49     EE_RTREE m_tree;
50 };
51 
52 
53 /**
54  * Declare the test suite
55  */
BOOST_FIXTURE_TEST_SUITE(SchRtree,TEST_SCH_RTREE_FIXTURE)56 BOOST_FIXTURE_TEST_SUITE( SchRtree, TEST_SCH_RTREE_FIXTURE )
57 
58 
59 /**
60  * Check default iterators
61  */
62 BOOST_AUTO_TEST_CASE( Default )
63 {
64     BOOST_CHECK_EQUAL( m_tree.empty(), true );
65 
66     int count = 0;
67     for( auto item : m_tree )
68     {
69         ignore_unused( item );
70         count++;
71     }
72 
73     BOOST_CHECK_EQUAL( count, 0 );
74 
75     for( int type = 0; type <= MAX_STRUCT_TYPE_ID; type++ )
76     {
77         count = 0;
78         for( auto item : m_tree.OfType( KICAD_T( type ) ) )
79         {
80             ignore_unused( item );
81             count++;
82         }
83 
84         BOOST_CHECK_EQUAL( count, 0 );
85     }
86 
87     EDA_RECT bbox;
88 
89     for( int type = 0; type <= MAX_STRUCT_TYPE_ID; type++ )
90     {
91         count = 0;
92         for( auto item : m_tree.Overlapping( SCH_JUNCTION_T, bbox ) )
93         {
94             ignore_unused( item );
95             count++;
96         }
97 
98         BOOST_CHECK_EQUAL( count, 0 );
99     }
100 }
101 
BOOST_AUTO_TEST_CASE(Junctions)102 BOOST_AUTO_TEST_CASE( Junctions )
103 {
104     for( int i = 0; i < 100; i++ )
105     {
106         SCH_JUNCTION* junction =
107                 new SCH_JUNCTION( wxPoint( Mils2iu( 100 ) * i, Mils2iu( 100 ) * i ) );
108         m_tree.insert( junction );
109     }
110 
111     int count = 0;
112 
113     for( auto item : m_tree.OfType( SCH_JUNCTION_T ) )
114     {
115         ignore_unused( item );
116         count++;
117     }
118 
119     BOOST_CHECK_EQUAL( count, 100 );
120 
121     count = 0;
122     for( auto item : m_tree.OfType( SCH_NO_CONNECT_T ) )
123     {
124         ignore_unused( item );
125         count++;
126     }
127 
128     BOOST_CHECK_EQUAL( count, 0 );
129 
130     EDA_RECT small_bbox( wxPoint( -1, -1 ), wxSize( Mils2iu( 2 ), Mils2iu( 2 ) ) );
131     EDA_RECT med_bbox( wxPoint( 0, 0 ), wxSize( Mils2iu( 100 ), Mils2iu( 100 ) ) );
132     EDA_RECT big_bbox( wxPoint( 0, 0 ), wxSize( Mils2iu( 5000 ), Mils2iu( 5000 ) ) );
133 
134     count = 0;
135     for( auto item : m_tree.Overlapping( small_bbox ) )
136     {
137         BOOST_CHECK( small_bbox.Intersects( item->GetBoundingBox() ) );
138         count++;
139     }
140 
141     BOOST_CHECK_EQUAL( count, 1 );
142 
143     count = 0;
144     for( auto item : m_tree.Overlapping( SCH_JUNCTION_T, small_bbox ) )
145     {
146         BOOST_CHECK( small_bbox.Intersects( item->GetBoundingBox() ) );
147         count++;
148     }
149 
150     BOOST_CHECK_EQUAL( count, 1 );
151 
152     count = 0;
153     for( auto item : m_tree.Overlapping( SCH_NO_CONNECT_T, small_bbox ) )
154     {
155         BOOST_CHECK( small_bbox.Intersects( item->GetBoundingBox() ) );
156         count++;
157     }
158 
159     BOOST_CHECK_EQUAL( count, 0 );
160 
161     count = 0;
162     for( auto item : m_tree.Overlapping( med_bbox ) )
163     {
164         BOOST_CHECK( med_bbox.Intersects( item->GetBoundingBox() ) );
165         count++;
166     }
167 
168     BOOST_CHECK_EQUAL( count, 2 );
169 
170     count = 0;
171     for( auto item : m_tree.Overlapping( big_bbox ) )
172     {
173         BOOST_CHECK( big_bbox.Intersects( item->GetBoundingBox() ) );
174         count++;
175     }
176 
177     BOOST_CHECK_EQUAL( count, 51 );
178 
179     for( SCH_ITEM* item : m_tree )
180         delete item;
181 }
182 
BOOST_AUTO_TEST_CASE(MixedElements)183 BOOST_AUTO_TEST_CASE( MixedElements )
184 {
185     for( int i = 0; i < 100; i++ )
186     {
187         int x_sign = ( i % 2 == 0 ) ? -1 : 1;
188         int y_sign = ( i % 3 == 0 ) ? -1 : 1;
189 
190         SCH_JUNCTION* junction = new SCH_JUNCTION(
191                 wxPoint( Mils2iu( 100 ) * i * x_sign, Mils2iu( 100 ) * i * y_sign ) );
192         m_tree.insert( junction );
193 
194         SCH_NO_CONNECT* nc = new SCH_NO_CONNECT(
195                 wxPoint( Mils2iu( 150 ) * i * y_sign, Mils2iu( 150 ) * i * x_sign ) );
196         m_tree.insert( nc );
197     }
198 
199     int count = 0;
200 
201     for( auto item : m_tree.OfType( SCH_JUNCTION_T ) )
202     {
203         ignore_unused( item );
204         count++;
205     }
206 
207     BOOST_CHECK_EQUAL( count, 100 );
208 
209     count = 0;
210     for( auto item : m_tree.OfType( SCH_NO_CONNECT_T ) )
211     {
212         ignore_unused( item );
213         count++;
214     }
215 
216     BOOST_CHECK_EQUAL( count, 100 );
217 
218     EDA_RECT small_bbox( wxPoint( -1, -1 ), wxSize( Mils2iu( 2 ), Mils2iu( 2 ) ) );
219 
220     count = 0;
221     for( auto item : m_tree.Overlapping( small_bbox ) )
222     {
223         BOOST_CHECK( small_bbox.Intersects( item->GetBoundingBox() ) );
224         count++;
225     }
226 
227     BOOST_CHECK_EQUAL( count, 2 );
228 
229     count = 0;
230     for( auto item : m_tree.Overlapping( SCH_JUNCTION_T, small_bbox ) )
231     {
232         BOOST_CHECK( small_bbox.Intersects( item->GetBoundingBox() ) );
233         count++;
234     }
235 
236     BOOST_CHECK_EQUAL( count, 1 );
237 
238     count = 0;
239     for( auto item : m_tree.Overlapping( SCH_NO_CONNECT_T, small_bbox ) )
240     {
241         BOOST_CHECK( small_bbox.Intersects( item->GetBoundingBox() ) );
242         count++;
243     }
244 
245     BOOST_CHECK_EQUAL( count, 1 );
246 
247     for( SCH_ITEM* item : m_tree )
248         delete item;
249 }
250 
251 // This tests the case where the tree has no branches but we want to iterator over a subset
252 // where the first case may or may not match
BOOST_AUTO_TEST_CASE(SingleElementTree)253 BOOST_AUTO_TEST_CASE( SingleElementTree )
254 {
255     SCH_JUNCTION* junction = new SCH_JUNCTION( wxPoint( Mils2iu( 100 ), Mils2iu( 100 ) ) );
256     m_tree.insert( junction );
257 
258     SCH_NO_CONNECT* nc = new SCH_NO_CONNECT( wxPoint( Mils2iu( 150 ), Mils2iu( 150 ) ) );
259     m_tree.insert( nc );
260 
261     int count = 0;
262 
263     for( auto item : m_tree.OfType( SCH_JUNCTION_T ) )
264     {
265         ignore_unused( item );
266         count++;
267     }
268 
269     BOOST_CHECK_EQUAL( count, 1 );
270 
271     count = 0;
272     for( auto item : m_tree.OfType( SCH_NO_CONNECT_T ) )
273     {
274         ignore_unused( item );
275         count++;
276     }
277 
278     BOOST_CHECK_EQUAL( count, 1 );
279 
280     for( SCH_ITEM* item : m_tree )
281         delete item;
282 }
283 
284 BOOST_AUTO_TEST_SUITE_END()
285