pcbnew: Unify connected lists between items/zones

Keep the zoneitems in the same list as the rest of the items.
This commit is contained in:
Seth Hillbrand 2018-07-06 14:55:25 -07:00
parent f87cb64d65
commit 284c39acac
2 changed files with 78 additions and 129 deletions

View File

@ -195,7 +195,7 @@ bool CN_CONNECTIVITY_ALGO::Remove( BOARD_ITEM* aItem )
{
m_itemMap[ static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ].MarkItemsAsInvalid();
m_itemMap.erase ( static_cast<BOARD_CONNECTED_ITEM*>( aItem ) );
m_zoneList.SetDirty( true );
m_itemList.SetDirty( true );
break;
}
@ -205,7 +205,6 @@ bool CN_CONNECTIVITY_ALGO::Remove( BOARD_ITEM* aItem )
// Once we delete an item, it may connect between lists, so mark both as potentially invalid
m_itemList.SetHasInvalid( true );
m_zoneList.SetHasInvalid( true );
return true;
}
@ -292,7 +291,7 @@ bool CN_CONNECTIVITY_ALGO::Add( BOARD_ITEM* aItem )
m_itemMap[zone] = ITEM_MAP_ENTRY();
for( auto zitem : m_zoneList.Add( zone ) )
for( auto zitem : m_itemList.Add( zone ) )
m_itemMap[zone].Link(zitem);
break;
@ -319,7 +318,6 @@ void CN_CONNECTIVITY_ALGO::searchConnections()
garbage.reserve( 1024 );
m_itemList.RemoveInvalidItems( garbage );
m_zoneList.RemoveInvalidItems( garbage );
for( auto item : garbage )
delete item;
@ -332,8 +330,7 @@ void CN_CONNECTIVITY_ALGO::searchConnections()
if( m_progressReporter )
{
m_progressReporter->SetMaxProgress(
m_zoneList.Size() + ( m_itemList.IsDirty() ? m_itemList.Size() : 0 ) );
m_progressReporter->SetMaxProgress( m_itemList.IsDirty() ? m_itemList.Size() : 0 );
}
#ifdef USE_OPENMP
@ -355,7 +352,6 @@ void CN_CONNECTIVITY_ALGO::searchConnections()
{
CN_VISITOR visitor( item, &m_listLock );
m_itemList.FindNearby( item, visitor );
m_zoneList.FindNearby( item, visitor );
}
if( m_progressReporter )
@ -367,30 +363,10 @@ void CN_CONNECTIVITY_ALGO::searchConnections()
search_basic.Show();
#endif
#ifdef USE_OPENMP
#pragma omp parallel for
#endif
for( int i = 0; i < m_zoneList.Size(); i++ )
{
auto item = m_zoneList[i];
auto zoneItem = static_cast<CN_ZONE *>( item );
if( zoneItem->Dirty() )
{
CN_VISITOR visitor( item, &m_listLock );
m_itemList.FindNearby( item, visitor );
m_zoneList.FindNearby( item, visitor );
}
if( m_progressReporter )
m_progressReporter->AdvanceProgress();
}
#ifdef USE_OPENMP
}
#endif
m_zoneList.ClearDirtyFlags();
m_itemList.ClearDirtyFlags();
#ifdef CONNECTIVITY_DEBUG
@ -405,11 +381,13 @@ void CN_CONNECTIVITY_ALGO::searchConnections()
void CN_ITEM::RemoveInvalidRefs()
{
auto lastConn = std::remove_if(m_connected.begin(), m_connected.end(), [] ( CN_ITEM * item) {
return !item->Valid();
} );
m_connected.resize( lastConn - m_connected.begin() );
for( auto it = m_connected.begin(); it != m_connected.end(); )
{
if( !(*it)->Valid() )
it = m_connected.erase( it );
else
++it;
}
}
@ -444,21 +422,25 @@ void CN_LIST::RemoveInvalidItems( std::vector<CN_ITEM*>& aGarbage )
bool CN_CONNECTIVITY_ALGO::isDirty() const
{
return m_itemList.IsDirty() || m_zoneList.IsDirty();
return m_itemList.IsDirty();
}
const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUSTER_SEARCH_MODE aMode )
{
constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_PAD_T, PCB_VIA_T, PCB_ZONE_AREA_T, PCB_MODULE_T, EOT };
return SearchClusters( aMode, types, -1 );
constexpr KICAD_T no_zones[] = { PCB_TRACE_T, PCB_PAD_T, PCB_VIA_T, PCB_MODULE_T, EOT };
if( aMode == CSM_PROPAGATE )
return SearchClusters( aMode, no_zones, -1 );
else
return SearchClusters( aMode, types, -1 );
}
const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUSTER_SEARCH_MODE aMode,
const KICAD_T aTypes[], int aSingleNet )
{
bool includeZones = ( aMode != CSM_PROPAGATE );
bool withinAnyNet = ( aMode != CSM_PROPAGATE );
std::deque<CN_ITEM*> Q;
@ -504,12 +486,6 @@ const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUST
std::for_each( m_itemList.begin(), m_itemList.end(), addToSearchList );
if( includeZones )
{
std::for_each( m_zoneList.begin(), m_zoneList.end(), addToSearchList );
}
while( head )
{
CN_CLUSTER_PTR cluster ( new CN_CLUSTER() );
@ -835,6 +811,12 @@ bool CN_VISITOR::operator()( CN_ITEM* aCandidate )
if( !( parentA->GetLayerSet() & parentB->GetLayerSet() ).any() )
return true;
// If both m_item and aCandidate are marked dirty, they will both be searched
// Since we are reciprocal in our connection, we arbitrarily pick one of the connections
// to conduct the expensive search
if( aCandidate->Dirty() && aCandidate < m_item )
return true;
// We should handle zone-zone connection separately
if ( ( parentA->Type() == PCB_ZONE_AREA_T || parentA->Type() == PCB_ZONE_T ) &&
( parentB->Type() == PCB_ZONE_AREA_T || parentB->Type() == PCB_ZONE_T ) )
@ -968,19 +950,14 @@ void CN_CONNECTIVITY_ALGO::Clear()
m_connClusters.clear();
m_itemMap.clear();
m_itemList.Clear();
m_zoneList.Clear();
}
void CN_CONNECTIVITY_ALGO::ForEachItem( const std::function<void( CN_ITEM& )>& aFunc )
{
for( auto item : m_itemList )
aFunc( *item );
for( auto item : m_zoneList )
aFunc( *item );
}

View File

@ -268,7 +268,7 @@ class CN_ITEM : public INTRUSIVE_LIST<CN_ITEM>
private:
BOARD_CONNECTED_ITEM* m_parent;
using CONNECTED_ITEMS = std::vector<CN_ITEM*>;
using CONNECTED_ITEMS = std::set<CN_ITEM*>;
///> list of items physically connected (touching)
CONNECTED_ITEMS m_connected;
@ -431,33 +431,15 @@ public:
return m_canChangeNet;
}
bool isConnected( CN_ITEM* aItem ) const
{
return ( m_connected.find( aItem ) != m_connected.end() );
}
static void Connect( CN_ITEM* a, CN_ITEM* b )
{
bool foundA = false, foundB = false;
for( auto item : a->m_connected )
{
if( item == b )
{
foundA = true;
break;
}
}
for( auto item : b->m_connected )
{
if( item == a )
{
foundB = true;
break;
}
}
if( !foundA )
a->m_connected.push_back( b );
if( !foundB )
b->m_connected.push_back( a );
a->m_connected.insert( b );
b->m_connected.insert( a );
}
void RemoveInvalidRefs();
@ -470,6 +452,53 @@ public:
typedef std::shared_ptr<CN_ITEM> CN_ITEM_PTR;
class CN_ZONE : public CN_ITEM
{
public:
CN_ZONE( ZONE_CONTAINER* aParent, bool aCanChangeNet, int aSubpolyIndex ) :
CN_ITEM( aParent, aCanChangeNet ),
m_subpolyIndex( aSubpolyIndex )
{
SHAPE_LINE_CHAIN outline = aParent->GetFilledPolysList().COutline( aSubpolyIndex );
outline.SetClosed( true );
outline.Simplify();
m_cachedPoly.reset( new POLY_GRID_PARTITION( outline, 16 ) );
}
int SubpolyIndex() const
{
return m_subpolyIndex;
}
bool ContainsAnchor( const CN_ANCHOR_PTR anchor ) const
{
return ContainsPoint( anchor->Pos() );
}
bool ContainsPoint( const VECTOR2I p ) const
{
auto zone = static_cast<ZONE_CONTAINER*> ( Parent() );
return m_cachedPoly->ContainsPoint( p, zone->GetMinThickness() );
}
const BOX2I& BBox()
{
if( m_dirty )
m_bbox = m_cachedPoly->BBox();
return m_bbox;
}
virtual int AnchorCount() const override;
virtual const VECTOR2I GetAnchor( int n ) const override;
private:
std::vector<VECTOR2I> m_testOutlinePoints;
std::unique_ptr<POLY_GRID_PARTITION> m_cachedPoly;
int m_subpolyIndex;
};
class CN_LIST
{
@ -608,62 +637,6 @@ public:
SetDirty();
return item;
}
};
class CN_ZONE : public CN_ITEM
{
public:
CN_ZONE( ZONE_CONTAINER* aParent, bool aCanChangeNet, int aSubpolyIndex ) :
CN_ITEM( aParent, aCanChangeNet ),
m_subpolyIndex( aSubpolyIndex )
{
SHAPE_LINE_CHAIN outline = aParent->GetFilledPolysList().COutline( aSubpolyIndex );
outline.SetClosed( true );
outline.Simplify();
m_cachedPoly.reset( new POLY_GRID_PARTITION( outline, 16 ) );
}
int SubpolyIndex() const
{
return m_subpolyIndex;
}
bool ContainsAnchor( const CN_ANCHOR_PTR anchor ) const
{
return ContainsPoint( anchor->Pos() );
}
bool ContainsPoint( const VECTOR2I p ) const
{
auto zone = static_cast<ZONE_CONTAINER*> ( Parent() );
return m_cachedPoly->ContainsPoint( p, zone->GetMinThickness() );
}
const BOX2I& BBox()
{
if( m_dirty )
m_bbox = m_cachedPoly->BBox();
return m_bbox;
}
virtual int AnchorCount() const override;
virtual const VECTOR2I GetAnchor( int n ) const override;
private:
std::vector<VECTOR2I> m_testOutlinePoints;
std::unique_ptr<POLY_GRID_PARTITION> m_cachedPoly;
int m_subpolyIndex;
};
class CN_ZONE_LIST : public CN_LIST
{
public:
CN_ZONE_LIST() {}
const std::vector<CN_ITEM*> Add( ZONE_CONTAINER* zone )
{
@ -742,7 +715,6 @@ public:
std::mutex m_listLock;
CN_LIST m_itemList;
CN_ZONE_LIST m_zoneList;
using ITEM_MAP_PAIR = std::pair <const BOARD_CONNECTED_ITEM*, ITEM_MAP_ENTRY>;