Fix connectivity to only resolve conflicts on netlist load

Fixes https://gitlab.com/kicad/code/kicad/-/issues/8007
This commit is contained in:
Jon Evans 2021-03-23 17:42:56 -04:00
parent a94ce75c02
commit f57dcf2a34
7 changed files with 54 additions and 14 deletions

View File

@ -37,14 +37,16 @@
using namespace std::placeholders;
BOARD_COMMIT::BOARD_COMMIT( PCB_TOOL_BASE* aTool )
BOARD_COMMIT::BOARD_COMMIT( PCB_TOOL_BASE* aTool ) :
m_resolveNetConflicts( false )
{
m_toolMgr = aTool->GetManager();
m_isFootprintEditor = aTool->IsFootprintEditor();
}
BOARD_COMMIT::BOARD_COMMIT( EDA_DRAW_FRAME* aFrame )
BOARD_COMMIT::BOARD_COMMIT( EDA_DRAW_FRAME* aFrame ) :
m_resolveNetConflicts( false )
{
m_toolMgr = aFrame->GetToolManager();
m_isFootprintEditor = aFrame->IsType( FRAME_FOOTPRINT_EDITOR );
@ -350,6 +352,9 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
{
size_t num_changes = m_changes.size();
if( m_resolveNetConflicts )
connectivity->PropagateNets( this, PROPAGATE_MODE::RESOLVE_CONFLICTS );
connectivity->RecalculateRatsnest( this );
connectivity->ClearDynamicRatsnest();
frame->GetCanvas()->RedrawRatsnest();

View File

@ -51,12 +51,23 @@ public:
COMMIT& Stage(
const PICKED_ITEMS_LIST& aItems, UNDO_REDO aModFlag = UNDO_REDO::UNSPECIFIED ) override;
/**
* Sets a flag that will cause Push() to resolve net conflicts on track/via clusters instead
* of the default behavior which is to skip updating track/via clusters that have conflicts.
* This is used in the netlist updater to update any clusters that were changed due to pad nets
* changing, but should not be used for other changes as you typically don't want to change
* track/via nets due to temporary conflicts created by board editing operations.
* @param aResolve is true if this commit should resolve conflicting track/via net assignments
*/
void SetResolveNetConflicts( bool aResolve = true ) { m_resolveNetConflicts = aResolve; }
private:
virtual EDA_ITEM* parentObject( EDA_ITEM* aItem ) const override;
private:
TOOL_MANAGER* m_toolMgr;
bool m_isFootprintEditor;
bool m_resolveNetConflicts;
};
#endif

View File

@ -477,11 +477,19 @@ void CN_CONNECTIVITY_ALGO::Build( const std::vector<BOARD_ITEM*>& aItems )
}
void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit )
void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit, PROPAGATE_MODE aMode )
{
bool skipConflicts = ( aMode == PROPAGATE_MODE::SKIP_CONFLICTS );
wxLogTrace( "CN", "propagateConnections: propagate skip conflicts? %d", skipConflicts );
for( const auto& cluster : m_connClusters )
{
if( cluster->IsOrphaned() )
if( skipConflicts && cluster->IsConflicting() )
{
wxLogTrace( "CN", "Conflicting nets in cluster %p; skipping update", cluster.get() );
}
else if( cluster->IsOrphaned() )
{
wxLogTrace( "CN", "Skipping orphaned cluster %p [net: %s]", cluster.get(),
(const char*) cluster->OriginNetName().c_str() );
@ -531,10 +539,10 @@ void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit )
}
void CN_CONNECTIVITY_ALGO::PropagateNets( BOARD_COMMIT* aCommit )
void CN_CONNECTIVITY_ALGO::PropagateNets( BOARD_COMMIT* aCommit, PROPAGATE_MODE aMode )
{
m_connClusters = SearchClusters( CSM_PROPAGATE );
propagateConnections( aCommit );
propagateConnections( aCommit, aMode );
}

View File

@ -168,7 +168,8 @@ private:
void searchConnections();
void propagateConnections( BOARD_COMMIT* aCommit = nullptr );
void propagateConnections( BOARD_COMMIT* aCommit = nullptr,
PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS );
template <class Container, class BItem>
void add( Container& c, BItem brditem )
@ -239,8 +240,10 @@ public:
/**
* Propagates nets from pads to other items in clusters
* @param aCommit is used to store undo information for items modified by the call
* @param aMode controls how clusters with conflicting nets are resolved
*/
void PropagateNets( BOARD_COMMIT* aCommit = nullptr );
void PropagateNets( BOARD_COMMIT* aCommit = nullptr,
PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS );
void FindIsolatedCopperIslands( ZONE* aZone, PCB_LAYER_ID aLayer, std::vector<int>& aIslands );

View File

@ -339,11 +339,12 @@ void CONNECTIVITY_DATA::HideDynamicRatsnest()
}
void CONNECTIVITY_DATA::PropagateNets()
void CONNECTIVITY_DATA::PropagateNets( BOARD_COMMIT* aCommit, PROPAGATE_MODE aMode )
{
m_connAlgo->PropagateNets();
m_connAlgo->PropagateNets( aCommit, aMode );
}
bool CONNECTIVITY_DATA::IsConnectedOnLayer( const BOARD_CONNECTED_ITEM *aItem, int aLayer,
std::vector<KICAD_T> aTypes ) const
{

View File

@ -82,6 +82,15 @@ struct RN_DYNAMIC_LINE
VECTOR2I a, b;
};
/**
* Controls how nets are propagated through clusters
*/
enum class PROPAGATE_MODE
{
SKIP_CONFLICTS, /// Clusters with conflicting drivers are not updated (default)
RESOLVE_CONFLICTS /// Clusters with conflicting drivers are updated to the most popular net
};
// a wrapper class encompassing the connectivity computation algorithm and the
class CONNECTIVITY_DATA
{
@ -155,10 +164,12 @@ public:
RN_NET* GetRatsnestForNet( int aNet );
/**
* Function PropagateNets()
* Propagates the net codes from the source pads to the tracks/vias.
* @param aCommit is used to save the undo state of items modified by this call
* @param aMode controls how conflicts between pads are resolved
*/
void PropagateNets();
void PropagateNets( BOARD_COMMIT* aCommit = nullptr,
PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS );
bool CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport );
@ -202,10 +213,10 @@ public:
* @param aItem is the reference item to find other connected items.
* @param aAnchor is the position to find connected items on.
* @param aTypes allows one to filter by item types.
* @return
* @return
*/
const std::vector<BOARD_CONNECTED_ITEM*> GetConnectedItemsAtAnchor( const BOARD_CONNECTED_ITEM* aItem,
const VECTOR2I& aAnchor,
const VECTOR2I& aAnchor,
const KICAD_T aTypes[] ) const;
void GetUnconnectedEdges( std::vector<CN_EDGE>& aEdges ) const;

View File

@ -1095,6 +1095,7 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
}
m_board->GetNetInfo().RemoveUnusedNets();
m_commit.SetResolveNetConflicts();
m_commit.Push( _( "Update netlist" ) );
m_board->SynchronizeNetsAndNetClasses();