Split anchor vectors by layer

This is a speed commit for large boards.  Tracks and pads cannot connect
to elements that are not on the same layer.  Rather than checking for
this at the last step, this commit splits the anchor vectors by layer,
limiting the initial search space.
This commit is contained in:
Seth Hillbrand 2018-05-10 18:01:38 -07:00
parent 019ada0a92
commit b2d0631370
2 changed files with 66 additions and 18 deletions

View File

@ -473,6 +473,8 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
#ifdef PROFILE
PROF_COUNTER search_cnt( "search-connections" );
PROF_COUNTER search_basic( "search-basic" );
PROF_COUNTER search_pads( "search-pads" );
PROF_COUNTER search_tracks( "search-tracks" );
#endif
if( m_padList.IsDirty() || m_trackList.IsDirty() || m_viaList.IsDirty() )
@ -484,10 +486,13 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
auto pad = static_cast<D_PAD*> ( padItem->Parent() );
auto searchPads = std::bind( checkForConnection, _1, padItem );
m_padList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads );
m_trackList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads );
m_viaList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads );
m_padList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads, pad->GetLayerSet() );
m_trackList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads, pad->GetLayerSet() );
m_viaList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads, pad->GetLayerSet() );
}
#ifdef PROFILE
search_pads.Show();
#endif
for( auto& trackItem : m_trackList )
{
@ -495,9 +500,12 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones )
int dist_max = track->GetWidth() / 2;
auto searchTracks = std::bind( checkForConnection, _1, trackItem, dist_max );
m_trackList.FindNearby( track->GetStart(), dist_max, searchTracks );
m_trackList.FindNearby( track->GetEnd(), dist_max, searchTracks );
m_trackList.FindNearby( track->GetStart(), dist_max, searchTracks, track->GetLayerSet() );
m_trackList.FindNearby( track->GetEnd(), dist_max, searchTracks, track->GetLayerSet() );
}
#ifdef PROFILE
search_tracks.Show();
#endif
for( auto& viaItem : m_viaList )
{
@ -602,6 +610,15 @@ void CN_LIST::RemoveInvalidItems( std::vector<CN_ITEM*>& aGarbage )
} );
m_anchors.resize( lastAnchor - m_anchors.begin() );
for( auto i = 0; i < PCB_LAYER_ID_COUNT; i++ )
{
lastAnchor = std::remove_if(m_layer_anchors[i].begin(), m_layer_anchors[i].end(),
[] ( const CN_ANCHOR_PTR anchor ) {
return !anchor->Valid();
} );
m_layer_anchors[i].resize( lastAnchor - m_layer_anchors[i].begin() );
}
auto lastItem = std::remove_if(m_items.begin(), m_items.end(), [&aGarbage] ( CN_ITEM* item ) {
if( !item->Valid() )

View File

@ -408,13 +408,21 @@ class CN_LIST
private:
bool m_dirty;
std::vector<CN_ANCHOR_PTR> m_anchors;
CN_ANCHORS m_layer_anchors[PCB_LAYER_ID_COUNT];
protected:
std::vector<CN_ITEM*> m_items;
void addAnchor( VECTOR2I pos, CN_ITEM* item )
{
m_anchors.push_back( item->AddAnchor( pos ) );
CN_ANCHOR_PTR new_anchor = item->AddAnchor( pos );
m_anchors.push_back( new_anchor );
for( int i = 0; i < PCB_LAYER_ID_COUNT; i++ )
{
if( ( item->Parent()->GetLayerSet() & LSET( 1, i ) ).any() )
m_layer_anchors[i].push_back( new_anchor );
}
}
private:
@ -425,6 +433,11 @@ private:
{
std::sort( m_anchors.begin(), m_anchors.end() );
for( auto i = 0; i < PCB_LAYER_ID_COUNT; i++ )
{
std::sort( m_layer_anchors[i].begin(), m_layer_anchors[i].end() );
}
m_dirty = false;
}
}
@ -453,10 +466,10 @@ public:
std::vector<CN_ANCHOR_PTR>& Anchors() { return m_anchors; }
template <class T>
void FindNearby( VECTOR2I aPosition, int aDistMax, T aFunc, bool aDirtyOnly = false );
void FindNearby( VECTOR2I aPosition, int aDistMax, T aFunc, LSET aLayers = LSET::AllLayersMask(), bool aDirtyOnly = false );
template <class T>
void FindNearby( BOX2I aBBox, T aFunc, bool aDirtyOnly = false );
void FindNearby( BOX2I aBBox, T aFunc, LSET aLayers = LSET::AllLayersMask(), bool aDirtyOnly = false );
void SetDirty( bool aDirty = true )
{
@ -627,18 +640,27 @@ public:
template <class T>
void CN_LIST::FindNearby( BOX2I aBBox, T aFunc, bool aDirtyOnly )
void CN_LIST::FindNearby( BOX2I aBBox, T aFunc, LSET aLayers, bool aDirtyOnly )
{
sort();
CN_ANCHOR_PTR lower_ptr = std::make_shared<CN_ANCHOR>
( aBBox.GetPosition(), m_anchors[0]->Item() );
CN_ANCHORS *anchor_set = &m_anchors;
PCB_LAYER_ID layer = aLayers.ExtractLayer();
auto lower_it = std::lower_bound( m_anchors.begin(), m_anchors.end(), lower_ptr,
if( layer > 0 )
anchor_set = &(m_layer_anchors[ layer ]);
if( (*anchor_set).size() == 0 )
return;
CN_ANCHOR_PTR lower_ptr = std::make_shared<CN_ANCHOR>
( aBBox.GetPosition(), (*anchor_set)[0]->Item() );
auto lower_it = std::lower_bound( anchor_set->begin(), anchor_set->end(), lower_ptr,
[]( const CN_ANCHOR_PTR& a, const CN_ANCHOR_PTR& b ) -> bool
{ return a->Pos().x < b->Pos().x; } );
for( auto it = lower_it; it != m_anchors.end(); it++)
for( auto it = lower_it; it != anchor_set->end(); it++)
{
if( (*it)->Pos().x > aBBox.GetRight() )
break;
@ -669,7 +691,7 @@ void CN_ZONE_LIST::FindNearbyZones( BOX2I aBBox, T aFunc, bool aDirtyOnly )
template <class T>
void CN_LIST::FindNearby( VECTOR2I aPosition, int aDistMax, T aFunc, bool aDirtyOnly )
void CN_LIST::FindNearby( VECTOR2I aPosition, int aDistMax, T aFunc, LSET aLayers, bool aDirtyOnly )
{
/* Search items in m_Candidates that position is <= aDistMax from aPosition
* (Rectilinear distance)
@ -680,14 +702,23 @@ void CN_LIST::FindNearby( VECTOR2I aPosition, int aDistMax, T aFunc, bool aDirty
sort();
CN_ANCHOR_PTR lower = std::make_shared<CN_ANCHOR>
( aPosition - VECTOR2I( aDistMax + 1, 0 ), m_anchors[0]->Item() );
CN_ANCHORS *anchor_set = &m_anchors;
PCB_LAYER_ID layer = aLayers.ExtractLayer();
auto lower_it = std::lower_bound( m_anchors.begin(), m_anchors.end(), lower,
if( layer > 0 )
anchor_set = &(m_layer_anchors[ layer ]);
if( (*anchor_set).size() == 0 )
return;
CN_ANCHOR_PTR lower = std::make_shared<CN_ANCHOR>
( aPosition - VECTOR2I( aDistMax, 0 ), (*anchor_set)[0]->Item() );
auto lower_it = std::lower_bound( anchor_set->begin(), anchor_set->end(), lower,
[]( const CN_ANCHOR_PTR& a, const CN_ANCHOR_PTR& b ) -> bool
{ return a->Pos().x < b->Pos().x; } );
for( auto it = lower_it; it != m_anchors.end(); it++ )
for( auto it = lower_it; it != anchor_set->end(); it++ )
{
if( (*it)->Pos().x > aDistMax + aPosition.x )
break;