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