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 The 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, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <junction_helpers.h>
23
24#include <sch_bus_entry.h>
25#include <sch_line.h>
26#include <sch_sheet.h>
27#include <sch_sheet_pin.h>
28
29using namespace JUNCTION_HELPERS;
30
31static constexpr int BE_SIZE = 25400;
32
37
38static SCH_LINE* make_wire( const VECTOR2I& aStart, const VECTOR2I& aEnd )
39{
40 SCH_LINE* const line = new SCH_LINE{ aStart, LAYER_WIRE };
41 line->SetEndPoint( aEnd );
42 return line;
43}
44
45static SCH_LINE* make_bus( const VECTOR2I& aStart, const VECTOR2I& aEnd )
46{
47 SCH_LINE* const line = new SCH_LINE{ aStart, LAYER_BUS };
48 line->SetEndPoint( aEnd );
49 return line;
50}
51
52BOOST_FIXTURE_TEST_SUITE( JunctionHelpers, JUNCTION_HELPER_FIXTURE )
53
54
58{
59 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
60
61 BOOST_CHECK( !info.isJunction );
62}
63
64BOOST_AUTO_TEST_CASE( SingleWireEnd )
65{
66 /*
67 * not a junction
68 * V
69 * -----------
70 */
71 items.insert( make_wire( { 0, 0 }, { 0, 100 } ) );
72
73 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
74
75 BOOST_CHECK( !info.isJunction );
76}
77
79{
80 /*
81 * |
82 * |_____
83 * ^
84 * not a junction
85 */
86 items.insert( make_wire( { 0, 0 }, { 100, 0 } ) );
87 items.insert( make_wire( { 0, 0 }, { 0, 100 } ) );
88
89 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
90
91 BOOST_CHECK( !info.isJunction );
92}
93
95{
96 /*
97 * | /-- junction in the middle
98 * | /
99 * -----O------
100 */
101 items.insert( make_wire( { 0, 0 }, { 100, 0 } ) );
102 items.insert( make_wire( { 0, 0 }, { -100, 0 } ) );
103 items.insert( make_wire( { 0, 0 }, { 0, 100 } ) );
104
105 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
106
107 BOOST_CHECK( info.isJunction );
108 BOOST_CHECK( !info.hasBusEntry );
109 BOOST_CHECK( !info.hasBusEntryToMultipleWires );
110}
111
112BOOST_AUTO_TEST_CASE( WireFourWayStubCross )
113{
114 /*
115 * LTspice-style four-wire cross: four stubs meet at endpoints.
116 * Collinear pairs must not be merged away into an unmarked crossing.
117 *
118 * |
119 * |
120 * -----O-----
121 * |
122 * |
123 */
124 items.insert( make_wire( { 0, 0 }, { 100, 0 } ) );
125 items.insert( make_wire( { 0, 0 }, { -100, 0 } ) );
126 items.insert( make_wire( { 0, 0 }, { 0, 100 } ) );
127 items.insert( make_wire( { 0, 0 }, { 0, -100 } ) );
128
129 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
130
131 BOOST_CHECK( info.isJunction );
132}
133
134BOOST_AUTO_TEST_CASE( WireMidsegmentCross )
135{
136 /*
137 * Two continuous wires crossing mid-segment are not a junction
138 * (KiCad allows wires to cross without connecting).
139 *
140 * |
141 * |
142 * ------------
143 * |
144 * |
145 */
146 items.insert( make_wire( { -100, 0 }, { 100, 0 } ) );
147 items.insert( make_wire( { 0, -100 }, { 0, 100 } ) );
148
149 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
150
151 BOOST_CHECK( !info.isJunction );
152}
153
154BOOST_AUTO_TEST_CASE( BusEntryOnBus )
155{
156 /*
157 * || <-- not a junction (it is a connection!)
158 * ||\
159 * || \
160 * || \ <-- also not a junction
161 */
162
163 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
164
165 SCH_BUS_WIRE_ENTRY* const busEntry = new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false );
166
167 // Make sure the BE is where we think it is
168 BOOST_REQUIRE_EQUAL( busEntry->GetPosition(), VECTOR2I( 0, 0 ) );
169 BOOST_REQUIRE_EQUAL( busEntry->GetEnd(), VECTOR2I( BE_SIZE, BE_SIZE ) );
170
171 items.insert( busEntry );
172
173 // BE-bus point
174 const POINT_INFO info_start = AnalyzePoint( items, { 0, 0 }, false );
175 BOOST_CHECK( !info_start.isJunction );
176 BOOST_CHECK( info_start.hasBusEntry );
177
178 // Dangling end of the bus entry
179 const POINT_INFO info_end = AnalyzePoint( items, { BE_SIZE, BE_SIZE }, false );
180 BOOST_CHECK( !info_end.isJunction );
181 BOOST_CHECK( info_end.hasBusEntry );
182 // There is no wire here
183 BOOST_CHECK( !info_end.hasBusEntryToMultipleWires );
184}
185
186BOOST_AUTO_TEST_CASE( BusEntryToWire )
187{
188 /*
189 * \
190 * \ /--- <-- not a junction
191 * \V________________
192 */
193 SCH_BUS_WIRE_ENTRY* const busEntry = new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false );
194 items.insert( busEntry );
195 items.insert( make_wire( { BE_SIZE, BE_SIZE }, { 2 * BE_SIZE, BE_SIZE } ) );
196
197 const POINT_INFO info = AnalyzePoint( items, { BE_SIZE, BE_SIZE }, false );
198 BOOST_CHECK( !info.isJunction );
199 BOOST_CHECK( info.hasBusEntry );
200 // This is a single wire to a bus entry, not multiple
201 BOOST_CHECK( !info.hasBusEntryToMultipleWires );
202}
203
204BOOST_AUTO_TEST_CASE( WireDirectToBus )
205{
206 /*
207 * || /--- <-- not a junction
208 * ||______________
209 */
210 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
211 items.insert( make_wire( { 0, 0 }, { BE_SIZE, 0 } ) );
212
213 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
214 BOOST_CHECK( !info.isJunction );
215 BOOST_CHECK( !info.hasBusEntry );
216 // It's a single wire, and not a bus entry
217 BOOST_CHECK( !info.hasBusEntryToMultipleWires );
218}
219
220BOOST_AUTO_TEST_CASE( WireCrossingBus )
221{
222 /* || __ not a junction
223 * || /
224 * ______________________
225 * ||
226 * ||
227 */
228 items.insert( make_bus( { 0, 0 }, { 0, -BE_SIZE } ) );
229 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
230 items.insert( make_wire( { 0, 0 }, { BE_SIZE, 0 } ) );
231 items.insert( make_wire( { 0, 0 }, { -BE_SIZE, 0 } ) );
232
233 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
234 // Two wires and two buses meet, which isn't a junction
235 BOOST_CHECK( !info.isJunction );
236 BOOST_CHECK( !info.hasBusEntry );
237 BOOST_CHECK( !info.hasBusEntryToMultipleWires );
238}
239
240BOOST_AUTO_TEST_CASE( WireToBusEntryRoot )
241{
242 /*
243 * /--- <-- not a junction
244 * _____________
245 * ||\
246 * || \
247 * || \
248 */
249 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
250 items.insert( make_wire( { 0, 0 }, { BE_SIZE, 0 } ) );
251 items.insert( new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false ) );
252
253 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
254 BOOST_CHECK( !info.isJunction );
255 BOOST_CHECK( info.hasBusEntry );
256 // The bus/bus-entry point isn't valid
257 BOOST_CHECK( !info.hasBusEntryToMultipleWires );
258}
259
260BOOST_AUTO_TEST_CASE( WireCrossingBusEntryRoot )
261{
262 /* ||
263 * || /--- <-- it's a junction, but the client can choose not
264 * || to put a dot here
265 * ______________________
266 * ||\
267 * || \
268 * || \
269 */
270 items.insert( make_bus( { 0, 0 }, { 0, -BE_SIZE } ) );
271 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
272 items.insert( make_wire( { 0, 0 }, { BE_SIZE, 0 } ) );
273 items.insert( make_wire( { 0, 0 }, { -BE_SIZE, 0 } ) );
274 items.insert( new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false ) );
275
276 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
277 // Three buses meet here, so this is a junction
278 BOOST_CHECK( info.isJunction );
279 BOOST_CHECK( info.hasBusEntry );
280 // There are multiple wires but they don't count here
281 BOOST_CHECK( !info.hasBusEntryToMultipleWires );
282}
283
284BOOST_AUTO_TEST_CASE( WireCornerToBusEntry )
285{
286 /*
287 * ||
288 * ||
289 * ||
290 * \ /--- junction here
291 * \ |
292 * O-------------
293 * |
294 * |
295 */
296 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
297 items.insert( make_wire( { BE_SIZE, BE_SIZE }, { 2 * BE_SIZE, BE_SIZE } ) );
298 items.insert( make_wire( { BE_SIZE, BE_SIZE }, { BE_SIZE, 2 * BE_SIZE } ) );
299 items.insert( new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false ) );
300
301 const POINT_INFO info = AnalyzePoint( items, { BE_SIZE, BE_SIZE }, false );
302 BOOST_CHECK( info.isJunction );
303 BOOST_CHECK( info.hasBusEntry );
304 BOOST_CHECK( info.hasBusEntryToMultipleWires );
305}
306
307BOOST_AUTO_TEST_CASE( WireTeeToBusEntry )
308{
309 /*
310 * ||
311 * ||
312 * || |
313 * \ | /--- junction here
314 * \| /
315 * O-------------
316 * |
317 * |
318 */
319 items.insert( make_bus( { 0, 0 }, { 0, BE_SIZE } ) );
320 items.insert( make_wire( { BE_SIZE, BE_SIZE }, { 2 * BE_SIZE, BE_SIZE } ) ); // right
321 items.insert( make_wire( { BE_SIZE, BE_SIZE }, { BE_SIZE, 0 } ) ); //up
322 items.insert( make_wire( { BE_SIZE, BE_SIZE }, { BE_SIZE, 2 * BE_SIZE } ) ); // down
323 items.insert( new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false ) );
324
325 const POINT_INFO info = AnalyzePoint( items, { BE_SIZE, BE_SIZE }, false );
326 BOOST_CHECK( info.isJunction );
327 BOOST_CHECK( info.hasBusEntry );
328 BOOST_CHECK( info.hasBusEntryToMultipleWires );
329}
330
331BOOST_AUTO_TEST_CASE( SheetPinToOneWire )
332{
333 /*
334 * ---+ ___not a junction
335 * |/
336 * |=>|---------
337 * |
338 * --+
339 */
340
341 // The point of interest is at (0, 0)
342
343 items.insert( make_wire( { 0, 0 }, { BE_SIZE, 0 } ) ); // right
344
345 SCH_SHEET* const sheet = new SCH_SHEET( nullptr, { -10 * BE_SIZE, -10 * BE_SIZE },
346 { 10 * BE_SIZE, 20 * BE_SIZE } );
347 SCH_SHEET_PIN* const pin = new SCH_SHEET_PIN( sheet, { 0, 0 }, "Pin Name" );
348 pin->SetSide( SHEET_SIDE::RIGHT );
349
350 sheet->AddPin( pin );
351 items.insert( sheet );
352
353 // This test won't make sense if the pin isn't where we think it is!
354 BOOST_REQUIRE( sheet->IsConnected( { 0, 0 } ) );
355
356 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
357 BOOST_CHECK( !info.isJunction );
358 BOOST_CHECK( !info.hasBusEntry );
359}
360
361BOOST_AUTO_TEST_CASE( SheetPinToTwoWires )
362{
363 /*
364 * A sheet pin counts as a wire, so this is a junction
365 *
366 * ---+ ___this is a junction
367 * |/
368 * |=>O---------
369 * |\
370 * | \
371 * | \
372 * --+
373 */
374 // The point of interest is at (0, 0)
375
376 items.insert( make_wire( { 0, 0 }, { BE_SIZE, 0 } ) ); // right
377 items.insert( make_wire( { 0, 0 }, { BE_SIZE, BE_SIZE } ) ); // right and down
378
379 SCH_SHEET* const sheet = new SCH_SHEET( nullptr, { -10 * BE_SIZE, -10 * BE_SIZE },
380 { 10 * BE_SIZE, 20 * BE_SIZE } );
381 SCH_SHEET_PIN* const pin = new SCH_SHEET_PIN( sheet, { 0, 0 }, "Pin Name" );
382 pin->SetSide( SHEET_SIDE::RIGHT );
383
384 sheet->AddPin( pin );
385 items.insert( sheet );
386
387 BOOST_REQUIRE( sheet->IsConnected( { 0, 0 } ) );
388
389 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
390 BOOST_CHECK( info.isJunction );
391 BOOST_CHECK( !info.hasBusEntry );
392}
393
Implement an R-tree for fast spatial and type indexing of schematic items.
Definition sch_rtree.h:34
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:478
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:38
void SetEndPoint(const VECTOR2I &aPosition)
Definition sch_line.h:145
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:44
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
@ LAYER_WIRE
Definition layer_ids.h:458
@ LAYER_BUS
Definition layer_ids.h:459
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 hasBusEntryToMultipleWires
True if there is a bus entry at the point and it connects to more than one wire.
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 (either end)
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
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)
KIBIS_PIN * pin
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683