62 for(
RULE_AREA& ra : aTool->GetData()->m_areas )
64 if( ra.m_ruleName.Contains( ( aName ) ) )
75 if( ra.m_zone && ra.m_zone->GetPlacementAreaSource() == aGroupName )
88 if( zone == aRuleArea.
m_zone )
91 if( zone->GetZoneName() != aZoneName )
106 std::vector<wxString> tests = {
"vme-wren" };
108 for(
const wxString& relPath : tests )
115 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
124 auto ruleData = mtTool->
GetData();
127 static_cast<int>( ruleData->m_areas.size() ) ) );
133 ruleData->m_replaceExisting =
true;
138 || ra.
m_sheetName == wxT(
"pp_driver_2x.kicad_sch" ) )
152 int n_areas_io = 0, n_areas_pp = 0, n_areas_other = 0;
155 static_cast<int>(ruleData->m_areas.size() ) ) );
157 for(
const RULE_AREA& ra : ruleData->m_areas )
161 if( ra.
m_ruleName.Contains( wxT(
"io_drivers_fp" ) ) )
166 else if( ra.
m_ruleName.Contains( wxT(
"io_drivers_pp" ) ) )
178 n_areas_io, n_areas_pp, n_areas_other ) );
184 const std::vector<wxString> rulesToTest = { wxT(
"io_drivers_fp" ),
185 wxT(
"io_drivers_pp" ) };
187 for(
const wxString& ruleName : rulesToTest )
189 for(
const RULE_AREA& refArea : ruleData->m_areas )
191 if( !refArea.
m_ruleName.Contains( ruleName ) )
196 for(
const RULE_AREA& targetArea : ruleData->m_areas )
201 if( !targetArea.
m_ruleName.Contains( ruleName ) )
204 auto cgRef = CONNECTION_GRAPH::BuildFromFootprintSet( refArea.
m_components,
207 CONNECTION_GRAPH::BuildFromFootprintSet( targetArea.
m_components,
212 std::vector<TMATCH::TOPOLOGY_MISMATCH_REASON> details;
213 bool status = cgRef->FindIsomorphism( cgTarget.get(),
result, details );
216 "topo match: '%s' [%d] -> '%s' [%d] result %d", refArea.
m_ruleName.c_str().AsChar(),
218 static_cast<int>( targetArea.
m_components.size() ), status ? 1 : 0 ) );
220 for(
const auto& iter :
result )
223 iter.second->GetReference(),
224 iter.first->GetReference() ) );
227 BOOST_CHECK( status );
228 BOOST_CHECK( details.empty() );
235 BOOST_ASSERT( refArea );
237 const std::vector<wxString> targetAreaNames( { wxT(
"io_drivers_fp/bank2/io78/" ),
238 wxT(
"io_drivers_fp/bank1/io78/" ),
239 wxT(
"io_drivers_fp/bank0/io01/" ) } );
241 for(
const wxString& targetRaName : targetAreaNames )
245 BOOST_ASSERT( targetRA !=
nullptr );
249 ruleData->m_compatMap[targetRA].m_doCopy =
true;
254 BOOST_ASSERT(
result >= 0 );
270 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
277 auto ruleData = mtTool->
GetData();
280 static_cast<int>( ruleData->m_areas.size() ) ) );
282 BOOST_CHECK( ruleData->m_areas.size() >= 2 );
284 if( ruleData->m_areas.size() < 2 )
292 if( ra.
m_ruleName.Contains( wxT(
"Untitled Sheet/" ) ) )
294 else if( ra.
m_ruleName.Contains( wxT(
"Untitled Sheet1/" ) ) )
298 if( !refArea || !targetArea )
300 BOOST_TEST_MESSAGE(
"Could not find Untitled Sheet and Untitled Sheet1 rule areas, skipping test" );
328 if( !refFP || !targetFP )
330 BOOST_TEST_MESSAGE(
"Could not find matching footprints in the rule areas, skipping test" );
335 bool refValueVisible = refValueField ? refValueField->
IsVisible() :
true;
337 std::vector<FP_3DMODEL> refModels = refFP->
Models();
341 ruleData->m_compatMap[targetArea].m_doCopy =
true;
342 ruleData->m_options.m_copyPlacement =
true;
346 BOOST_CHECK(
result >= 0 );
350 if( targetValueField && refValueField )
354 refValueVisible, targetValueField->
IsVisible() ) );
359 if( !refModels.empty() )
362 static_cast<int>( refModels.size() ),
363 static_cast<int>( targetFP->
Models().size() ) ) );
382 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
389 auto ruleData = mtTool->
GetData();
392 static_cast<int>( ruleData->m_areas.size() ) ) );
396 if( ruleData->m_areas.size() < 2 )
413 int refViaCountBefore = 0;
415 for(
PCB_TRACK* track : m_board->Tracks() )
427 BOOST_TEST_MESSAGE( wxString::Format(
"Reference area vias before repeat: %d", refViaCountBefore ) );
428 BOOST_CHECK( refViaCountBefore > 0 );
432 ruleData->m_compatMap[targetArea].m_doCopy =
true;
433 ruleData->m_options.m_copyPlacement =
true;
434 ruleData->m_options.m_copyRouting =
true;
438 BOOST_CHECK(
result >= 0 );
440 int refViaCountAfter = 0;
442 for(
PCB_TRACK* track : m_board->Tracks() )
454 BOOST_TEST_MESSAGE( wxString::Format(
"Reference area vias after repeat: %d", refViaCountAfter ) );
471 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
534 auto cgRef = std::make_unique<CONNECTION_GRAPH>();
535 auto cgTarget = std::make_unique<CONNECTION_GRAPH>();
538 LIB_ID fpid( wxT(
"Package_SO" ), wxT(
"SOIC-8_3.9x4.9mm_P1.27mm" ) );
550 PAD padRef1( &fpRef );
553 fpRef.
Add( &padRef1 );
555 PAD padRef2( &fpRef );
558 fpRef.
Add( &padRef2 );
560 PAD padTarget1( &fpTarget );
563 fpTarget.
Add( &padTarget1 );
565 PAD padTarget2( &fpTarget );
568 fpTarget.
Add( &padTarget2 );
571 cgRef->AddFootprint( &fpRef,
VECTOR2I( 0, 0 ) );
572 cgTarget->AddFootprint( &fpTarget,
VECTOR2I( 0, 0 ) );
574 cgRef->BuildConnectivity();
575 cgTarget->BuildConnectivity();
581 COMPONENT* cmpRef = cgRef->Components()[0];
582 COMPONENT* cmpTarget = cgTarget->Components()[0];
584 bool sameKind = cmpRef->IsSameKind( *cmpTarget );
586 BOOST_TEST_MESSAGE( wxString::Format(
"TRIM_1.1 and TRIM_2.1 IsSameKind: %d", sameKind ? 1 : 0 ) );
587 BOOST_CHECK( sameKind );
591 std::vector<TMATCH::TOPOLOGY_MISMATCH_REASON> details;
592 bool status = cgRef->FindIsomorphism( cgTarget.get(),
result, details );
594 BOOST_TEST_MESSAGE( wxString::Format(
"Topology match result: %d", status ? 1 : 0 ) );
596 if( !status && !details.empty() )
598 for(
const auto& reason : details )
601 reason.m_reference, reason.m_candidate, reason.m_reason ) );
605 BOOST_CHECK( status );
606 BOOST_CHECK( details.empty() );
609 fpRef.
Pads().clear();
610 fpTarget.
Pads().clear();
629 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
636 auto ruleData = mtTool->
GetData();
644 if( ra.
m_sheetPath == wxT(
"/io_drivers_fp/bank0/io01/" ) )
646 else if( ra.
m_sheetPath == wxT(
"/io_drivers_fp/bank0/" ) )
648 else if( ra.
m_sheetPath == wxT(
"/io_drivers_fp/" ) )
656 BOOST_TEST_MESSAGE( wxString::Format(
"Leaf /io_drivers_fp/bank0/io01/ components: %d",
695 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
702 auto ruleData = mtTool->
GetData();
708 if( ra.
m_sheetName == wxT(
"io_driver.kicad_sch" ) )
722 auto cgRef = CONNECTION_GRAPH::BuildFromFootprintSet( refArea->
m_components,
724 auto cgTarget = CONNECTION_GRAPH::BuildFromFootprintSet( targetArea->
m_components,
729 std::atomic<bool> cancelled(
true );
730 std::atomic<int> matched( 0 );
731 std::atomic<int> total( 0 );
739 std::vector<TMATCH::TOPOLOGY_MISMATCH_REASON> details;
741 bool status = cgRef->FindIsomorphism( cgTarget.get(),
result, details, params );
743 BOOST_CHECK( !status );
744 BOOST_CHECK(
result.empty() );
751 std::atomic<bool> cancelled(
false );
752 std::atomic<int> matched( 0 );
753 std::atomic<int> total( 0 );
761 std::vector<TMATCH::TOPOLOGY_MISMATCH_REASON> details;
763 bool status = cgRef->FindIsomorphism( cgTarget.get(),
result, details, params );
765 BOOST_CHECK( status );
767 int finalMatched = matched.load();
768 int finalTotal = total.load();
770 BOOST_TEST_MESSAGE( wxString::Format(
"Progress: matched=%d, total=%d", finalMatched, finalTotal ) );
772 BOOST_CHECK( finalTotal > 0 );
779 std::vector<TMATCH::TOPOLOGY_MISMATCH_REASON> details;
781 bool status = cgRef->FindIsomorphism( cgTarget.get(),
result, details );
783 BOOST_CHECK( status );
784 BOOST_CHECK( !
result.empty() );
810 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
817 auto ruleData = mtTool->
GetData();
820 static_cast<int>( ruleData->m_areas.size() ) ) );
834 if( source == wxT(
"/i2c_thingy_ch0/" ) )
836 else if( source == wxT(
"/i2c_thingy_ch1/" ) )
840 BOOST_REQUIRE_MESSAGE( ch0Area !=
nullptr,
"Could not find i2c_thingy_ch0 rule area" );
841 BOOST_REQUIRE_MESSAGE( ch1Area !=
nullptr,
"Could not find i2c_thingy_ch1 rule area" );
849 auto cgRef = CONNECTION_GRAPH::BuildFromFootprintSet( ch0Area->
m_components,
851 auto cgTarget = CONNECTION_GRAPH::BuildFromFootprintSet( ch1Area->
m_components,
855 std::vector<TMATCH::TOPOLOGY_MISMATCH_REASON> details;
856 bool status = cgRef->FindIsomorphism( cgTarget.get(),
result, details );
860 for(
const auto& reason : details )
863 reason.m_reference, reason.m_candidate,
869 "Topology match failed for channels with hierarchical pins "
870 "tied to global nets (issue 21739)" );
884 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
887 auto addNet = [&](
const wxString& aName ) ->
int
894 const int netGnd = addNet( wxT(
"GND" ) );
895 const int netVcc = addNet( wxT(
"+5VP" ) );
896 const int netChainInRef = addNet( wxT(
"Net-(D-RefChainIn)" ) );
897 const int netBridge = addNet( wxT(
"Net-(D38-DOUT)" ) );
898 const int netChainOutTgt = addNet( wxT(
"Net-(D43-DOUT)" ) );
899 const int netD2Dout = addNet( wxT(
"unconnected-(D2-DOUT)" ) );
900 const int netD3Dout = addNet( wxT(
"unconnected-(D3-DOUT)" ) );
901 const int netD5Dout = addNet( wxT(
"unconnected-(D5-DOUT)" ) );
902 const int netD6Dout = addNet( wxT(
"unconnected-(D6-DOUT)" ) );
904 LIB_ID ledId( wxT(
"TestLib" ), wxT(
"WS2812" ) );
907 auto makeLed = [&](
const wxString& aRef,
int aDout,
int aDin ) ->
FOOTPRINT*
914 auto addPad = [&](
const wxString& aNumber,
int aNetCode )
917 pad->SetNumber( aNumber );
922 pad->SetNetCode( aNetCode );
926 addPad( wxT(
"1" ), aDout );
927 addPad( wxT(
"2" ), netGnd );
928 addPad( wxT(
"3" ), aDin );
929 addPad( wxT(
"4" ), netVcc );
936 std::set<FOOTPRINT*> refFps;
937 refFps.insert( makeLed( wxT(
"D1" ), netBridge, netChainInRef ) );
938 refFps.insert( makeLed( wxT(
"D2" ), netD2Dout, netChainInRef ) );
939 refFps.insert( makeLed( wxT(
"D3" ), netD3Dout, netChainInRef ) );
943 std::set<FOOTPRINT*> tgtFps;
944 tgtFps.insert( makeLed( wxT(
"D4" ), netChainOutTgt, netBridge ) );
945 tgtFps.insert( makeLed( wxT(
"D5" ), netD5Dout, netBridge ) );
946 tgtFps.insert( makeLed( wxT(
"D6" ), netD6Dout, netBridge ) );
948 auto cgRef = CONNECTION_GRAPH::BuildFromFootprintSet( refFps, tgtFps );
949 auto cgTarget = CONNECTION_GRAPH::BuildFromFootprintSet( tgtFps, refFps );
952 std::vector<TMATCH::TOPOLOGY_MISMATCH_REASON> details;
953 bool status = cgRef->FindIsomorphism( cgTarget.get(),
result, details );
957 for(
const auto& reason : details )
960 reason.m_reference, reason.m_candidate,
966 "Topology match failed because the design-block boundary signal net "
967 "was misclassified as a global rail and excluded asymmetrically" );
983 m_board = std::make_unique<BOARD>();
999 pad->SetNumber( wxT(
"1" ) );
1001 pad->SetPosition( aPos );
1013 FOOTPRINT* refFp1 = makeFootprint( wxT(
"R1" ),
1015 FOOTPRINT* refFp2 = makeFootprint( wxT(
"R2" ),
1023 m_board->Add( silkRect );
1026 FOOTPRINT* destFp1 = makeFootprint( wxT(
"R3" ),
1028 FOOTPRINT* destFp2 = makeFootprint( wxT(
"R4" ),
1032 destGroup->
SetName( wxT(
"design-block-dest" ) );
1033 destGroup->
AddItem( destFp1 );
1034 destGroup->
AddItem( destFp2 );
1035 m_board->Add( destGroup );
1044 m_board->Add( unrelatedSilk );
1048 for(
BOARD_ITEM* item : m_board->Drawings() )
1054 BOOST_REQUIRE_EQUAL( silkBefore, 2 );
1087 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
1093 .m_connectedRoutingOnly =
false,
1094 .m_copyPlacement =
true,
1095 .m_copyOtherItems =
true,
1096 .m_groupItems =
false,
1097 .m_includeLockedItems =
true,
1098 .m_anchorFp =
nullptr };
1110 int silkInGroup = 0;
1111 bool unrelatedSurvived =
false;
1114 for(
BOARD_ITEM* item : m_board->Drawings() )
1121 if( item == unrelatedSilk )
1122 unrelatedSurvived =
true;
1124 if( item->GetParentGroup() == destGroup )
1136 wxString::Format(
"Expected 3 silkscreen shapes after Apply Design Block "
1137 "Layout (2 original + 1 copy), found %d (issue 24372)",
1140 wxString::Format(
"Expected 1 silkscreen shape in destination group, "
1141 "found %d (issue 24372)",
1144 "Unrelated silkscreen drawing outside the design block group was "
1145 "deleted by Apply Design Block Layout (issue 24372)" );
1164 m_board = std::make_unique<BOARD>();
1168 m_board->Add( net );
1170 auto makeFootprint = [&](
const wxString& aRef,
const VECTOR2I& aPos ) ->
FOOTPRINT*
1181 txt->
SetText( wxT(
"${REFERENCE}" ) );
1188 pad->SetNumber( wxT(
"1" ) );
1190 pad->SetPosition( aPos );
1205 if( item->Type() ==
PCB_TEXT_T && item->GetLayer() == layer )
1219 destGroup->
SetName( wxT(
"design-block-dest" ) );
1220 destGroup->
AddItem( destFp1 );
1221 destGroup->
AddItem( destFp2 );
1222 m_board->Add( destGroup );
1224 BOOST_REQUIRE_EQUAL( countSilkText( destFp1,
F_SilkS ), 1 );
1225 BOOST_REQUIRE_EQUAL( countSilkText( destFp1,
B_SilkS ), 1 );
1255 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
1261 .m_connectedRoutingOnly =
false,
1262 .m_copyPlacement =
true,
1263 .m_copyOtherItems =
true,
1264 .m_groupItems =
false,
1265 .m_includeLockedItems =
true,
1266 .m_anchorFp =
nullptr };
1275 for(
FOOTPRINT* destFp : { destFp1, destFp2 } )
1278 wxString::Format(
"%s lost its F.Silkscreen reference text "
1279 "(issue 24583): F=%d B=%d",
1280 destFp->GetReference(), countSilkText( destFp,
F_SilkS ),
1281 countSilkText( destFp,
B_SilkS ) ) );
1293 m_board = std::make_unique<BOARD>();
1317 m_board->Add( destPlaceholder );
1320 destGroup->
SetName( wxT(
"design-block-dest" ) );
1321 destGroup->
AddItem( destPlaceholder );
1322 m_board->Add( destGroup );
1326 for(
BOARD_ITEM* item : m_board->Drawings() )
1332 BOOST_REQUIRE_EQUAL( silkBefore, 2 );
1360 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
1366 .m_connectedRoutingOnly =
false,
1367 .m_copyPlacement =
true,
1368 .m_copyOtherItems =
true,
1369 .m_groupItems =
false,
1370 .m_includeLockedItems =
true,
1371 .m_anchorFp =
nullptr };
1379 BOOST_REQUIRE_MESSAGE(
result >= 0, wxString::Format(
"RepeatLayout failed for a footprint-free "
1380 "(graphics-only) design block (issue 24592): %s",
1388 for(
BOARD_ITEM* item : m_board->Drawings() )
1401 BOOST_CHECK_MESSAGE( silkAfter == 2, wxString::Format(
"Expected 2 silkscreen shapes after Apply Design Block "
1402 "Layout (source + 1 copy, placeholder replaced), found "
1405 BOOST_REQUIRE_MESSAGE( copiedRect !=
nullptr,
"Footprint-free block graphic was not copied (issue 24592)" );
1407 "Copied block graphic was not added to the destination group (issue 24592)" );
1418 m_board = std::make_unique<BOARD>();
1422 m_board->Add( net );
1431 m_board->Add( srcTrack );
1433 BOOST_REQUIRE_EQUAL( srcTrack->
GetNetCode(), 1 );
1441 m_board->Add( destPlaceholder );
1444 destGroup->
SetName( wxT(
"design-block-dest" ) );
1445 destGroup->
AddItem( destPlaceholder );
1446 m_board->Add( destGroup );
1474 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
1480 .m_connectedRoutingOnly =
false,
1481 .m_copyPlacement =
true,
1482 .m_copyOtherItems =
true,
1483 .m_groupItems =
false,
1484 .m_includeLockedItems =
true,
1485 .m_anchorFp =
nullptr };
1493 BOOST_REQUIRE_MESSAGE(
result >= 0, wxString::Format(
"RepeatLayout failed for a footprint-free copper "
1494 "block (issue 24592): %s",
1500 for(
PCB_TRACK* track : m_board->Tracks() )
1502 if( track != srcTrack )
1503 copiedTrack = track;
1506 BOOST_REQUIRE_MESSAGE( copiedTrack !=
nullptr,
"Footprint-free block track was not copied (issue 24592)" );
1508 wxString::Format(
"Copied copper should be no-net, got net code %d "
1512 "Copied copper was not added to the destination group (issue 24592)" );
1527 m_board = std::make_unique<BOARD>();
1536 m_board->Add( srcRect );
1544 m_board->Add( destPlaceholder );
1547 destGroup->
SetName( wxT(
"design-block-dest" ) );
1548 destGroup->
AddItem( destPlaceholder );
1549 m_board->Add( destGroup );
1553 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
1558 auto applyOnce = [&]() ->
int
1585 .m_connectedRoutingOnly =
false,
1586 .m_copyPlacement =
true,
1587 .m_copyOtherItems =
true,
1588 .m_groupItems =
false,
1589 .m_includeLockedItems =
true,
1590 .m_anchorFp =
nullptr };
1599 BOOST_REQUIRE_MESSAGE( applyOnce() >= 0,
"First apply failed (issue 24592)" );
1600 BOOST_REQUIRE_MESSAGE( applyOnce() >= 0,
"Second apply failed (issue 24592)" );
1606 for(
BOARD_ITEM* item : m_board->Drawings() )
1615 BOOST_CHECK_MESSAGE( rects == 2, wxString::Format(
"Re-apply stacked copies: expected 2 rectangles "
1616 "(source + 1 copy), found %d (issue 24592)",
1630 m_board = std::make_unique<BOARD>();
1634 m_board->Add( net );
1643 m_board->Add( srcTrack );
1651 m_board->Add( destPlaceholder );
1654 destGroup->
SetName( wxT(
"design-block-dest" ) );
1655 destGroup->
AddItem( destPlaceholder );
1656 m_board->Add( destGroup );
1664 m_board->Add( siblingTrack );
1667 siblingGroup->
SetName( wxT(
"design-block-sibling" ) );
1668 siblingGroup->
AddItem( siblingTrack );
1669 m_board->Add( siblingGroup );
1677 m_board->Add( looseTrack );
1705 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
1711 .m_connectedRoutingOnly =
false,
1712 .m_copyPlacement =
true,
1713 .m_copyOtherItems =
true,
1714 .m_groupItems =
false,
1715 .m_includeLockedItems =
true,
1716 .m_anchorFp =
nullptr };
1724 BOOST_REQUIRE_MESSAGE(
result >= 0, wxString::Format(
"RepeatLayout failed: %s", err ) );
1727 int siblingTracks = 0;
1728 int looseTracks = 0;
1730 for(
PCB_TRACK* track : m_board->Tracks() )
1732 int y = track->GetStart().y;
1741 wxString::Format(
"Sibling group routing was deleted (issue 24767): found %d, expected 1",
1744 wxString::Format(
"Loose routing in the target area should be replaced: found %d, expected 0",
1762 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
1769 auto ruleData = mtTool->
GetData();
1772 static_cast<int>( ruleData->m_areas.size() ) ) );
1774 BOOST_REQUIRE_EQUAL( ruleData->m_areas.size(), 4 );
1777 const size_t sharedCount = ruleData->m_areas.front().m_components.size();
1781 for(
const RULE_AREA& ra : ruleData->m_areas )
1784 RULE_AREA* refArea = &ruleData->m_areas.front();
1788 BOOST_REQUIRE_EQUAL( ruleData->m_compatMap.size(), ruleData->m_areas.size() - 1 );
1790 for(
const auto& [targetArea, compatData] : ruleData->m_compatMap )
1793 "Duplicate placement area was wrongly reported as a valid copy target "
1795 BOOST_CHECK( !compatData.m_mismatchReasons.empty() );
1799 RULE_AREA* targetArea = &ruleData->m_areas[1];
1807 "RepeatLayout copied a Rule Area onto an identical-component area "
1809 BOOST_CHECK( !err.IsEmpty() );
1831 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
1838 auto ruleData = mtTool->
GetData();
1841 static_cast<int>( ruleData->m_areas.size() ) ) );
1843 BOOST_REQUIRE_EQUAL( ruleData->m_areas.size(), 4 );
1847 for(
RULE_AREA& ra : ruleData->m_areas )
1855 std::set<KIID> groupUuidsBefore;
1856 std::set<wxString> userGroupNamesBefore;
1860 groupUuidsBefore.insert(
group->m_Uuid );
1862 if( !
group->GetName().IsEmpty() )
1863 userGroupNamesBefore.insert(
group->GetName() );
1868 for(
auto& [targetArea, compatData] : ruleData->m_compatMap )
1869 compatData.m_doCopy =
true;
1871 ruleData->m_options.m_copyPlacement =
true;
1872 ruleData->m_options.m_copyRouting =
true;
1873 ruleData->m_options.m_copyOtherItems =
true;
1874 ruleData->m_options.m_groupItems =
true;
1875 ruleData->m_options.m_includeLockedItems =
true;
1881 int clonedUserGroups = 0;
1885 bool isNew = !groupUuidsBefore.contains(
group->m_Uuid );
1887 if( isNew && userGroupNamesBefore.contains(
group->GetName() ) )
1892 wxString::Format(
"Repeat layout cloned %d unrelated user groups "
1894 clonedUserGroups ) );
1913 toolMgr.
SetEnvironment( m_board.get(),
nullptr,
nullptr,
nullptr, toolsHolder );
1920 auto ruleData = mtTool->
GetData();
1922 BOOST_REQUIRE_EQUAL( ruleData->m_areas.size(), 2 );
1927 for(
RULE_AREA& ra : ruleData->m_areas )
1929 if( ra.
m_ruleName.Contains( wxT(
"Untitled Sheet/" ) ) )
1931 else if( ra.
m_ruleName.Contains( wxT(
"Untitled Sheet1/" ) ) )
1941 auto cgRef = CONNECTION_GRAPH::BuildFromFootprintSet( refArea->
m_components,
1943 auto cgTarget = CONNECTION_GRAPH::BuildFromFootprintSet( targetArea->
m_components,
1947 std::vector<TMATCH::TOPOLOGY_MISMATCH_REASON> details;
1948 bool status = cgRef->FindIsomorphism( cgTarget.get(),
result, details );
1951 BOOST_CHECK( !status );
1956 std::set<wxString> refRefDes;
1957 std::set<wxString> targetRefDes;
1965 bool sawConnectivityReason =
false;
1967 for(
const auto& reason : details )
1970 reason.m_candidate, reason.m_reason ) );
1974 BOOST_CHECK( !reason.m_reason.Contains( wxT(
"No compatible component found" ) ) );
1976 if( reason.m_reason.Contains( wxT(
"connects to" ) )
1977 || reason.m_reason.Contains( wxT(
"connectivity" ) ) )
1979 sawConnectivityReason =
true;
1984 wxString::Format(
"Reason reference '%s' should be a reference-area "
1985 "component", reason.m_reference ) );
1987 wxString::Format(
"Reason candidate '%s' should be a target-area "
1988 "component", reason.m_candidate ) );
1993 "Topology mismatch message should explain the connectivity difference "
1994 "rather than report a generic missing-component error (issue 24192)" );
constexpr EDA_IU_SCALE pcbIUScale
virtual bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
virtual void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Information pertinent to a Pcbnew printed circuit board.
const ZONES & Zones() const
static constexpr BOX2< VECTOR2I > ByCorners(const VECTOR2I &aCorner1, const VECTOR2I &aCorner2)
Store all of the related component information found in a netlist.
void AddItem(EDA_ITEM *aItem)
Add item to group.
void SetName(const wxString &aName)
virtual EDA_GROUP * GetParentGroup() const
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
virtual bool IsVisible() const
virtual void SetText(const wxString &aText)
A logical library item identifier and consists of various portions much like a URI.
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Handle the data for a net.
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
void SetNumber(const wxString &aNumber)
Set the pad number (note that it can be alphanumeric, such as the array reference "AA12").
A set of BOARD_ITEMs (i.e., without duplicates).
void SetEnd(const VECTOR2I &aEnd) override
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetStart(const VECTOR2I &aStart) override
void SetStroke(const STROKE_PARAMS &aStroke) override
virtual void SetPosition(const VECTOR2I &aPos) override
void SetEnd(const VECTOR2I &aEnd)
void SetStart(const VECTOR2I &aStart)
const VECTOR2I & GetStart() const
virtual void SetWidth(int aWidth)
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
virtual VECTOR2I Centre() const
Compute a center-of-mass of the shape.
Simple container to manage line stroke parameters.
Handle a list of polygons defining a copper zone.
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
wxString GetPlacementAreaSource() const
SHAPE_POLY_SET * Outline()
void SetIsRuleArea(bool aEnable)
void SetLayerSet(const LSET &aLayerSet) override
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
PCB_LAYER_ID
A quick note on layer IDs:
SHAPE_LINE_CHAIN BoxToLineChain(const BOX2I &aBox)
void LoadBoard(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< BOARD > &aBoard)
std::map< FOOTPRINT *, FOOTPRINT * > COMPONENT_MATCHES
Class to handle a set of BOARD_ITEMs.
Utility functions for working with shapes.
MULTICHANNEL_TEST_FIXTURE()
SETTINGS_MANAGER m_settingsManager
std::unique_ptr< BOARD > m_board
bool m_includeLockedItems
std::vector< RULE_AREA > m_areas
std::unordered_set< EDA_ITEM * > m_designBlockItems
PLACEMENT_SOURCE_T m_sourceType
std::set< FOOTPRINT * > m_components
std::atomic< bool > * m_cancelled
std::atomic< int > * m_matchedComponents
std::atomic< int > * m_totalComponents
@ VALUE
Field Value of part, i.e. "3.3K".
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
RULE_AREA * findRuleAreaByPartialName(MULTICHANNEL_TOOL *aTool, const wxString &aName)
BOOST_FIXTURE_TEST_CASE(MultichannelToolRegressions, MULTICHANNEL_TEST_FIXTURE)
int countZonesByNameInRuleArea(BOARD *aBoard, const wxString &aZoneName, const RULE_AREA &aRuleArea)
RULE_AREA * findRuleAreaByPlacementGroup(MULTICHANNEL_TOOL *aTool, const wxString &aGroupName)
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))
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
VECTOR2< int32_t > VECTOR2I