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
* netlist ).
*
* @param aDC is the current device context (can be NULL).
* @param aDisplayStatus if true, display the computation results.
*/
void Compile_Ratsnest( bool aDisplayStatus );

View File

@ -155,6 +155,7 @@ BOARD::~BOARD()
void BOARD::BuildConnectivity( PROGRESS_REPORTER* aReporter )
{
GetConnectivity()->Build( this, aReporter );
UpdateRatsnestExclusions();
}
@ -234,29 +235,43 @@ void BOARD::IncrementTimeStamp()
}
}
void BOARD::UpdateRatsnestExclusions()
{
std::set<std::pair<KIID, KIID>> m_ratsnestExclusions;
for( PCB_MARKER* marker : GetBoard()->Markers() )
{
if( marker->GetMarkerType() == MARKER_BASE::MARKER_RATSNEST && marker->IsExcluded() )
{
const std::shared_ptr<RC_ITEM>& rcItem = marker->GetRCItem();
m_ratsnestExclusions.emplace( rcItem->GetMainItemID(), rcItem->GetAuxItemID() );
m_ratsnestExclusions.emplace( rcItem->GetAuxItemID(), rcItem->GetMainItemID() );
}
}
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()
{
std::shared_ptr<CONNECTIVITY_DATA> conn = GetConnectivity();
auto setExcluded =
[&conn]( PCB_MARKER* aMarker )
{
if( aMarker->GetMarkerType() == MARKER_BASE::MARKER_RATSNEST )
{
const std::shared_ptr<RC_ITEM>& rcItem = aMarker->GetRCItem();
conn->AddExclusion( rcItem->GetMainItemID(), rcItem->GetAuxItemID() );
}
aMarker->SetExcluded( true );
};
for( PCB_MARKER* marker : GetBoard()->Markers() )
{
auto i = m_designSettings->m_DrcExclusions.find( marker->Serialize() );
if( i != m_designSettings->m_DrcExclusions.end() )
{
setExcluded( marker );
marker->SetExcluded( true );
m_designSettings->m_DrcExclusions.erase( i );
}
}
@ -269,7 +284,7 @@ std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions()
if( marker )
{
setExcluded( marker );
marker->SetExcluded( true );
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 bbox;
@ -1221,7 +1230,7 @@ void BOARD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>
int viaCount = 0;
int trackSegmentCount = 0;
std::set<int> netCodes;
int unconnected = GetConnectivity()->GetUnconnectedCount();
int unconnected = GetConnectivity()->GetUnconnectedCount( true );
for( PCB_TRACK* item : m_tracks )
{

View File

@ -456,6 +456,11 @@ public:
*/
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
*/
@ -724,11 +729,6 @@ public:
*/
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.
*

View File

@ -34,7 +34,6 @@
#include <tools/pcb_tool_base.h>
#include <tools/pcb_actions.h>
#include <connectivity/connectivity_data.h>
#include <pcbnew_settings.h>
#include <functional>
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->RecalculateRatsnest( this );
board->UpdateRatsnestExclusions();
connectivity->ClearLocalRatsnest();
}
@ -593,10 +593,10 @@ EDA_ITEM* BOARD_COMMIT::parentObject( EDA_ITEM* aItem ) const
void BOARD_COMMIT::Revert()
{
PICKED_ITEMS_LIST undoList;
KIGFX::VIEW* view = m_toolMgr->GetView();
BOARD* board = (BOARD*) m_toolMgr->GetModel();
auto connectivity = board->GetConnectivity();
PICKED_ITEMS_LIST undoList;
KIGFX::VIEW* view = m_toolMgr->GetView();
BOARD* board = (BOARD*) m_toolMgr->GetModel();
std::shared_ptr<CONNECTIVITY_DATA> connectivity = board->GetConnectivity();
std::vector<BOARD_ITEM*> bulkAddedItems;
std::vector<BOARD_ITEM*> bulkRemovedItems;
@ -664,7 +664,10 @@ void BOARD_COMMIT::Revert()
board->OnItemsChanged( itemsChanged );
if ( !m_isFootprintEditor )
{
connectivity->RecalculateRatsnest();
board->UpdateRatsnestExclusions();
}
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
selTool->RebuildSelection();

View File

@ -178,7 +178,7 @@ void CONNECTIVITY_DATA::updateRatsnest()
[&]( const int a, const int b)
{
for( int ii = a; ii < b; ++ii )
dirty_nets[ii]->Update( m_exclusions );
dirty_nets[ii]->Update();
}).wait();
#ifdef PROFILE
@ -235,9 +235,7 @@ void CONNECTIVITY_DATA::RecalculateRatsnest( BOARD_COMMIT* aCommit )
}
if( m_connAlgo->IsNetDirty( net ) )
{
addRatsnestCluster( c );
}
}
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;
@ -469,7 +467,7 @@ unsigned int CONNECTIVITY_DATA::GetUnconnectedCount() const
for( const CN_EDGE& edge : net->GetEdges() )
{
if( edge.IsVisible() )
if( edge.IsVisible() || !aVisibleOnly )
++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*>
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::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 )
{
for( const CN_EDGE& edge : rnNet->GetEdges() )
aEdges.push_back( edge );
for( CN_EDGE& edge : rnNet->GetEdges() )
{
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 )
{
std::set<int> nets;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application.
*
* 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 Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
@ -176,8 +176,6 @@ public:
void PropagateNets( BOARD_COMMIT* aCommit = nullptr,
PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS );
bool CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport );
/**
* Function FindIsolatedCopperIslands()
* 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 );
/**
* Function GetUnconnectedCount()
* Returns the number of remaining edges in the ratsnest.
* @param aVisibleOnly include only visbile edges in the count
* @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,
const std::initializer_list<KICAD_T>& aTypes = {},
@ -230,7 +228,7 @@ public:
const std::initializer_list<KICAD_T>& aTypes,
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 );
@ -287,9 +285,6 @@ public:
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
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
bool m_skipRatsnest = false;
/// Ratsnest lines that have been excluded in DRC
std::set<std::pair<KIID, KIID>> m_exclusions;
KISPINLOCK m_lock;
/// 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 )
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 )
{
for( const CN_EDGE& edge : edges )
{
if( edge.GetSourceNode()->Parent() == a && edge.GetTargetNode()->Parent() == b )
{
if( item == a )
m_frame->FocusOnLocation( edge.GetSourcePos() );
else
m_frame->FocusOnLocation( edge.GetTargetPos() );
m_frame->GetBoard()->GetConnectivity()->RunOnUnconnectedEdges(
[&]( CN_EDGE& edge )
{
if( edge.GetSourceNode()->Parent() == a
&& edge.GetTargetNode()->Parent() == b )
{
if( item == a )
m_frame->FocusOnLocation( edge.GetSourcePos() );
else
m_frame->FocusOnLocation( edge.GetTargetPos() );
break;
}
}
return false;
}
return true;
} );
}
else
{
@ -651,12 +652,14 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
marker->SetExcluded( false );
if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
conn->RemoveExclusion( drcItem->GetMainItemID(), drcItem->GetAuxItemID() );
if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
{
m_frame->GetBoard()->UpdateRatsnestExclusions();
m_frame->GetCanvas()->RedrawRatsnest();
}
else
{
m_frame->GetCanvas()->GetView()->Update( marker );
}
// Update view
static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
@ -675,12 +678,14 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
marker->SetExcluded( true );
if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
conn->AddExclusion( drcItem->GetMainItemID(), drcItem->GetAuxItemID() );
if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS )
{
m_frame->GetBoard()->UpdateRatsnestExclusions();
m_frame->GetCanvas()->RedrawRatsnest();
}
else
{
m_frame->GetCanvas()->GetView()->Update( marker );
}
// Update view
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,
// because it is likely some tracks and vias were removed
// If some board items are deleted: Rebuild the connectivity, because it is likely some
// tracks and vias were removed
if( hasRemovedBoardItems )
{
// Rebuild list of nets (full ratsnest rebuild)
m_pcb->BuildConnectivity();
m_frame->Compile_Ratsnest( true );
}
if( modified )
m_frame->OnModify();

View File

@ -82,7 +82,7 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
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->Build( board, m_drcEngine->GetProgressReporter() );
connectivity->FindIsolatedCopperIslands( islandsList, true );
@ -155,24 +155,24 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
if( !reportPhase( _( "Checking net connections..." ) ) )
return false; // DRC cancelled
std::vector<CN_EDGE> edges;
connectivity->GetUnconnectedEdges( edges );
ii = 0;
count = edges.size();
count = connectivity->GetUnconnectedCount( false );
for( const CN_EDGE& edge : edges )
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_UNCONNECTED_ITEMS ) )
break;
connectivity->RunOnUnconnectedEdges(
[&]( CN_EDGE& edge )
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_UNCONNECTED_ITEMS ) )
return false;
if( !reportProgress( ii++, count, progressDelta ) )
return false; // DRC cancelled
if( !reportProgress( ii++, count, progressDelta ) )
return false; // DRC cancelled
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS );
drcItem->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() );
reportViolation( drcItem, edge.GetSourceNode()->Pos(), UNDEFINED_LAYER );
}
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS );
drcItem->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() );
reportViolation( drcItem, edge.GetSourceNode()->Pos(), UNDEFINED_LAYER );
return true;
} );
reportRuleStatistics();

View File

@ -104,7 +104,7 @@ void PCB_EDIT_FRAME::Edit_Zone_Params( ZONE* aZone )
commit.Stage( pickedList );
commit.Push( _( "Modify zone properties" ), SKIP_CONNECTIVITY );
GetBoard()->GetConnectivity()->Build( GetBoard() );
GetBoard()->BuildConnectivity();
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 )
{
m_board->GetConnectivity()->Build( m_board );
m_board->BuildConnectivity();
testConnectivity( aNetlist, footprintMap );
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 trackSegmentCount = 0;
std::set<int> netCodes;
int unconnected = board->GetConnectivity()->GetUnconnectedCount();
int unconnected = board->GetConnectivity()->GetUnconnectedCount( true );
for( PCB_TRACK* item : board->Tracks() )
{

View File

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

View File

@ -2,7 +2,7 @@
* 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) 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
* modify it under the terms of the GNU General Public License
@ -23,23 +23,19 @@
*/
#include <pcb_edit_frame.h>
#include <macros.h>
#include <board.h>
#include <footprint.h>
#include <pcbnew.h>
#include <ratsnest/ratsnest_data.h>
/**
* Function Compile_Ratsnest
* Create the entire board ratsnest.
* Must be called after a board change (changes for
* pads, footprints or a read netlist ).
* @param aDC = the current device context (can be NULL)
* Must be called after a board change (changes for pads, footprints or a read netlist ).
* @param aDisplayStatus : if true, display the computation results
*/
void PCB_BASE_FRAME::Compile_Ratsnest( bool aDisplayStatus )
{
GetBoard()->GetConnectivity()->RecalculateRatsnest();
GetBoard()->UpdateRatsnestExclusions();
if( aDisplayStatus )
SetMsgPanel( m_pcb );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application.
*
* 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 Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
@ -107,8 +107,7 @@ private:
};
void RN_NET::kruskalMST( std::vector<CN_EDGE>& aEdges,
const std::set< std::pair<KIID, KIID> >& aExclusions )
void RN_NET::kruskalMST( const std::vector<CN_EDGE> &aEdges )
{
disjoint_set dset( m_nodes.size() );
@ -119,20 +118,15 @@ void RN_NET::kruskalMST( std::vector<CN_EDGE>& aEdges,
for( const std::shared_ptr<CN_ANCHOR>& node : m_nodes )
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>& target = tmp.GetTargetNode();
const std::shared_ptr<CN_ANCHOR>& source = tmp.GetSourceNode();
const std::shared_ptr<CN_ANCHOR>& target = tmp.GetTargetNode();
if( dset.unite( source->GetTag(), target->GetTag() ) )
{
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 );
}
}
}
}
@ -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
// the Delaunay triangulator)
@ -285,15 +279,9 @@ void RN_NET::compute( const std::set< std::pair<KIID, KIID> >& aExclusions )
auto last = ++m_nodes.begin();
// There can be only one possible connection, but it is missing
CN_EDGE edge( *m_nodes.begin(), *last );
const std::shared_ptr<CN_ANCHOR>& source = edge.GetSourceNode();
const std::shared_ptr<CN_ANCHOR>& target = edge.GetTargetNode();
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 );
CN_EDGE edge ( *m_nodes.begin(), *last );
edge.GetSourceNode()->SetTag( 0 );
edge.GetTargetNode()->SetTag( 1 );
m_rnEdges.push_back( edge );
}
@ -333,7 +321,7 @@ void RN_NET::compute( const std::set< std::pair<KIID, KIID> >& aExclusions )
#ifdef PROFILE
PROF_TIMER cnt2( "mst" );
#endif
kruskalMST( triangEdges, aExclusions );
kruskalMST( triangEdges );
#ifdef PROFILE
cnt2.Show();
#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;
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application.
*
* 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>
*
@ -80,7 +80,7 @@ public:
/**
* Recompute ratsnest for a net.
*/
void Update( const std::set< std::pair<KIID, KIID> >& aExclusions );
void Update();
void Clear();
void AddCluster( std::shared_ptr<CN_CLUSTER> aCluster );
@ -94,11 +94,10 @@ public:
protected:
///< 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
void kruskalMST( std::vector<CN_EDGE>& aEdges,
const std::set< std::pair<KIID, KIID> >& aExclusions );
void kruskalMST( const std::vector<CN_EDGE> &aEdges );
///< Vector of 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();
GetBoard()->GetConnectivity()->Clear();
GetBoard()->GetConnectivity()->Build( GetBoard() );
GetBoard()->BuildConnectivity();
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() );
if( aCommitter && aCommitAfterRemove )
aCommitter->Push( _( "Remove teardrops" ) );
aCommitter->Push( _( "Remove teardrops" ), SKIP_CONNECTIVITY );
m_board->BuildConnectivity();
}
return count;

View File

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

View File

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

View File

@ -46,10 +46,14 @@ public:
PROGRESS_REPORTER* GetProgressReporter() const { return m_progressReporter; }
/**
* Fills the given list of zones. 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.
* 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 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 );
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.
*
* 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>
*
* 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
*/
//#define USE_TOOL_MANAGER
#include <wx/timer.h>
#include <wx/math.h>
#include <wx/log.h>
#include <wx/popupwin.h>
#include <wx/cmdline.h>
#include <profile.h>
@ -38,7 +34,6 @@
#include <layer_ids.h>
#include <gal/graphics_abstraction_layer.h>
#include <view/view.h>
#include <class_draw_panel_gal.h>
#include <pcb_draw_panel_gal.h>
#include <view/wx_view_controls.h>
@ -47,23 +42,18 @@
#include <pad.h>
#include <footprint.h>
#include <board.h>
#include <pcb_track.h>
#include <pcb_painter.h>
#include <pcb_edit_frame.h>
#include <connectivity/connectivity_data.h>
#include <io_mgr.h>
#include <memory>
#include <set>
#include <tool/actions.h>
#include <tool/tool_manager.h>
#include <tool/tool_dispatcher.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 "pcb_test_frame.h"
@ -78,7 +68,7 @@ void PCB_TEST_FRAME_BASE::SetBoard( std::shared_ptr<BOARD> b )
m_board = b;
PROF_TIMER cntConnectivity( "connectivity-build" );
m_board->GetConnectivity()->Build( m_board.get() );
m_board->BuildConnectivity();
cntConnectivity.Stop();
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.
*
* 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
* 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::FillZones( m_board.get() );
m_board->GetConnectivity()->RecalculateRatsnest();
m_board->UpdateRatsnestExclusions();
TOOL_MANAGER toolMgr;
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::FillZones( m_board.get() );
m_board->GetConnectivity()->RecalculateRatsnest();
m_board->UpdateRatsnestExclusions();
TOOL_MANAGER toolMgr;
toolMgr.SetEnvironment( m_board.get(), nullptr, nullptr, nullptr, nullptr );