KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_issue22864_align_sheet_pins.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 2
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-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 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
35
38
39#include <schematic.h>
40#include <sch_sheet.h>
41#include <sch_sheet_path.h>
42#include <sch_sheet_pin.h>
43#include <sch_screen.h>
44#include <sch_line.h>
46#include <locale_io.h>
47#include <base_units.h>
48
49#include <sch_item_alignment.h>
51
52
57{
58public:
59 TEST_GRID_HELPER( const VECTOR2D& aGridSize ) :
61 m_gridSize( aGridSize )
62 {
63 }
64
65 VECTOR2D GetGridSize( GRID_HELPER_GRIDS aGrid ) const override
66 {
67 return m_gridSize;
68 }
69
70private:
72};
73
74
76{
78
80 {
81 KI_TEST::LoadSchematic( m_settingsManager, "issue22864/Test_Move_Grid", m_schematic );
82 }
83
87 std::map<VECTOR2I, std::vector<SCH_LINE*>> BuildPositionToWiresMap( SCH_SCREEN* aScreen )
88 {
89 std::map<VECTOR2I, std::vector<SCH_LINE*>> positionToWires;
90
91 for( SCH_ITEM* item : aScreen->Items().OfType( SCH_LINE_T ) )
92 {
93 SCH_LINE* wire = static_cast<SCH_LINE*>( item );
94
95 if( wire->GetLayer() != LAYER_WIRE )
96 continue;
97
98 positionToWires[wire->GetStartPoint()].push_back( wire );
99 positionToWires[wire->GetEndPoint()].push_back( wire );
100 }
101
102 return positionToWires;
103 }
104
114 bool RunAlignmentAndVerify( SCH_SCREEN* aScreen, std::vector<EDA_ITEM*>& aSelection,
115 const VECTOR2D& aGridSize, const std::string& aTestName )
116 {
117 TEST_GRID_HELPER grid( aGridSize );
118
119 // Build position-to-wires map BEFORE alignment
120 auto positionToWires = BuildPositionToWiresMap( aScreen );
121
122 // Initialize items the same way AlignToGrid does in sch_move_tool.cpp (lines 2493-2508)
123 // This sets storedPos and flags that the move logic depends on.
124 std::set<EDA_ITEM*> selectionSet( aSelection.begin(), aSelection.end() );
125
126 for( SCH_ITEM* it : aScreen->Items() )
127 {
128 if( selectionSet.find( it ) == selectionSet.end() )
129 it->ClearFlags( STARTPOINT | ENDPOINT );
130 else
131 it->SetFlags( STARTPOINT | ENDPOINT );
132
133 it->SetStoredPos( it->GetPosition() );
134
135 if( it->Type() == SCH_SHEET_T )
136 {
137 for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( it )->GetPins() )
138 pin->SetStoredPos( pin->GetPosition() );
139 }
140 }
141
142 SCH_ALIGNMENT_CALLBACKS callbacks;
143
144 // Use the shared MoveSchematicItem function - the same logic used by production code
145 callbacks.m_doMoveItem = []( EDA_ITEM* aItem, const VECTOR2I& aDelta )
146 {
147 MoveSchematicItem( aItem, aDelta );
148 };
149
150 callbacks.m_getConnectedDragItems =
151 [&]( SCH_ITEM* aItem, const VECTOR2I& aPoint, EDA_ITEMS& aList )
152 {
153 auto it = positionToWires.find( aPoint );
154
155 if( it != positionToWires.end() )
156 {
157 for( SCH_LINE* wire : it->second )
158 {
159 // Skip selected wires - they will be processed in their own
160 // SCH_LINE_T block. This matches the real getConnectedDragItems
161 // behavior in sch_move_tool.cpp.
162 if( wire->HasFlag( SELECTED ) )
163 continue;
164
165 if( std::find( aList.begin(), aList.end(), wire ) == aList.end() )
166 {
167 wire->SetFlags( STARTPOINT | ENDPOINT );
168
169 if( wire->GetStartPoint() == aPoint )
170 wire->ClearFlags( ENDPOINT );
171 else
172 wire->ClearFlags( STARTPOINT );
173
174 aList.push_back( wire );
175 }
176 }
177 }
178 };
179
180 // Run alignment
181 AlignSchematicItemsToGrid( aScreen, aSelection, grid, GRID_CONNECTABLE, callbacks );
182
183 // Collect all pin positions
184 std::set<VECTOR2I> pinPositions;
185
186 for( SCH_ITEM* item : aScreen->Items().OfType( SCH_SHEET_T ) )
187 {
188 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
189
190 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
191 pinPositions.insert( pin->GetPosition() );
192 }
193
194 // Verify all wire endpoints connect to pins
195 bool allConnected = true;
196
197 for( SCH_ITEM* item : aScreen->Items().OfType( SCH_LINE_T ) )
198 {
199 SCH_LINE* wire = static_cast<SCH_LINE*>( item );
200
201 if( wire->GetLayer() != LAYER_WIRE )
202 continue;
203
204 VECTOR2I start = wire->GetStartPoint();
205 VECTOR2I end = wire->GetEndPoint();
206
207 bool startConnected = pinPositions.count( start ) > 0;
208 bool endConnected = pinPositions.count( end ) > 0;
209
210 if( !startConnected )
211 {
212 BOOST_TEST_MESSAGE( aTestName << ": Wire start (" << start.x << ", " << start.y
213 << ") not connected to any pin" );
214
215 for( const VECTOR2I& pinPos : pinPositions )
216 {
217 BOOST_TEST_MESSAGE( " Available pin at (" << pinPos.x << ", " << pinPos.y
218 << ")" );
219 }
220
221 allConnected = false;
222 }
223
224 if( !endConnected )
225 {
226 BOOST_TEST_MESSAGE( aTestName << ": Wire end (" << end.x << ", " << end.y
227 << ") not connected to any pin" );
228
229 for( const VECTOR2I& pinPos : pinPositions )
230 {
231 BOOST_TEST_MESSAGE( " Available pin at (" << pinPos.x << ", " << pinPos.y
232 << ")" );
233 }
234
235 allConnected = false;
236 }
237 }
238
239 return allConnected;
240 }
241
253 bool RunAlignmentAndVerifyNoSkew( SCH_SCREEN* aScreen, const std::vector<EDA_ITEM*>& aSelection,
254 const VECTOR2D& aGridSize, const std::string& aTestName )
255 {
256 std::set<EDA_ITEM*> selectionSet( aSelection.begin(), aSelection.end() );
257
258 // Record original wire endpoints to check for skew
259 std::map<SCH_LINE*, std::pair<VECTOR2I, VECTOR2I>> originalWireEndpoints;
260
261 for( SCH_ITEM* it : aScreen->Items().OfType( SCH_LINE_T ) )
262 {
263 SCH_LINE* wire = static_cast<SCH_LINE*>( it );
264
265 if( wire->GetLayer() == LAYER_WIRE )
266 originalWireEndpoints[wire] = { wire->GetStartPoint(), wire->GetEndPoint() };
267 }
268
269 TEST_GRID_HELPER grid( aGridSize );
270 std::map<VECTOR2I, std::vector<SCH_LINE*>> positionToWires =
271 BuildPositionToWiresMap( aScreen );
272
273 for( SCH_ITEM* it : aScreen->Items() )
274 {
275 if( selectionSet.find( it ) == selectionSet.end() )
276 it->ClearFlags( STARTPOINT | ENDPOINT );
277 else
278 it->SetFlags( STARTPOINT | ENDPOINT );
279
280 it->SetStoredPos( it->GetPosition() );
281
282 if( it->Type() == SCH_SHEET_T )
283 {
284 for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( it )->GetPins() )
285 pin->SetStoredPos( pin->GetPosition() );
286 }
287 }
288
289 SCH_ALIGNMENT_CALLBACKS callbacks;
290
291 callbacks.m_doMoveItem = []( EDA_ITEM* aItem, const VECTOR2I& aDelta )
292 {
293 MoveSchematicItem( aItem, aDelta );
294 };
295
296 callbacks.m_getConnectedDragItems =
297 [&]( SCH_ITEM* aItem, const VECTOR2I& aPoint, EDA_ITEMS& aList )
298 {
299 auto it = positionToWires.find( aPoint );
300
301 if( it != positionToWires.end() )
302 {
303 for( SCH_LINE* wire : it->second )
304 {
305 if( wire->HasFlag( SELECTED ) )
306 continue;
307
308 if( std::find( aList.begin(), aList.end(), wire ) == aList.end() )
309 {
310 wire->SetFlags( STARTPOINT | ENDPOINT );
311
312 if( wire->GetStartPoint() == aPoint )
313 wire->ClearFlags( ENDPOINT );
314 else
315 wire->ClearFlags( STARTPOINT );
316
317 aList.push_back( wire );
318 }
319 }
320 }
321 };
322
323 // Run alignment
324 AlignSchematicItemsToGrid( aScreen, aSelection, grid, GRID_CONNECTABLE, callbacks );
325
326 // Check for wire skew - wires should maintain their original orientation
327 bool noSkew = true;
328
329 for( const auto& [wire, origEndpoints] : originalWireEndpoints )
330 {
331 VECTOR2I origStart = origEndpoints.first;
332 VECTOR2I origEnd = origEndpoints.second;
333 VECTOR2I newStart = wire->GetStartPoint();
334 VECTOR2I newEnd = wire->GetEndPoint();
335
336 // Check if wire was originally horizontal (same Y)
337 bool wasHorizontal = ( origStart.y == origEnd.y );
338
339 // Check if wire is still horizontal
340 bool isHorizontal = ( newStart.y == newEnd.y );
341
342 if( wasHorizontal && !isHorizontal )
343 {
344 BOOST_TEST_MESSAGE( aTestName << ": Wire became skewed! Original: ("
345 << origStart.x << ", " << origStart.y << ") to ("
346 << origEnd.x << ", " << origEnd.y << "), Now: ("
347 << newStart.x << ", " << newStart.y << ") to ("
348 << newEnd.x << ", " << newEnd.y << ")" );
349 noSkew = false;
350 }
351
352 // Check if wire was originally vertical (same X)
353 bool wasVertical = ( origStart.x == origEnd.x );
354 bool isVertical = ( newStart.x == newEnd.x );
355
356 if( wasVertical && !isVertical )
357 {
358 BOOST_TEST_MESSAGE( aTestName << ": Wire became skewed! Original: ("
359 << origStart.x << ", " << origStart.y << ") to ("
360 << origEnd.x << ", " << origEnd.y << "), Now: ("
361 << newStart.x << ", " << newStart.y << ") to ("
362 << newEnd.x << ", " << newEnd.y << ")" );
363 noSkew = false;
364 }
365 }
366
367 // Also check connectivity - collect all pin positions
368 std::set<VECTOR2I> pinPositions;
369
370 for( SCH_ITEM* item : aScreen->Items().OfType( SCH_SHEET_T ) )
371 {
372 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
373
374 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
375 pinPositions.insert( pin->GetPosition() );
376 }
377
378 bool allConnected = true;
379
380 for( const auto& [wire, origEndpoints] : originalWireEndpoints )
381 {
382 VECTOR2I start = wire->GetStartPoint();
383 VECTOR2I end = wire->GetEndPoint();
384
385 bool startConnected = pinPositions.count( start ) > 0;
386 bool endConnected = pinPositions.count( end ) > 0;
387
388 if( !startConnected )
389 {
390 BOOST_TEST_MESSAGE( aTestName << ": Wire start (" << start.x << ", " << start.y
391 << ") not connected to any pin" );
392 allConnected = false;
393 }
394
395 if( !endConnected )
396 {
397 BOOST_TEST_MESSAGE( aTestName << ": Wire end (" << end.x << ", " << end.y
398 << ") not connected to any pin" );
399 allConnected = false;
400 }
401 }
402
403 // Return true only if both no skew AND all connected
404 return noSkew && allConnected;
405 }
406
408 std::unique_ptr<SCHEMATIC> m_schematic;
409};
410
411
412BOOST_AUTO_TEST_SUITE( Issue22864AlignSheetPins )
413
414
415
418BOOST_FIXTURE_TEST_CASE( AlignAllItemsStandardGrid, ISSUE22864_FIXTURE )
419{
422
423 SCH_SCREEN* screen = m_schematic->RootScreen();
424 BOOST_REQUIRE( screen != nullptr );
425
426 // Select all sheets
427 std::vector<EDA_ITEM*> selection;
428
429 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
430 selection.push_back( item );
431
432 BOOST_REQUIRE_EQUAL( selection.size(), 2 );
433
434 const VECTOR2D gridSize( schIUScale.mmToIU( 2.54 ), schIUScale.mmToIU( 2.54 ) );
435
436 bool allConnected = RunAlignmentAndVerify( screen, selection, gridSize,
437 "AlignAllItemsStandardGrid" );
438
439 BOOST_CHECK_MESSAGE( allConnected, "All wire endpoints should connect to pins after "
440 "aligning all items with 2.54mm grid" );
441}
442
443
448{
451
452 SCH_SCREEN* screen = m_schematic->RootScreen();
453 BOOST_REQUIRE( screen != nullptr );
454
455 std::vector<EDA_ITEM*> selection;
456
457 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
458 selection.push_back( item );
459
460 const VECTOR2D gridSize( schIUScale.mmToIU( 1.27 ), schIUScale.mmToIU( 1.27 ) );
461
462 bool allConnected = RunAlignmentAndVerify( screen, selection, gridSize,
463 "AlignAllItemsFineGrid" );
464
465 BOOST_CHECK_MESSAGE( allConnected, "All wire endpoints should connect to pins after "
466 "aligning all items with 1.27mm grid" );
467}
468
469
474{
477
478 SCH_SCREEN* screen = m_schematic->RootScreen();
479 BOOST_REQUIRE( screen != nullptr );
480
481 std::vector<EDA_ITEM*> selection;
482
483 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
484 selection.push_back( item );
485
486 const VECTOR2D gridSize( schIUScale.mmToIU( 5.08 ), schIUScale.mmToIU( 5.08 ) );
487
488 bool allConnected = RunAlignmentAndVerify( screen, selection, gridSize,
489 "AlignAllItemsCoarseGrid" );
490
491 BOOST_CHECK_MESSAGE( allConnected, "All wire endpoints should connect to pins after "
492 "aligning all items with 5.08mm grid" );
493}
494
495
502{
505
506 SCH_SCREEN* screen = m_schematic->RootScreen();
507 BOOST_REQUIRE( screen != nullptr );
508
509 SCH_SHEET* sheet1 = nullptr;
510
511 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
512 {
513 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
514
515 if( sheet->GetName() == "sheet1" )
516 {
517 sheet1 = sheet;
518 break;
519 }
520 }
521
522 BOOST_REQUIRE( sheet1 != nullptr );
523
524 std::vector<EDA_ITEM*> selection{ sheet1 };
525 const VECTOR2D gridSize( schIUScale.mmToIU( 2.54 ), schIUScale.mmToIU( 2.54 ) );
526
527 bool success = RunAlignmentAndVerifyNoSkew( screen, selection, gridSize, "AlignSheet1Only" );
528 BOOST_CHECK_MESSAGE( success, "Wires should remain straight and connected when aligning only sheet1" );
529}
530
531
538{
541
542 SCH_SCREEN* screen = m_schematic->RootScreen();
543 BOOST_REQUIRE( screen != nullptr );
544
545 SCH_SHEET* sheet2 = nullptr;
546
547 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
548 {
549 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
550
551 if( sheet->GetName() == "sheet2" )
552 {
553 sheet2 = sheet;
554 break;
555 }
556 }
557
558 BOOST_REQUIRE( sheet2 != nullptr );
559
560 std::vector<EDA_ITEM*> selection{ sheet2 };
561 const VECTOR2D gridSize( schIUScale.mmToIU( 2.54 ), schIUScale.mmToIU( 2.54 ) );
562
563 bool success = RunAlignmentAndVerifyNoSkew( screen, selection, gridSize, "AlignSheet2Only" );
564
565 BOOST_CHECK_MESSAGE( success, "Wires should remain straight and connected when aligning only sheet2" );
566}
567
568
575{
578
579 SCH_SCREEN* screen = m_schematic->RootScreen();
580 BOOST_REQUIRE( screen != nullptr );
581
582 SCH_SHEET* sheet1 = nullptr;
583 SCH_SHEET* sheet2 = nullptr;
584
585 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
586 {
587 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
588
589 if( sheet->GetName() == "sheet1" )
590 sheet1 = sheet;
591 else if( sheet->GetName() == "sheet2" )
592 sheet2 = sheet;
593 }
594
595 BOOST_REQUIRE( sheet1 != nullptr );
596 BOOST_REQUIRE( sheet2 != nullptr );
597
598 const VECTOR2D gridSize( schIUScale.mmToIU( 2.54 ), schIUScale.mmToIU( 2.54 ) );
599
600 // First align sheet1
601 std::vector<EDA_ITEM*> selection1{ sheet1 };
602 bool success1 = RunAlignmentAndVerifyNoSkew( screen, selection1, gridSize,
603 "AlignSheet1ThenSheet2 (step 1)" );
604
605 BOOST_CHECK_MESSAGE( success1, "Wires should remain straight and connected after aligning sheet1" );
606
607 // Then align sheet2
608 std::vector<EDA_ITEM*> selection2{ sheet2 };
609 bool success2 = RunAlignmentAndVerifyNoSkew( screen, selection2, gridSize,
610 "AlignSheet1ThenSheet2 (step 2)" );
611
612 BOOST_CHECK_MESSAGE( success2, "Wires should remain straight and connected after aligning sheet2" );
613}
614
615
622{
625
626 SCH_SCREEN* screen = m_schematic->RootScreen();
627 BOOST_REQUIRE( screen != nullptr );
628
629 SCH_SHEET* sheet1 = nullptr;
630 SCH_SHEET* sheet2 = nullptr;
631
632 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
633 {
634 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
635
636 if( sheet->GetName() == "sheet1" )
637 sheet1 = sheet;
638 else if( sheet->GetName() == "sheet2" )
639 sheet2 = sheet;
640 }
641
642 BOOST_REQUIRE( sheet1 != nullptr );
643 BOOST_REQUIRE( sheet2 != nullptr );
644
645 const VECTOR2D gridSize( schIUScale.mmToIU( 2.54 ), schIUScale.mmToIU( 2.54 ) );
646
647 // First align sheet2
648 std::vector<EDA_ITEM*> selection2{ sheet2 };
649 bool success2 = RunAlignmentAndVerifyNoSkew( screen, selection2, gridSize,
650 "AlignSheet2ThenSheet1 (step 1)" );
651
652 BOOST_CHECK_MESSAGE( success2, "Wires should remain straight and connected after aligning sheet2" );
653
654 // Then align sheet1
655 std::vector<EDA_ITEM*> selection1{ sheet1 };
656 bool success1 = RunAlignmentAndVerifyNoSkew( screen, selection1, gridSize,
657 "AlignSheet2ThenSheet1 (step 2)" );
658
659 BOOST_CHECK_MESSAGE( success1, "Wires should remain straight and connected after aligning sheet1" );
660}
661
662
667{
670
671 SCH_SCREEN* screen = m_schematic->RootScreen();
672 BOOST_REQUIRE( screen != nullptr );
673
674 std::vector<EDA_ITEM*> selection;
675
676 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
677 selection.push_back( item );
678
679 // Test with progressively finer grids
680 std::vector<double> gridSizesMm = { 5.08, 2.54, 1.27, 0.635 };
681
682 for( double gridMm : gridSizesMm )
683 {
684 // Reload schematic for fresh state
686 screen = m_schematic->RootScreen();
687 selection.clear();
688
689 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
690 selection.push_back( item );
691
692 const VECTOR2D gridSize( schIUScale.mmToIU( gridMm ), schIUScale.mmToIU( gridMm ) );
693
694 std::stringstream testName;
695 testName << "AlignMultipleGridSizes (" << gridMm << "mm)";
696
697 bool allConnected = RunAlignmentAndVerify( screen, selection, gridSize, testName.str() );
698
699 BOOST_CHECK_MESSAGE( allConnected, "All wire endpoints should connect to pins with "
700 << gridMm << "mm grid" );
701 }
702}
703
704
708BOOST_FIXTURE_TEST_CASE( VerifyPinWireYCoordinateMatch, ISSUE22864_FIXTURE )
709{
712
713 SCH_SCREEN* screen = m_schematic->RootScreen();
714 BOOST_REQUIRE( screen != nullptr );
715
716 std::vector<EDA_ITEM*> selection;
717
718 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
719 selection.push_back( item );
720
721 const VECTOR2D gridSize( schIUScale.mmToIU( 2.54 ), schIUScale.mmToIU( 2.54 ) );
722 TEST_GRID_HELPER grid( gridSize );
723
724 auto positionToWires = BuildPositionToWiresMap( screen );
725
726 SCH_ALIGNMENT_CALLBACKS callbacks;
727
728 callbacks.m_doMoveItem = []( EDA_ITEM* aItem, const VECTOR2I& aDelta )
729 {
730 if( aItem->Type() == SCH_SHEET_T )
731 static_cast<SCH_SHEET*>( aItem )->Move( aDelta );
732 else
733 MoveSchematicItem( aItem, aDelta );
734 };
735
736 callbacks.m_getConnectedDragItems =
737 [&]( SCH_ITEM* aItem, const VECTOR2I& aPoint, EDA_ITEMS& aList )
738 {
739 auto it = positionToWires.find( aPoint );
740
741 if( it != positionToWires.end() )
742 {
743 for( SCH_LINE* wire : it->second )
744 {
745 if( std::find( aList.begin(), aList.end(), wire ) == aList.end() )
746 {
747 wire->SetFlags( STARTPOINT | ENDPOINT );
748
749 if( wire->GetStartPoint() == aPoint )
750 wire->ClearFlags( ENDPOINT );
751 else
752 wire->ClearFlags( STARTPOINT );
753
754 aList.push_back( wire );
755 }
756 }
757 }
758 };
759
760 AlignSchematicItemsToGrid( screen, selection, grid, GRID_CONNECTABLE, callbacks );
761
762 // For each sheet, verify each pin has a wire endpoint at the same position
763 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
764 {
765 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
766
767 for( SCH_SHEET_PIN* pin : sheet->GetPins() )
768 {
769 VECTOR2I pinPos = pin->GetPosition();
770 bool foundWire = false;
771
772 for( SCH_ITEM* wireItem : screen->Items().OfType( SCH_LINE_T ) )
773 {
774 SCH_LINE* wire = static_cast<SCH_LINE*>( wireItem );
775
776 if( wire->GetLayer() != LAYER_WIRE )
777 continue;
778
779 if( wire->GetStartPoint() == pinPos || wire->GetEndPoint() == pinPos )
780 {
781 foundWire = true;
782 break;
783 }
784 }
785
786 BOOST_CHECK_MESSAGE( foundWire,
787 "Pin at (" << pinPos.x << ", " << pinPos.y
788 << ") should have a connected wire endpoint" );
789 }
790 }
791}
792
793
799BOOST_FIXTURE_TEST_CASE( AlignSheetsAndWiresTogether, ISSUE22864_FIXTURE )
800{
803
804 SCH_SCREEN* screen = m_schematic->RootScreen();
805 BOOST_REQUIRE( screen != nullptr );
806
807 // Select ALL sheets AND wires (simulates Ctrl+A or Select All)
808 std::vector<EDA_ITEM*> selection;
809
810 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
811 {
812 item->SetFlags( SELECTED );
813 selection.push_back( item );
814 }
815
816 for( SCH_ITEM* item : screen->Items().OfType( SCH_LINE_T ) )
817 {
818 SCH_LINE* wire = static_cast<SCH_LINE*>( item );
819
820 if( wire->GetLayer() == LAYER_WIRE )
821 {
822 wire->SetFlags( SELECTED );
823 selection.push_back( wire );
824 }
825 }
826
827 BOOST_REQUIRE_GE( selection.size(), 4 ); // At least 2 sheets + 2 wires
828
829 const VECTOR2D gridSize( schIUScale.mmToIU( 2.54 ), schIUScale.mmToIU( 2.54 ) );
830
831 bool allConnected = RunAlignmentAndVerify( screen, selection, gridSize,
832 "AlignSheetsAndWiresTogether" );
833
834 BOOST_CHECK_MESSAGE( allConnected,
835 "All wire endpoints should connect to pins after aligning "
836 "both sheets AND wires together (Select All scenario)" );
837}
838
839
843BOOST_FIXTURE_TEST_CASE( AlignSheetsAndWiresMultipleGrids, ISSUE22864_FIXTURE )
844{
845 std::vector<double> gridSizesMm = { 5.08, 2.54, 1.27, 0.635 };
846
847 for( double gridMm : gridSizesMm )
848 {
851
852 SCH_SCREEN* screen = m_schematic->RootScreen();
853 BOOST_REQUIRE( screen != nullptr );
854
855 // Select ALL sheets AND wires
856 std::vector<EDA_ITEM*> selection;
857
858 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
859 {
860 item->SetFlags( SELECTED );
861 selection.push_back( item );
862 }
863
864 for( SCH_ITEM* item : screen->Items().OfType( SCH_LINE_T ) )
865 {
866 SCH_LINE* wire = static_cast<SCH_LINE*>( item );
867
868 if( wire->GetLayer() == LAYER_WIRE )
869 {
870 wire->SetFlags( SELECTED );
871 selection.push_back( wire );
872 }
873 }
874
875 const VECTOR2D gridSize( schIUScale.mmToIU( gridMm ), schIUScale.mmToIU( gridMm ) );
876
877 std::stringstream testName;
878 testName << "AlignSheetsAndWiresMultipleGrids (" << gridMm << "mm)";
879
880 bool allConnected = RunAlignmentAndVerify( screen, selection, gridSize, testName.str() );
881
882 BOOST_CHECK_MESSAGE( allConnected,
883 "All wire endpoints should connect to pins with "
884 << gridMm << "mm grid when sheets AND wires are selected" );
885 }
886}
887
888
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:147
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:149
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:151
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:241
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:41
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:167
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition sch_item.h:340
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:42
VECTOR2I GetEndPoint() const
Definition sch_line.h:148
VECTOR2I GetStartPoint() const
Definition sch_line.h:139
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:118
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:48
wxString GetName() const
Definition sch_sheet.h:142
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition sch_sheet.h:233
Helper class to test grid alignment with configurable grid size.
TEST_GRID_HELPER(const VECTOR2D &aGridSize)
VECTOR2D GetGridSize(GRID_HELPER_GRIDS aGrid) const override
Return the size of the specified grid.
#define SELECTED
Item was manually selected by the user.
#define ENDPOINT
ends. (Used to support dragging.)
#define STARTPOINT
When a line is selected, these flags indicate which.
GRID_HELPER_GRIDS
Definition grid_helper.h:44
@ GRID_CONNECTABLE
Definition grid_helper.h:48
@ LAYER_WIRE
Definition layer_ids.h:452
void LoadSchematic(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< SCHEMATIC > &aSchematic)
static void LoadSchematic(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const wxString &aFileName)
void MoveSchematicItem(EDA_ITEM *aItem, const VECTOR2I &aDelta)
Move a schematic item by a delta.
void AlignSchematicItemsToGrid(SCH_SCREEN *aScreen, const std::vector< EDA_ITEM * > &aItems, EE_GRID_HELPER &aGrid, GRID_HELPER_GRIDS aSelectionGrid, const SCH_ALIGNMENT_CALLBACKS &aCallbacks)
Align a set of schematic items to the grid.
std::vector< EDA_ITEM * > EDA_ITEMS
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
std::vector< FAB_LAYER_COLOR > dummy
std::unique_ptr< SCHEMATIC > m_schematic
std::map< VECTOR2I, std::vector< SCH_LINE * > > BuildPositionToWiresMap(SCH_SCREEN *aScreen)
Build a map of positions to connected wires for the callback.
bool RunAlignmentAndVerifyNoSkew(SCH_SCREEN *aScreen, const std::vector< EDA_ITEM * > &aSelection, const VECTOR2D &aGridSize, const std::string &aTestName)
Run alignment and verify that wires are not skewed.
bool RunAlignmentAndVerify(SCH_SCREEN *aScreen, std::vector< EDA_ITEM * > &aSelection, const VECTOR2D &aGridSize, const std::string &aTestName)
Run alignment on selected items and verify wire connectivity.
Callbacks for alignment operations.
std::function< void(SCH_ITEM *aItem, const VECTOR2I &aPoint, EDA_ITEMS &aList)> m_getConnectedDragItems
Callback to get items connected to a given item at a specific point.
std::function< void(EDA_ITEM *aItem, const VECTOR2I &aDelta)> m_doMoveItem
Callback to move an item by a delta.
BOOST_FIXTURE_TEST_CASE(BoardTypes, PROTO_TEST_FIXTURE)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_FIXTURE_TEST_CASE(AlignAllItemsStandardGrid, ISSUE22864_FIXTURE)
Test aligning all items with standard grid (2.54mm).
KIBIS_PIN * pin
VECTOR2I end
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
@ SCH_LINE_T
Definition typeinfo.h:167
@ SCH_SHEET_T
Definition typeinfo.h:179
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694