Move ratsnest exclusion processing to a post-pass.

Also fixes a few cases where we were unnecessarily rebuilding
connectivity more than once for an operation.
This commit is contained in:
Jeff Young 2022-09-29 17:07:42 +01:00
parent bb63e1a2ff
commit d67437a2aa
25 changed files with 164 additions and 237 deletions

View File

@ -303,7 +303,6 @@ public:
* This must be called after a board change (changes for pads, footprints or a read * This must be called after a board change (changes for pads, footprints or a read
* netlist ). * netlist ).
* *
* @param aDC is the current device context (can be NULL).
* @param aDisplayStatus if true, display the computation results. * @param aDisplayStatus if true, display the computation results.
*/ */
void Compile_Ratsnest( bool aDisplayStatus ); void Compile_Ratsnest( bool aDisplayStatus );

View File

@ -155,6 +155,7 @@ BOARD::~BOARD()
void BOARD::BuildConnectivity( PROGRESS_REPORTER* aReporter ) void BOARD::BuildConnectivity( PROGRESS_REPORTER* aReporter )
{ {
GetConnectivity()->Build( this, aReporter ); GetConnectivity()->Build( this, aReporter );
UpdateRatsnestExclusions();
} }
@ -234,29 +235,43 @@ void BOARD::IncrementTimeStamp()
} }
} }
std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions()
{
std::shared_ptr<CONNECTIVITY_DATA> conn = GetConnectivity();
auto setExcluded = void BOARD::UpdateRatsnestExclusions()
[&conn]( PCB_MARKER* aMarker )
{ {
if( aMarker->GetMarkerType() == MARKER_BASE::MARKER_RATSNEST ) std::set<std::pair<KIID, KIID>> m_ratsnestExclusions;
for( PCB_MARKER* marker : GetBoard()->Markers() )
{ {
const std::shared_ptr<RC_ITEM>& rcItem = aMarker->GetRCItem(); if( marker->GetMarkerType() == MARKER_BASE::MARKER_RATSNEST && marker->IsExcluded() )
conn->AddExclusion( rcItem->GetMainItemID(), rcItem->GetAuxItemID() ); {
const std::shared_ptr<RC_ITEM>& rcItem = marker->GetRCItem();
m_ratsnestExclusions.emplace( rcItem->GetMainItemID(), rcItem->GetAuxItemID() );
m_ratsnestExclusions.emplace( rcItem->GetAuxItemID(), rcItem->GetMainItemID() );
}
} }
aMarker->SetExcluded( true ); GetConnectivity()->RunOnUnconnectedEdges(
}; [&]( CN_EDGE& aEdge )
{
std::pair<KIID, KIID> ids = { aEdge.GetSourceNode()->Parent()->m_Uuid,
aEdge.GetTargetNode()->Parent()->m_Uuid };
aEdge.SetVisible( m_ratsnestExclusions.count( ids ) == 0 );
return true;
} );
}
std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions()
{
for( PCB_MARKER* marker : GetBoard()->Markers() ) for( PCB_MARKER* marker : GetBoard()->Markers() )
{ {
auto i = m_designSettings->m_DrcExclusions.find( marker->Serialize() ); auto i = m_designSettings->m_DrcExclusions.find( marker->Serialize() );
if( i != m_designSettings->m_DrcExclusions.end() ) if( i != m_designSettings->m_DrcExclusions.end() )
{ {
setExcluded( marker ); marker->SetExcluded( true );
m_designSettings->m_DrcExclusions.erase( i ); m_designSettings->m_DrcExclusions.erase( i );
} }
} }
@ -269,7 +284,7 @@ std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions()
if( marker ) if( marker )
{ {
setExcluded( marker ); marker->SetExcluded( true );
newMarkers.push_back( marker ); newMarkers.push_back( marker );
} }
} }
@ -1148,12 +1163,6 @@ unsigned BOARD::GetNodesCount( int aNet ) const
} }
unsigned BOARD::GetUnconnectedNetCount() const
{
return m_connectivity->GetUnconnectedCount();
}
BOX2I BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const BOX2I BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const
{ {
BOX2I bbox; BOX2I bbox;
@ -1221,7 +1230,7 @@ void BOARD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>
int viaCount = 0; int viaCount = 0;
int trackSegmentCount = 0; int trackSegmentCount = 0;
std::set<int> netCodes; std::set<int> netCodes;
int unconnected = GetConnectivity()->GetUnconnectedCount(); int unconnected = GetConnectivity()->GetUnconnectedCount( true );
for( PCB_TRACK* item : m_tracks ) for( PCB_TRACK* item : m_tracks )
{ {

View File

@ -456,6 +456,11 @@ public:
*/ */
std::vector<PCB_MARKER*> ResolveDRCExclusions(); std::vector<PCB_MARKER*> ResolveDRCExclusions();
/**
* Update the visibility flags on the current unconnected ratsnest lines.
*/
void UpdateRatsnestExclusions();
/** /**
* Reset all high light data to the init state * Reset all high light data to the init state
*/ */
@ -724,11 +729,6 @@ public:
*/ */
unsigned GetNodesCount( int aNet = -1 ) const; unsigned GetNodesCount( int aNet = -1 ) const;
/**
* @return the number of unconnected nets in the current ratsnest.
*/
unsigned GetUnconnectedNetCount() const;
/** /**
* Return a reference to a list of all the pads. * Return a reference to a list of all the pads.
* *

View File

@ -34,7 +34,6 @@
#include <tools/pcb_tool_base.h> #include <tools/pcb_tool_base.h>
#include <tools/pcb_actions.h> #include <tools/pcb_actions.h>
#include <connectivity/connectivity_data.h> #include <connectivity/connectivity_data.h>
#include <pcbnew_settings.h>
#include <functional> #include <functional>
using namespace std::placeholders; using namespace std::placeholders;
@ -501,6 +500,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
connectivity->PropagateNets( this, PROPAGATE_MODE::RESOLVE_CONFLICTS ); connectivity->PropagateNets( this, PROPAGATE_MODE::RESOLVE_CONFLICTS );
connectivity->RecalculateRatsnest( this ); connectivity->RecalculateRatsnest( this );
board->UpdateRatsnestExclusions();
connectivity->ClearLocalRatsnest(); connectivity->ClearLocalRatsnest();
} }
@ -596,7 +596,7 @@ void BOARD_COMMIT::Revert()
PICKED_ITEMS_LIST undoList; PICKED_ITEMS_LIST undoList;
KIGFX::VIEW* view = m_toolMgr->GetView(); KIGFX::VIEW* view = m_toolMgr->GetView();
BOARD* board = (BOARD*) m_toolMgr->GetModel(); BOARD* board = (BOARD*) m_toolMgr->GetModel();
auto connectivity = board->GetConnectivity(); std::shared_ptr<CONNECTIVITY_DATA> connectivity = board->GetConnectivity();
std::vector<BOARD_ITEM*> bulkAddedItems; std::vector<BOARD_ITEM*> bulkAddedItems;
std::vector<BOARD_ITEM*> bulkRemovedItems; std::vector<BOARD_ITEM*> bulkRemovedItems;
@ -664,7 +664,10 @@ void BOARD_COMMIT::Revert()
board->OnItemsChanged( itemsChanged ); board->OnItemsChanged( itemsChanged );
if ( !m_isFootprintEditor ) if ( !m_isFootprintEditor )
{
connectivity->RecalculateRatsnest(); connectivity->RecalculateRatsnest();
board->UpdateRatsnestExclusions();
}
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>(); PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
selTool->RebuildSelection(); selTool->RebuildSelection();

View File

@ -178,7 +178,7 @@ void CONNECTIVITY_DATA::updateRatsnest()
[&]( const int a, const int b) [&]( const int a, const int b)
{ {
for( int ii = a; ii < b; ++ii ) for( int ii = a; ii < b; ++ii )
dirty_nets[ii]->Update( m_exclusions ); dirty_nets[ii]->Update();
}).wait(); }).wait();
#ifdef PROFILE #ifdef PROFILE
@ -235,10 +235,8 @@ void CONNECTIVITY_DATA::RecalculateRatsnest( BOARD_COMMIT* aCommit )
} }
if( m_connAlgo->IsNetDirty( net ) ) if( m_connAlgo->IsNetDirty( net ) )
{
addRatsnestCluster( c ); addRatsnestCluster( c );
} }
}
m_connAlgo->ClearDirtyFlags(); m_connAlgo->ClearDirtyFlags();
@ -458,7 +456,7 @@ bool CONNECTIVITY_DATA::IsConnectedOnLayer( const BOARD_CONNECTED_ITEM *aItem, i
} }
unsigned int CONNECTIVITY_DATA::GetUnconnectedCount() const unsigned int CONNECTIVITY_DATA::GetUnconnectedCount( bool aVisibleOnly ) const
{ {
unsigned int unconnected = 0; unsigned int unconnected = 0;
@ -469,7 +467,7 @@ unsigned int CONNECTIVITY_DATA::GetUnconnectedCount() const
for( const CN_EDGE& edge : net->GetEdges() ) for( const CN_EDGE& edge : net->GetEdges() )
{ {
if( edge.IsVisible() ) if( edge.IsVisible() || !aVisibleOnly )
++unconnected; ++unconnected;
} }
} }
@ -546,35 +544,10 @@ CONNECTIVITY_DATA::GetNetItems( int aNetCode, const std::initializer_list<KICAD_
} }
bool CONNECTIVITY_DATA::CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport )
{
RecalculateRatsnest();
for( auto net : m_nets )
{
if( net )
{
for( const auto& edge : net->GetEdges() )
{
CN_DISJOINT_NET_ENTRY ent;
ent.net = edge.GetSourceNode()->Parent()->GetNetCode();
ent.a = edge.GetSourceNode()->Parent();
ent.b = edge.GetTargetNode()->Parent();
ent.anchorA = edge.GetSourceNode()->Pos();
ent.anchorB = edge.GetTargetNode()->Pos();
aReport.push_back( ent );
}
}
}
return aReport.empty();
}
const std::vector<PCB_TRACK*> const std::vector<PCB_TRACK*>
CONNECTIVITY_DATA::GetConnectedTracks( const BOARD_CONNECTED_ITEM* aItem ) const CONNECTIVITY_DATA::GetConnectedTracks( const BOARD_CONNECTED_ITEM* aItem ) const
{ {
auto& entry = m_connAlgo->ItemEntry( aItem ); CN_CONNECTIVITY_ALGO::ITEM_MAP_ENTRY& entry = m_connAlgo->ItemEntry( aItem );
std::set<PCB_TRACK*> tracks; std::set<PCB_TRACK*> tracks;
std::vector<PCB_TRACK*> rv; std::vector<PCB_TRACK*> rv;
@ -662,14 +635,17 @@ unsigned int CONNECTIVITY_DATA::GetPadCount( int aNet ) const
} }
void CONNECTIVITY_DATA::GetUnconnectedEdges( std::vector<CN_EDGE>& aEdges) const void CONNECTIVITY_DATA::RunOnUnconnectedEdges( std::function<bool( CN_EDGE& )> aFunc )
{ {
for( const RN_NET* rnNet : m_nets ) for( RN_NET* rnNet : m_nets )
{ {
if( rnNet ) if( rnNet )
{ {
for( const CN_EDGE& edge : rnNet->GetEdges() ) for( CN_EDGE& edge : rnNet->GetEdges() )
aEdges.push_back( edge ); {
if( !aFunc( edge ) )
return;
}
} }
} }
} }
@ -888,48 +864,6 @@ void CONNECTIVITY_DATA::SetProgressReporter( PROGRESS_REPORTER* aReporter )
} }
void CONNECTIVITY_DATA::AddExclusion( const KIID& aBoardItemId1, const KIID& aBoardItemId2 )
{
m_exclusions.emplace( aBoardItemId1, aBoardItemId2 );
m_exclusions.emplace( aBoardItemId2, aBoardItemId1 );
for( RN_NET* rnNet : m_nets )
{
for( CN_EDGE& edge : rnNet->GetEdges() )
{
if( ( edge.GetSourceNode()->Parent()->m_Uuid == aBoardItemId1
&& edge.GetTargetNode()->Parent()->m_Uuid == aBoardItemId2 )
|| ( edge.GetSourceNode()->Parent()->m_Uuid == aBoardItemId2
&& edge.GetTargetNode()->Parent()->m_Uuid == aBoardItemId1 ) )
{
edge.SetVisible( false );
}
}
}
}
void CONNECTIVITY_DATA::RemoveExclusion( const KIID& aBoardItemId1, const KIID& aBoardItemId2 )
{
m_exclusions.erase( std::pair<KIID, KIID>( aBoardItemId1, aBoardItemId2 ) );
m_exclusions.erase( std::pair<KIID, KIID>( aBoardItemId2, aBoardItemId1 ) );
for( RN_NET* rnNet : m_nets )
{
for( CN_EDGE& edge : rnNet->GetEdges() )
{
if( ( edge.GetSourceNode()->Parent()->m_Uuid == aBoardItemId1
&& edge.GetTargetNode()->Parent()->m_Uuid == aBoardItemId2 )
|| ( edge.GetSourceNode()->Parent()->m_Uuid == aBoardItemId2
&& edge.GetTargetNode()->Parent()->m_Uuid == aBoardItemId1 ) )
{
edge.SetVisible( true );
}
}
}
}
const std::vector<CN_EDGE> CONNECTIVITY_DATA::GetRatsnestForItems( std::vector<BOARD_ITEM*> aItems ) const std::vector<CN_EDGE> CONNECTIVITY_DATA::GetRatsnestForItems( std::vector<BOARD_ITEM*> aItems )
{ {
std::set<int> nets; std::set<int> nets;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2013-2017 CERN * Copyright (C) 2013-2017 CERN
* Copyright (C) 2018-2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors.
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
@ -176,8 +176,6 @@ public:
void PropagateNets( BOARD_COMMIT* aCommit = nullptr, void PropagateNets( BOARD_COMMIT* aCommit = nullptr,
PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS ); PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS );
bool CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport );
/** /**
* Function FindIsolatedCopperIslands() * Function FindIsolatedCopperIslands()
* Searches for copper islands in zone aZone that are not connected to any pad. * Searches for copper islands in zone aZone that are not connected to any pad.
@ -196,10 +194,10 @@ public:
void RecalculateRatsnest( BOARD_COMMIT* aCommit = nullptr ); void RecalculateRatsnest( BOARD_COMMIT* aCommit = nullptr );
/** /**
* Function GetUnconnectedCount() * @param aVisibleOnly include only visbile edges in the count
* Returns the number of remaining edges in the ratsnest. * @return the number of remaining edges in the ratsnest
*/ */
unsigned int GetUnconnectedCount() const; unsigned int GetUnconnectedCount( bool aVisibileOnly ) const;
bool IsConnectedOnLayer( const BOARD_CONNECTED_ITEM* aItem, int aLayer, bool IsConnectedOnLayer( const BOARD_CONNECTED_ITEM* aItem, int aLayer,
const std::initializer_list<KICAD_T>& aTypes = {}, const std::initializer_list<KICAD_T>& aTypes = {},
@ -230,7 +228,7 @@ public:
const std::initializer_list<KICAD_T>& aTypes, const std::initializer_list<KICAD_T>& aTypes,
const int& aMaxError = 0 ) const; const int& aMaxError = 0 ) const;
void GetUnconnectedEdges( std::vector<CN_EDGE>& aEdges ) const; void RunOnUnconnectedEdges( std::function<bool( CN_EDGE& )> aFunc );
bool TestTrackEndpointDangling( PCB_TRACK* aTrack, VECTOR2I* aPos = nullptr ); bool TestTrackEndpointDangling( PCB_TRACK* aTrack, VECTOR2I* aPos = nullptr );
@ -287,9 +285,6 @@ public:
const std::map<int, wxString>& GetNetclassMap() const { return m_netclassMap; } const std::map<int, wxString>& GetNetclassMap() const { return m_netclassMap; }
void AddExclusion( const KIID& aBoardItemId1, const KIID& aBoardItemId2 );
void RemoveExclusion( const KIID& aBoardItemId1, const KIID& aBoardItemId2 );
#ifndef SWIG #ifndef SWIG
const std::vector<CN_EDGE> GetRatsnestForItems( const std::vector<BOARD_ITEM*> aItems ); const std::vector<CN_EDGE> GetRatsnestForItems( const std::vector<BOARD_ITEM*> aItems );
@ -316,9 +311,6 @@ private:
/// Used to suppress ratsnest calculations on dynamic ratsnests /// Used to suppress ratsnest calculations on dynamic ratsnests
bool m_skipRatsnest = false; bool m_skipRatsnest = false;
/// Ratsnest lines that have been excluded in DRC
std::set<std::pair<KIID, KIID>> m_exclusions;
KISPINLOCK m_lock; KISPINLOCK m_lock;
/// Map of netcode -> netclass the net is a member of; used for ratsnest painting /// Map of netcode -> netclass the net is a member of; used for ratsnest painting

View File

@ -473,23 +473,24 @@ void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent )
if( !m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest ) if( !m_frame->GetPcbNewSettings()->m_Display.m_ShowGlobalRatsnest )
m_frame->GetToolManager()->RunAction( PCB_ACTIONS::showRatsnest, true ); m_frame->GetToolManager()->RunAction( PCB_ACTIONS::showRatsnest, true );
std::vector<CN_EDGE> edges;
m_frame->GetBoard()->GetConnectivity()->GetUnconnectedEdges( edges );
if( item->Type() == PCB_ZONE_T ) if( item->Type() == PCB_ZONE_T )
{ {
for( const CN_EDGE& edge : edges ) m_frame->GetBoard()->GetConnectivity()->RunOnUnconnectedEdges(
[&]( CN_EDGE& edge )
{ {
if( edge.GetSourceNode()->Parent() == a && edge.GetTargetNode()->Parent() == b ) if( edge.GetSourceNode()->Parent() == a
&& edge.GetTargetNode()->Parent() == b )
{ {
if( item == a ) if( item == a )
m_frame->FocusOnLocation( edge.GetSourcePos() ); m_frame->FocusOnLocation( edge.GetSourcePos() );
else else
m_frame->FocusOnLocation( edge.GetTargetPos() ); m_frame->FocusOnLocation( edge.GetTargetPos() );
break; return false;
}
} }
return true;
} );
} }
else else
{ {
@ -651,12 +652,14 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
marker->SetExcluded( false ); marker->SetExcluded( false );
if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS ) if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
conn->RemoveExclusion( drcItem->GetMainItemID(), drcItem->GetAuxItemID() ); {
m_frame->GetBoard()->UpdateRatsnestExclusions();
if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
m_frame->GetCanvas()->RedrawRatsnest(); m_frame->GetCanvas()->RedrawRatsnest();
}
else else
{
m_frame->GetCanvas()->GetView()->Update( marker ); m_frame->GetCanvas()->GetView()->Update( marker );
}
// Update view // Update view
static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node ); static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
@ -675,12 +678,14 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
marker->SetExcluded( true ); marker->SetExcluded( true );
if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS ) if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
conn->AddExclusion( drcItem->GetMainItemID(), drcItem->GetAuxItemID() ); {
m_frame->GetBoard()->UpdateRatsnestExclusions();
if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
m_frame->GetCanvas()->RedrawRatsnest(); m_frame->GetCanvas()->RedrawRatsnest();
}
else else
{
m_frame->GetCanvas()->GetView()->Update( marker ); m_frame->GetCanvas()->GetView()->Update( marker );
}
// Update view // Update view
if( m_severities & RPT_SEVERITY_EXCLUSION ) if( m_severities & RPT_SEVERITY_EXCLUSION )

View File

@ -572,14 +572,10 @@ bool PANEL_SETUP_LAYERS::TransferDataFromWindow()
} }
} }
// If some board items are deleted: Rebuild the connectivity, // If some board items are deleted: Rebuild the connectivity, because it is likely some
// because it is likely some tracks and vias were removed // tracks and vias were removed
if( hasRemovedBoardItems ) if( hasRemovedBoardItems )
{
// Rebuild list of nets (full ratsnest rebuild)
m_pcb->BuildConnectivity(); m_pcb->BuildConnectivity();
m_frame->Compile_Ratsnest( true );
}
if( modified ) if( modified )
m_frame->OnModify(); m_frame->OnModify();

View File

@ -82,7 +82,7 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
islandsList.emplace_back( CN_ZONE_ISOLATED_ISLAND_LIST( zone ) ); islandsList.emplace_back( CN_ZONE_ISOLATED_ISLAND_LIST( zone ) );
} }
// Rebuild just in case. This really needs to be reliable. // Rebuild (from scratch, ignoring dirty flags) just in case. This really needs to be reliable.
connectivity->Clear(); connectivity->Clear();
connectivity->Build( board, m_drcEngine->GetProgressReporter() ); connectivity->Build( board, m_drcEngine->GetProgressReporter() );
connectivity->FindIsolatedCopperIslands( islandsList, true ); connectivity->FindIsolatedCopperIslands( islandsList, true );
@ -155,16 +155,14 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
if( !reportPhase( _( "Checking net connections..." ) ) ) if( !reportPhase( _( "Checking net connections..." ) ) )
return false; // DRC cancelled return false; // DRC cancelled
std::vector<CN_EDGE> edges;
connectivity->GetUnconnectedEdges( edges );
ii = 0; ii = 0;
count = edges.size(); count = connectivity->GetUnconnectedCount( false );
for( const CN_EDGE& edge : edges ) connectivity->RunOnUnconnectedEdges(
[&]( CN_EDGE& edge )
{ {
if( m_drcEngine->IsErrorLimitExceeded( DRCE_UNCONNECTED_ITEMS ) ) if( m_drcEngine->IsErrorLimitExceeded( DRCE_UNCONNECTED_ITEMS ) )
break; return false;
if( !reportProgress( ii++, count, progressDelta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; // DRC cancelled return false; // DRC cancelled
@ -172,7 +170,9 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS ); std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS );
drcItem->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() ); drcItem->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() );
reportViolation( drcItem, edge.GetSourceNode()->Pos(), UNDEFINED_LAYER ); reportViolation( drcItem, edge.GetSourceNode()->Pos(), UNDEFINED_LAYER );
}
return true;
} );
reportRuleStatistics(); reportRuleStatistics();

View File

@ -104,7 +104,7 @@ void PCB_EDIT_FRAME::Edit_Zone_Params( ZONE* aZone )
commit.Stage( pickedList ); commit.Stage( pickedList );
commit.Push( _( "Modify zone properties" ), SKIP_CONNECTIVITY ); commit.Push( _( "Modify zone properties" ), SKIP_CONNECTIVITY );
GetBoard()->GetConnectivity()->Build( GetBoard() ); GetBoard()->BuildConnectivity();
pickedList.ClearItemsList(); // s_ItemsListPicker is no longer owner of picked items pickedList.ClearItemsList(); // s_ItemsListPicker is no longer owner of picked items
} }

View File

@ -1038,7 +1038,7 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
if( !m_isDryRun ) if( !m_isDryRun )
{ {
m_board->GetConnectivity()->Build( m_board ); m_board->BuildConnectivity();
testConnectivity( aNetlist, footprintMap ); testConnectivity( aNetlist, footprintMap );
for( NETINFO_ITEM* net : m_board->GetNetInfo() ) for( NETINFO_ITEM* net : m_board->GetNetInfo() )

View File

@ -498,7 +498,7 @@ void PCB_DRAW_PANEL_GAL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
int viaCount = 0; int viaCount = 0;
int trackSegmentCount = 0; int trackSegmentCount = 0;
std::set<int> netCodes; std::set<int> netCodes;
int unconnected = board->GetConnectivity()->GetUnconnectedCount(); int unconnected = board->GetConnectivity()->GetUnconnectedCount( true );
for( PCB_TRACK* item : board->Tracks() ) for( PCB_TRACK* item : board->Tracks() )
{ {

View File

@ -52,7 +52,6 @@
#include <pcb_painter.h> #include <pcb_painter.h>
#include <project/project_file.h> #include <project/project_file.h>
#include <project/project_local_settings.h> #include <project/project_local_settings.h>
#include <project/net_settings.h>
#include <python_scripting.h> #include <python_scripting.h>
#include <settings/common_settings.h> #include <settings/common_settings.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
@ -98,7 +97,6 @@
#include <ratsnest/ratsnest_view_item.h> #include <ratsnest/ratsnest_view_item.h>
#include <widgets/appearance_controls.h> #include <widgets/appearance_controls.h>
#include <widgets/pcb_search_pane.h> #include <widgets/pcb_search_pane.h>
#include <wx/fdrepdlg.h>
#include <widgets/infobar.h> #include <widgets/infobar.h>
#include <widgets/panel_selection_filter.h> #include <widgets/panel_selection_filter.h>
#include <widgets/wx_aui_utils.h> #include <widgets/wx_aui_utils.h>
@ -493,7 +491,7 @@ void PCB_EDIT_FRAME::SetBoard( BOARD* aBoard, bool aBuildConnectivity,
aBoard->SetProject( &Prj() ); aBoard->SetProject( &Prj() );
if( aBuildConnectivity ) if( aBuildConnectivity )
aBoard->GetConnectivity()->Build( aBoard ); aBoard->BuildConnectivity();
// reload the drawing-sheet // reload the drawing-sheet
SetPageSettings( aBoard->GetPageSettings() ); SetPageSettings( aBoard->GetPageSettings() );
@ -949,7 +947,7 @@ void PCB_EDIT_FRAME::ResolveDRCExclusions()
commit.Add( marker ); commit.Add( marker );
} }
commit.Push( wxEmptyString, SKIP_UNDO | SKIP_SET_DIRTY ); commit.Push( wxEmptyString, SKIP_UNDO | SKIP_SET_DIRTY | SKIP_CONNECTIVITY );
for( PCB_MARKER* marker : GetBoard()->Markers() ) for( PCB_MARKER* marker : GetBoard()->Markers() )
{ {
@ -959,6 +957,8 @@ void PCB_EDIT_FRAME::ResolveDRCExclusions()
GetCanvas()->GetView()->Add( marker ); GetCanvas()->GetView()->Add( marker );
} }
} }
GetBoard()->UpdateRatsnestExclusions();
} }
@ -1484,7 +1484,6 @@ void PCB_EDIT_FRAME::UpdateUserInterface()
// Rebuild list of nets (full ratsnest rebuild) // Rebuild list of nets (full ratsnest rebuild)
GetBoard()->BuildConnectivity(); GetBoard()->BuildConnectivity();
Compile_Ratsnest( true );
// Update info shown by the horizontal toolbars // Update info shown by the horizontal toolbars
ReCreateLayerBox(); ReCreateLayerBox();

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2007-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2007-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -23,23 +23,19 @@
*/ */
#include <pcb_edit_frame.h> #include <pcb_edit_frame.h>
#include <macros.h>
#include <board.h>
#include <footprint.h> #include <footprint.h>
#include <pcbnew.h>
#include <ratsnest/ratsnest_data.h> #include <ratsnest/ratsnest_data.h>
/** /**
* Function Compile_Ratsnest * Function Compile_Ratsnest
* Create the entire board ratsnest. * Create the entire board ratsnest.
* Must be called after a board change (changes for * Must be called after a board change (changes for pads, footprints or a read netlist ).
* pads, footprints or a read netlist ).
* @param aDC = the current device context (can be NULL)
* @param aDisplayStatus : if true, display the computation results * @param aDisplayStatus : if true, display the computation results
*/ */
void PCB_BASE_FRAME::Compile_Ratsnest( bool aDisplayStatus ) void PCB_BASE_FRAME::Compile_Ratsnest( bool aDisplayStatus )
{ {
GetBoard()->GetConnectivity()->RecalculateRatsnest(); GetBoard()->GetConnectivity()->RecalculateRatsnest();
GetBoard()->UpdateRatsnestExclusions();
if( aDisplayStatus ) if( aDisplayStatus )
SetMsgPanel( m_pcb ); SetMsgPanel( m_pcb );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2013-2017 CERN * Copyright (C) 2013-2017 CERN
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
* *
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
@ -107,8 +107,7 @@ private:
}; };
void RN_NET::kruskalMST( std::vector<CN_EDGE>& aEdges, void RN_NET::kruskalMST( const std::vector<CN_EDGE> &aEdges )
const std::set< std::pair<KIID, KIID> >& aExclusions )
{ {
disjoint_set dset( m_nodes.size() ); disjoint_set dset( m_nodes.size() );
@ -119,7 +118,7 @@ void RN_NET::kruskalMST( std::vector<CN_EDGE>& aEdges,
for( const std::shared_ptr<CN_ANCHOR>& node : m_nodes ) for( const std::shared_ptr<CN_ANCHOR>& node : m_nodes )
node->SetTag( i++ ); node->SetTag( i++ );
for( CN_EDGE& tmp : aEdges ) for( const CN_EDGE& tmp : aEdges )
{ {
const std::shared_ptr<CN_ANCHOR>& source = tmp.GetSourceNode(); const std::shared_ptr<CN_ANCHOR>& source = tmp.GetSourceNode();
const std::shared_ptr<CN_ANCHOR>& target = tmp.GetTargetNode(); const std::shared_ptr<CN_ANCHOR>& target = tmp.GetTargetNode();
@ -127,15 +126,10 @@ void RN_NET::kruskalMST( std::vector<CN_EDGE>& aEdges,
if( dset.unite( source->GetTag(), target->GetTag() ) ) if( dset.unite( source->GetTag(), target->GetTag() ) )
{ {
if( tmp.GetWeight() > 0 ) if( tmp.GetWeight() > 0 )
{
std::pair<KIID, KIID> ids = { source->Parent()->m_Uuid, target->Parent()->m_Uuid };
tmp.SetVisible( aExclusions.count( ids ) == 0 );
m_rnEdges.push_back( tmp ); m_rnEdges.push_back( tmp );
} }
} }
} }
}
class RN_NET::TRIANGULATOR_STATE class RN_NET::TRIANGULATOR_STATE
@ -271,7 +265,7 @@ RN_NET::RN_NET() : m_dirty( true )
} }
void RN_NET::compute( const std::set< std::pair<KIID, KIID> >& aExclusions ) void RN_NET::compute()
{ {
// Special cases do not need complicated algorithms (actually, it does not work well with // Special cases do not need complicated algorithms (actually, it does not work well with
// the Delaunay triangulator) // the Delaunay triangulator)
@ -286,14 +280,8 @@ void RN_NET::compute( const std::set< std::pair<KIID, KIID> >& aExclusions )
// There can be only one possible connection, but it is missing // There can be only one possible connection, but it is missing
CN_EDGE edge ( *m_nodes.begin(), *last ); CN_EDGE edge ( *m_nodes.begin(), *last );
const std::shared_ptr<CN_ANCHOR>& source = edge.GetSourceNode(); edge.GetSourceNode()->SetTag( 0 );
const std::shared_ptr<CN_ANCHOR>& target = edge.GetTargetNode(); edge.GetTargetNode()->SetTag( 1 );
std::pair<KIID, KIID> ids = { source->Parent()->m_Uuid, target->Parent()->m_Uuid };
source->SetTag( 0 );
target->SetTag( 1 );
edge.SetVisible( aExclusions.count( ids ) == 0 );
m_rnEdges.push_back( edge ); m_rnEdges.push_back( edge );
} }
@ -333,7 +321,7 @@ void RN_NET::compute( const std::set< std::pair<KIID, KIID> >& aExclusions )
#ifdef PROFILE #ifdef PROFILE
PROF_TIMER cnt2( "mst" ); PROF_TIMER cnt2( "mst" );
#endif #endif
kruskalMST( triangEdges, aExclusions ); kruskalMST( triangEdges );
#ifdef PROFILE #ifdef PROFILE
cnt2.Show(); cnt2.Show();
#endif #endif
@ -341,9 +329,9 @@ void RN_NET::compute( const std::set< std::pair<KIID, KIID> >& aExclusions )
void RN_NET::Update( const std::set< std::pair<KIID, KIID> >& aExclusions ) void RN_NET::Update()
{ {
compute( aExclusions ); compute();
m_dirty = false; m_dirty = false;
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2013-2015 CERN * Copyright (C) 2013-2015 CERN
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
* *
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
@ -80,7 +80,7 @@ public:
/** /**
* Recompute ratsnest for a net. * Recompute ratsnest for a net.
*/ */
void Update( const std::set< std::pair<KIID, KIID> >& aExclusions ); void Update();
void Clear(); void Clear();
void AddCluster( std::shared_ptr<CN_CLUSTER> aCluster ); void AddCluster( std::shared_ptr<CN_CLUSTER> aCluster );
@ -94,11 +94,10 @@ public:
protected: protected:
///< Recompute ratsnest from scratch. ///< Recompute ratsnest from scratch.
void compute( const std::set< std::pair<KIID, KIID> >& aExclusions ); void compute();
///< Compute the minimum spanning tree using Kruskal's algorithm ///< Compute the minimum spanning tree using Kruskal's algorithm
void kruskalMST( std::vector<CN_EDGE>& aEdges, void kruskalMST( const std::vector<CN_EDGE> &aEdges );
const std::set< std::pair<KIID, KIID> >& aExclusions );
///< Vector of nodes ///< Vector of nodes
std::multiset<std::shared_ptr<CN_ANCHOR>, CN_PTR_CMP> m_nodes; std::multiset<std::shared_ptr<CN_ANCHOR>, CN_PTR_CMP> m_nodes;

View File

@ -84,7 +84,7 @@ bool PCB_EDIT_FRAME::ImportSpecctraSession( const wxString& fullFileName )
OnModify(); OnModify();
GetBoard()->GetConnectivity()->Clear(); GetBoard()->GetConnectivity()->Clear();
GetBoard()->GetConnectivity()->Build( GetBoard() ); GetBoard()->BuildConnectivity();
if( GetCanvas() ) // Update view: if( GetCanvas() ) // Update view:
{ {

View File

@ -430,7 +430,9 @@ int TEARDROP_MANAGER::RemoveTeardrops( BOARD_COMMIT* aCommitter, bool aCommitAft
(void)filler.Fill( m_board->Zones() ); (void)filler.Fill( m_board->Zones() );
if( aCommitter && aCommitAfterRemove ) if( aCommitter && aCommitAfterRemove )
aCommitter->Push( _( "Remove teardrops" ) ); aCommitter->Push( _( "Remove teardrops" ), SKIP_CONNECTIVITY );
m_board->BuildConnectivity();
} }
return count; return count;

View File

@ -904,9 +904,6 @@ int PCB_CONTROL::Paste( const TOOL_EVENT& aEvent )
} }
placeBoardItems( clipBoard, true, mode == PASTE_MODE::UNIQUE_ANNOTATIONS ); placeBoardItems( clipBoard, true, mode == PASTE_MODE::UNIQUE_ANNOTATIONS );
m_frame->GetBoard()->BuildConnectivity();
m_frame->Compile_Ratsnest( true );
} }
break; break;

View File

@ -94,7 +94,7 @@ void ZONE_FILLER_TOOL::CheckAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aRep
commit.Revert(); commit.Revert();
} }
board()->GetConnectivity()->Build( board() ); board()->BuildConnectivity();
canvas()->Refresh(); canvas()->Refresh();
m_fillInProgress = false; m_fillInProgress = false;
@ -169,7 +169,7 @@ void ZONE_FILLER_TOOL::FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aRepo
commit.Revert(); commit.Revert();
} }
board()->GetConnectivity()->Build( board(), reporter.get() ); board()->BuildConnectivity( reporter.get() );
if( filler.IsDebug() ) if( filler.IsDebug() )
frame->UpdateUserInterface(); frame->UpdateUserInterface();
@ -251,7 +251,7 @@ int ZONE_FILLER_TOOL::ZoneFillDirty( const TOOL_EVENT& aEvent )
else else
commit.Revert(); commit.Revert();
board()->GetConnectivity()->Build( board(), reporter.get() ); board()->BuildConnectivity( reporter.get() );
if( filler.IsDebug() ) if( filler.IsDebug() )
frame->UpdateUserInterface(); frame->UpdateUserInterface();
@ -309,7 +309,7 @@ int ZONE_FILLER_TOOL::ZoneFill( const TOOL_EVENT& aEvent )
commit.Revert(); commit.Revert();
} }
board()->GetConnectivity()->Build( board(), reporter.get() ); board()->BuildConnectivity( reporter.get() );
canvas()->Refresh(); canvas()->Refresh();
m_fillInProgress = false; m_fillInProgress = false;

View File

@ -77,6 +77,16 @@ void ZONE_FILLER::SetProgressReporter( PROGRESS_REPORTER* aReporter )
} }
/**
* Fills the given list of zones.
*
* NB: Invalidates connectivity - it is up to the caller to obtain a lock on the connectivity
* data before calling Fill to prevent access to stale data by other coroutines (for example,
* ratsnest redraw). This will generally be required if a UI-based progress reporter has been
* installed.
*
* Caller is also responsible for re-building connectivity afterwards.
*/
bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aParent ) bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aParent )
{ {
std::lock_guard<KISPINLOCK> lock( m_board->GetConnectivity()->GetLock() ); std::lock_guard<KISPINLOCK> lock( m_board->GetConnectivity()->GetLock() );
@ -87,7 +97,7 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity(); std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
// Rebuild just in case. This really needs to be reliable. // Rebuild (from scratch, ignoring dirty flags) just in case. This really needs to be reliable.
connectivity->Clear(); connectivity->Clear();
connectivity->Build( m_board, m_progressReporter ); connectivity->Build( m_board, m_progressReporter );

View File

@ -46,10 +46,14 @@ public:
PROGRESS_REPORTER* GetProgressReporter() const { return m_progressReporter; } PROGRESS_REPORTER* GetProgressReporter() const { return m_progressReporter; }
/** /**
* Fills the given list of zones. Invalidates connectivity - it is up to the caller to obtain * Fills the given list of zones.
* a lock on the connectivity data before calling Fill to prevent access to stale data by other *
* coroutines (for example, ratsnest redraw). This will generally be required if a UI-based * NB: Invalidates connectivity - it is up to the caller to obtain a lock on the connectivity
* progress reporter has been installed. * data before calling Fill to prevent access to stale data by other coroutines (for example,
* ratsnest redraw). This will generally be required if a UI-based progress reporter has been
* installed.
*
* Caller is also responsible for re-building connectivity afterwards.
*/ */
bool Fill( std::vector<ZONE*>& aZones, bool aCheck = false, wxWindow* aParent = nullptr ); bool Fill( std::vector<ZONE*>& aZones, bool aCheck = false, wxWindow* aParent = nullptr );

View File

@ -118,7 +118,9 @@ void FillZones( BOARD* m_board )
toFill.push_back( zone ); toFill.push_back( zone );
if( filler.Fill( toFill, false, nullptr ) ) if( filler.Fill( toFill, false, nullptr ) )
commit.Push( _( "Fill Zone(s)" ), SKIP_UNDO | SKIP_SET_DIRTY | ZONE_FILL_OP ); commit.Push( _( "Fill Zone(s)" ), SKIP_UNDO | SKIP_SET_DIRTY | ZONE_FILL_OP | SKIP_CONNECTIVITY );
m_board->BuildConnectivity();
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013-2017 CERN * Copyright (C) 2013-2017 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -23,11 +23,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
//#define USE_TOOL_MANAGER
#include <wx/timer.h>
#include <wx/math.h>
#include <wx/log.h>
#include <wx/popupwin.h> #include <wx/popupwin.h>
#include <wx/cmdline.h> #include <wx/cmdline.h>
#include <profile.h> #include <profile.h>
@ -38,7 +34,6 @@
#include <layer_ids.h> #include <layer_ids.h>
#include <gal/graphics_abstraction_layer.h> #include <gal/graphics_abstraction_layer.h>
#include <view/view.h>
#include <class_draw_panel_gal.h> #include <class_draw_panel_gal.h>
#include <pcb_draw_panel_gal.h> #include <pcb_draw_panel_gal.h>
#include <view/wx_view_controls.h> #include <view/wx_view_controls.h>
@ -47,23 +42,18 @@
#include <pad.h> #include <pad.h>
#include <footprint.h> #include <footprint.h>
#include <board.h> #include <board.h>
#include <pcb_track.h> #include <pcb_track.h>
#include <pcb_painter.h>
#include <pcb_edit_frame.h> #include <pcb_edit_frame.h>
#include <connectivity/connectivity_data.h> #include <connectivity/connectivity_data.h>
#include <io_mgr.h> #include <io_mgr.h>
#include <memory> #include <memory>
#include <set>
#include <tool/actions.h> #include <tool/actions.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <tool/tool_dispatcher.h> #include <tool/tool_dispatcher.h>
#include <tools/pcb_tool_base.h> #include <tools/pcb_tool_base.h>
#include <tools/pcb_actions.h>
#include <pcbnew/tools/pcb_selection_tool.h>
#include <plugins/kicad/pcb_plugin.h> #include <plugins/kicad/pcb_plugin.h>
#include "pcb_test_frame.h" #include "pcb_test_frame.h"
@ -78,7 +68,7 @@ void PCB_TEST_FRAME_BASE::SetBoard( std::shared_ptr<BOARD> b )
m_board = b; m_board = b;
PROF_TIMER cntConnectivity( "connectivity-build" ); PROF_TIMER cntConnectivity( "connectivity-build" );
m_board->GetConnectivity()->Build( m_board.get() ); m_board->BuildConnectivity();
cntConnectivity.Stop(); cntConnectivity.Stop();
PROF_TIMER cntView("view-build"); PROF_TIMER cntView("view-build");

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -78,6 +78,7 @@ BOOST_FIXTURE_TEST_CASE( FailedToCleanRegressionTests, TRACK_CLEANER_TEST_FIXTUR
KI_TEST::LoadBoard( m_settingsManager, entry.m_File, m_board ); KI_TEST::LoadBoard( m_settingsManager, entry.m_File, m_board );
KI_TEST::FillZones( m_board.get() ); KI_TEST::FillZones( m_board.get() );
m_board->GetConnectivity()->RecalculateRatsnest(); m_board->GetConnectivity()->RecalculateRatsnest();
m_board->UpdateRatsnestExclusions();
TOOL_MANAGER toolMgr; TOOL_MANAGER toolMgr;
toolMgr.SetEnvironment( m_board.get(), nullptr, nullptr, nullptr, nullptr ); toolMgr.SetEnvironment( m_board.get(), nullptr, nullptr, nullptr, nullptr );
@ -146,6 +147,7 @@ BOOST_FIXTURE_TEST_CASE( TrackCleanerRegressionTests, TRACK_CLEANER_TEST_FIXTURE
KI_TEST::LoadBoard( m_settingsManager, relPath, m_board ); KI_TEST::LoadBoard( m_settingsManager, relPath, m_board );
KI_TEST::FillZones( m_board.get() ); KI_TEST::FillZones( m_board.get() );
m_board->GetConnectivity()->RecalculateRatsnest(); m_board->GetConnectivity()->RecalculateRatsnest();
m_board->UpdateRatsnestExclusions();
TOOL_MANAGER toolMgr; TOOL_MANAGER toolMgr;
toolMgr.SetEnvironment( m_board.get(), nullptr, nullptr, nullptr, nullptr ); toolMgr.SetEnvironment( m_board.get(), nullptr, nullptr, nullptr, nullptr );