KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_junction_helpers.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2024 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 * https://www.gnu.org/licenses/gpl-3.0.en.html
19 * or you may search the http://www.gnu.org website for the version 32 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
25
26#include <junction_helpers.h>
27
28#include <sch_bus_entry.h>
29#include <sch_line.h>
30#include <sch_sheet.h>
31#include <sch_sheet_pin.h>
32
33using namespace JUNCTION_HELPERS;
34
35static constexpr int BE_SIZE = 25400;
36
38{
40};
41
42static SCH_LINE* make_wire( const VECTOR2I& aStart, const VECTOR2I& aEnd )
43{
44 SCH_LINE* const line = new SCH_LINE{ aStart, LAYER_WIRE };
45 line->SetEndPoint( aEnd );
46 return line;
47}
48
49static SCH_LINE* make_bus( const VECTOR2I& aStart, const VECTOR2I& aEnd )
50{
51 SCH_LINE* const line = new SCH_LINE{ aStart, LAYER_BUS };
52 line->SetEndPoint( aEnd );
53 return line;
54}
55
56BOOST_FIXTURE_TEST_SUITE( JunctionHelpers, JUNCTION_HELPER_FIXTURE )
57
58
62{
63 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
64
65 BOOST_CHECK( !info.isJunction );
66}
67
68BOOST_AUTO_TEST_CASE( SingleWireEnd )
69{
70 /*
71 * not a junction
72 * V
73 * -----------
74 */
75 items.insert( make_wire( { 0, 0 }, { 0, 100 } ) );
76
77 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
78
79 BOOST_CHECK( !info.isJunction );
80}
81
83{
84 /*
85 * |
86 * |_____
87 * ^
88 * not a junction
89 */
90 items.insert( make_wire( { 0, 0 }, { 100, 0 } ) );
91 items.insert( make_wire( { 0, 0 }, { 0, 100 } ) );
92
93 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
94
95 BOOST_CHECK( !info.isJunction );
96}
97
99{
100 /*
101 * | /-- junction in the middle
102 * | /
103 * -----O------
104 */
105 items.insert( make_wire( { 0, 0 }, { 100, 0 } ) );
106 items.insert( make_wire( { 0, 0 }, { -100, 0 } ) );
107 items.insert( make_wire( { 0, 0 }, { 0, 100 } ) );
108
109 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
110
111 BOOST_CHECK( info.isJunction );
112 BOOST_CHECK( !info.hasBusEntry );
113 BOOST_CHECK( !info.hasBusEntryToMultipleWires );
114}
115
116BOOST_AUTO_TEST_CASE( BusEntryOnBus )
117{
118 /*
119 * || <-- not a junction (it is a connection!)
120 * ||\
121 * || \
122 * || \ <-- also not a junction
123 */
124
125 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
126
127 SCH_BUS_WIRE_ENTRY* const busEntry = new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false );
128
129 // Make sure the BE is where we think it is
130 BOOST_REQUIRE_EQUAL( busEntry->GetPosition(), VECTOR2I( 0, 0 ) );
131 BOOST_REQUIRE_EQUAL( busEntry->GetEnd(), VECTOR2I( BE_SIZE, BE_SIZE ) );
132
133 items.insert( busEntry );
134
135 // BE-bus point
136 const POINT_INFO info_start = AnalyzePoint( items, { 0, 0 }, false );
137 BOOST_CHECK( !info_start.isJunction );
138 BOOST_CHECK( info_start.hasBusEntry );
139
140 // Dangling end of the bus entry
141 const POINT_INFO info_end = AnalyzePoint( items, { BE_SIZE, BE_SIZE }, false );
142 BOOST_CHECK( !info_end.isJunction );
143 BOOST_CHECK( info_end.hasBusEntry );
144 // There is no wire here
146}
147
148BOOST_AUTO_TEST_CASE( BusEntryToWire )
149{
150 /*
151 * \
152 * \ /--- <-- not a junction
153 * \V________________
154 */
155 SCH_BUS_WIRE_ENTRY* const busEntry = new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false );
156 items.insert( busEntry );
157 items.insert( make_wire( { BE_SIZE, BE_SIZE }, { 2 * BE_SIZE, BE_SIZE } ) );
158
159 const POINT_INFO info = AnalyzePoint( items, { BE_SIZE, BE_SIZE }, false );
160 BOOST_CHECK( !info.isJunction );
161 BOOST_CHECK( info.hasBusEntry );
162 // This is a single wire to a bus entry, not multiple
163 BOOST_CHECK( !info.hasBusEntryToMultipleWires );
164}
165
166BOOST_AUTO_TEST_CASE( WireDirectToBus )
167{
168 /*
169 * || /--- <-- not a junction
170 * ||______________
171 */
172 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
173 items.insert( make_wire( { 0, 0 }, { BE_SIZE, 0 } ) );
174
175 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
176 BOOST_CHECK( !info.isJunction );
177 BOOST_CHECK( !info.hasBusEntry );
178 // It's a single wire, and not a bus entry
179 BOOST_CHECK( !info.hasBusEntryToMultipleWires );
180}
181
182BOOST_AUTO_TEST_CASE( WireCrossingBus )
183{
184 /* || __ not a junction
185 * || /
186 * ______________________
187 * ||
188 * ||
189 */
190 items.insert( make_bus( { 0, 0 }, { 0, -BE_SIZE } ) );
191 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
192 items.insert( make_wire( { 0, 0 }, { BE_SIZE, 0 } ) );
193 items.insert( make_wire( { 0, 0 }, { -BE_SIZE, 0 } ) );
194
195 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
196 // Two wires and two buses meet, which isn't a junction
197 BOOST_CHECK( !info.isJunction );
198 BOOST_CHECK( !info.hasBusEntry );
199 BOOST_CHECK( !info.hasBusEntryToMultipleWires );
200}
201
202BOOST_AUTO_TEST_CASE( WireToBusEntryRoot )
203{
204 /*
205 * /--- <-- not a junction
206 * _____________
207 * ||\
208 * || \
209 * || \
210 */
211 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
212 items.insert( make_wire( { 0, 0 }, { BE_SIZE, 0 } ) );
213 items.insert( new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false ) );
214
215 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
216 BOOST_CHECK( !info.isJunction );
217 BOOST_CHECK( info.hasBusEntry );
218 // The bus/bus-entry point isn't valid
219 BOOST_CHECK( !info.hasBusEntryToMultipleWires );
220}
221
222BOOST_AUTO_TEST_CASE( WireCrossingBusEntryRoot )
223{
224 /* ||
225 * || /--- <-- it's a junction, but the client can choose not
226 * || to put a dot here
227 * ______________________
228 * ||\
229 * || \
230 * || \
231 */
232 items.insert( make_bus( { 0, 0 }, { 0, -BE_SIZE } ) );
233 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
234 items.insert( make_wire( { 0, 0 }, { BE_SIZE, 0 } ) );
235 items.insert( make_wire( { 0, 0 }, { -BE_SIZE, 0 } ) );
236 items.insert( new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false ) );
237
238 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
239 // Three buses meet here, so this is a junction
240 BOOST_CHECK( info.isJunction );
241 BOOST_CHECK( info.hasBusEntry );
242 // There are multiple wires but they don't count here
243 BOOST_CHECK( !info.hasBusEntryToMultipleWires );
244}
245
246BOOST_AUTO_TEST_CASE( WireCornerToBusEntry )
247{
248 /*
249 * ||
250 * ||
251 * ||
252 * \ /--- junction here
253 * \ |
254 * O-------------
255 * |
256 * |
257 */
258 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
259 items.insert( make_wire( { BE_SIZE, BE_SIZE }, { 2 * BE_SIZE, BE_SIZE } ) );
260 items.insert( make_wire( { BE_SIZE, BE_SIZE }, { BE_SIZE, 2 * BE_SIZE } ) );
261 items.insert( new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false ) );
262
263 const POINT_INFO info = AnalyzePoint( items, { BE_SIZE, BE_SIZE }, false );
264 BOOST_CHECK( info.isJunction );
265 BOOST_CHECK( info.hasBusEntry );
266 BOOST_CHECK( info.hasBusEntryToMultipleWires );
267}
268
269BOOST_AUTO_TEST_CASE( WireTeeToBusEntry )
270{
271 /*
272 * ||
273 * ||
274 * || |
275 * \ | /--- junction here
276 * \| /
277 * O-------------
278 * |
279 * |
280 */
281 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
282 items.insert( make_wire( { BE_SIZE, BE_SIZE }, { 2 * BE_SIZE, BE_SIZE } ) ); // right
283 items.insert( make_wire( { BE_SIZE, BE_SIZE }, { BE_SIZE, 0 } ) ); //up
284 items.insert( make_wire( { BE_SIZE, BE_SIZE }, { BE_SIZE, 2 * BE_SIZE } ) ); // down
285 items.insert( new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false ) );
286
287 const POINT_INFO info = AnalyzePoint( items, { BE_SIZE, BE_SIZE }, false );
288 BOOST_CHECK( info.isJunction );
289 BOOST_CHECK( info.hasBusEntry );
290 BOOST_CHECK( info.hasBusEntryToMultipleWires );
291}
292
293BOOST_AUTO_TEST_CASE( SheetPinToOneWire )
294{
295 /*
296 * ---+ ___not a junction
297 * |/
298 * |=>|---------
299 * |
300 * --+
301 */
302
303 // The point of interest is at (0, 0)
304
305 items.insert( make_wire( { 0, 0 }, { BE_SIZE, 0 } ) ); // right
306
307 SCH_SHEET* const sheet = new SCH_SHEET( nullptr, { -10 * BE_SIZE, -10 * BE_SIZE },
308 { 10 * BE_SIZE, 20 * BE_SIZE } );
309 SCH_SHEET_PIN* const pin = new SCH_SHEET_PIN( sheet, { 0, 0 }, "Pin Name" );
310 pin->SetSide( SHEET_SIDE::RIGHT );
311
312 sheet->AddPin( pin );
313 items.insert( sheet );
314
315 // This test won't make sense if the pin isn't where we think it is!
316 BOOST_REQUIRE( sheet->IsConnected( { 0, 0 } ) );
317
318 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
319 BOOST_CHECK( !info.isJunction );
320 BOOST_CHECK( !info.hasBusEntry );
321}
322
323BOOST_AUTO_TEST_CASE( SheetPinToTwoWires )
324{
325 /*
326 * A sheet pin counts as a wire, so this is a junction
327 *
328 * ---+ ___this is a junction
329 * |/
330 * |=>O---------
331 * |\
332 * | \
333 * | \
334 * --+
335 */
336 // The point of interest is at (0, 0)
337
338 items.insert( make_wire( { 0, 0 }, { BE_SIZE, 0 } ) ); // right
339 items.insert( make_wire( { 0, 0 }, { BE_SIZE, BE_SIZE } ) ); // right and down
340
341 SCH_SHEET* const sheet = new SCH_SHEET( nullptr, { -10 * BE_SIZE, -10 * BE_SIZE },
342 { 10 * BE_SIZE, 20 * BE_SIZE } );
343 SCH_SHEET_PIN* const pin = new SCH_SHEET_PIN( sheet, { 0, 0 }, "Pin Name" );
344 pin->SetSide( SHEET_SIDE::RIGHT );
345
346 sheet->AddPin( pin );
347 items.insert( sheet );
348
349 BOOST_REQUIRE( sheet->IsConnected( { 0, 0 } ) );
350
351 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
352 BOOST_CHECK( info.isJunction );
353 BOOST_CHECK( !info.hasBusEntry );
354}
355
356BOOST_AUTO_TEST_SUITE_END()
Implements an R-tree for fast spatial and type indexing of schematic items.
Definition: sch_rtree.h:40
VECTOR2I GetPosition() const override
VECTOR2I GetEnd() const
Class for a wire to bus entry.
bool IsConnected(const VECTOR2I &aPoint) const
Test the item to see if it is connected to aPoint.
Definition: sch_item.cpp:207
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:41
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:142
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:66
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
Definition: sch_sheet.cpp:426
@ LAYER_WIRE
Definition: layer_ids.h:356
@ LAYER_BUS
Definition: layer_ids.h:357
POINT_INFO AnalyzePoint(const EE_RTREE &aItem, const VECTOR2I &aPosition, bool aBreakCrossings)
Check a tree of items for a confluence at a given point and work out what kind of junction it is,...
A selection of information about a point in the schematic that might be eligible for turning into a j...
bool isJunction
< True if the point has 3+ wires and/or 3+ buses meeting there
bool hasBusEntry
True if there is a bus entry at the point and it connects to more than one wire.
BOOST_CHECK(box.ClosestPointTo(VECTOR2D(0, 0))==VECTOR2D(1, 2))
Test suite for KiCad math code.
static SCH_LINE * make_wire(const VECTOR2I &aStart, const VECTOR2I &aEnd)
BOOST_AUTO_TEST_CASE(Empty)
Check that we can get the basic properties out as expected.
static constexpr int BE_SIZE
static SCH_LINE * make_bus(const VECTOR2I &aStart, const VECTOR2I &aEnd)