51 switch( aItem->
Type() )
119 return !it->second.GetItems().empty();
122 switch( aItem->
Type() )
135 if( alreadyAdded(
pad ) )
152 if( alreadyAdded( aItem ) )
160 if( alreadyAdded( aItem ) )
167 if( alreadyAdded( aItem ) )
174 if( alreadyAdded( aItem ) )
181 if( alreadyAdded( aItem ) )
192 ZONE* zone =
static_cast<ZONE*
>( aItem );
194 if( alreadyAdded( aItem ) )
227 item->RemoveInvalidRefs();
233 std::lock_guard lock(
m_mutex );
235 PROF_TIMER garbage_collection(
"garbage-collection" );
237 std::vector<CN_ITEM*> garbage;
238 garbage.reserve( 1024 );
251 garbage_collection.
Show();
256 std::vector<CN_ITEM*> dirtyItems;
260 return aItem->Dirty();
273 std::vector<std::future<size_t>> returns( dirtyItems.size() );
278 std::vector<std::pair<BOARD_CONNECTED_ITEM*, int>> deferredNetCodes;
279 std::mutex deferredNetCodesMutex;
281 for(
size_t ii = 0; ii < dirtyItems.size(); ++ii )
283 returns[ii] =
tp.submit_task(
284 [&dirtyItems, ii,
this, &deferredNetCodes, &deferredNetCodesMutex] () ->
size_t
289 CN_VISITOR visitor( dirtyItems[ii], &deferredNetCodes, &deferredNetCodesMutex );
290 m_itemList.FindNearby( dirtyItems[ii], visitor );
299 for(
const std::future<size_t>& ret : returns )
302 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
304 while( status != std::future_status::ready )
309 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
314 for(
const auto& [item, netCode] : deferredNetCodes )
315 item->SetNetCode( netCode );
340 std::deque<CN_ITEM*>
Q;
341 std::set<CN_ITEM*> item_set;
348 std::set<CN_ITEM*> visited;
350 auto addToSearchList =
351 [&item_set, withinAnyNet, aSingleNet, &aExcludeZones](
CN_ITEM *aItem )
353 if( withinAnyNet && aItem->Net() <= 0 )
356 if( !aItem->Valid() )
359 if( aSingleNet >=0 && aItem->Net() != aSingleNet )
362 if( aExcludeZones && aItem->Parent()->Type() ==
PCB_ZONE_T )
365 item_set.insert( aItem );
373 while( !item_set.empty() )
375 std::shared_ptr<CN_CLUSTER> cluster = std::make_shared<CN_CLUSTER>();
377 auto it = item_set.begin();
379 while( it != item_set.end() && visited.contains( *it ) )
380 it = item_set.erase( item_set.begin() );
382 if( it == item_set.end() )
386 visited.insert( root );
396 cluster->Add( current );
400 if( withinAnyNet && n->Net() != root->
Net() )
403 if( aExcludeZones && n->Parent()->Type() ==
PCB_ZONE_T )
406 if( !visited.contains( n ) && n->Valid() )
414 clusters.push_back( std::move( cluster ) );
420 std::sort( clusters.begin(), clusters.end(),
421 [](
const std::shared_ptr<CN_CLUSTER>& a,
const std::shared_ptr<CN_CLUSTER>& b )
423 return a->OriginNet() < b->OriginNet();
434 std::vector<CN_ZONE_LAYER*> zitems;
438 if( zone->IsOnCopperLayer() )
451 for(
int j = 0; j < zone->GetFilledPolysList( layer )->OutlineCount(); j++ )
459 int progressDelta = 50;
462 size += zitems.size();
463 size += zitems.size();
464 size += aBoard->
Tracks().size();
468 size += footprint->Pads().size();
472 progressDelta = std::max( progressDelta, (
int) size / 4 );
477 if( aReporter && ( progress % progressDelta ) == 0 )
487 std::vector<std::future<size_t>> returns( zitems.size() );
495 aZoneLayer->BuildRTree();
503 for(
size_t ii = 0; ii < zitems.size(); ++ii )
506 returns[ii] =
tp.submit_task(
507 [cache_zones, ptr] {
return cache_zones( ptr ); } );
510 for(
const std::future<size_t>& ret : returns )
512 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
514 while( status != std::future_status::ready )
519 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
526 int ii = zitems.size();
531 m_itemMap[ zitem->Parent() ].Link( zitem );
543 for(
PAD*
pad : footprint->Pads() )
554 if( shape->IsOnCopperLayer() )
570 const std::vector<BOARD_ITEM*>& aLocalItems )
577 switch( item->Type() )
597 for(
const std::shared_ptr<CN_CLUSTER>& cluster :
m_connClusters )
599 if( cluster->IsConflicting() )
603 wxLogTrace( wxT(
"CN" ), wxT(
"Conflicting pads in cluster %p; skipping propagation" ),
606 else if( cluster->HasValidNet() )
612 for(
CN_ITEM* item : *cluster )
614 if( item->Valid() && item->CanChangeNet()
615 && item->Parent()->GetNetCode() != cluster->OriginNet() )
621 aCommit->
Modify( item->Parent() );
623 item->Parent()->SetNetCode( cluster->OriginNet() );
630 wxLogTrace( wxT(
"CN" ), wxT(
"Cluster %p: net: %d %s" ),
632 cluster->OriginNet(),
633 (
const char*) cluster->OriginNetName().c_str() );
637 wxLogTrace( wxT(
"CN" ), wxT(
"Cluster %p: no changeable items to propagate to" ),
643 wxLogTrace( wxT(
"CN" ), wxT(
"Cluster %p: connected to unused net" ),
659 bool aConnectivityAlreadyRebuilt )
661 int progressDelta = 50;
664 progressDelta = std::max( progressDelta, (
int) aMap.size() / 4 );
666 if( !aConnectivityAlreadyRebuilt )
668 for(
const auto& [ zone, islands ] : aMap )
687 for(
auto& [ zone, zoneIslands ] : aMap )
689 for(
auto& [ layer, layerIslands ] : zoneIslands )
691 if( zone->GetFilledPolysList( layer )->IsEmpty() )
694 bool notInConnectivity =
true;
696 for(
const std::shared_ptr<CN_CLUSTER>& cluster :
m_connClusters )
698 for(
CN_ITEM* item : *cluster )
700 if( item->Parent() == zone && item->GetBoardLayer() == layer )
703 notInConnectivity =
false;
705 if( cluster->IsOrphaned() )
706 layerIslands.m_IsolatedOutlines.push_back( z->
SubpolyIndex() );
708 layerIslands.m_SingleConnectionOutlines.push_back( z->
SubpolyIndex() );
713 if( notInConnectivity )
714 layerIslands.m_IsolatedOutlines.push_back( 0 );
741 for(
int i = lastNet; i < aNet + 1; i++ )
777 if(
pad->ConditionallyFlashed( layer )
784 if(
pad->IsBackdrilledOrPostMachined( layer ) )
791 if(
via->ConditionallyFlashed( layer )
798 if(
via->IsBackdrilledOrPostMachined( layer ) )
836 if( aZoneLayerB->
GetLayer() != layer )
844 for(
int i = 0; i < outlineA.
PointCount(); i++ )
853 aZoneLayerA->
Connect( aZoneLayerB );
854 aZoneLayerB->
Connect( aZoneLayerA );
861 for(
int i = 0; i < outlineB.
PointCount(); i++ )
870 aZoneLayerA->
Connect( aZoneLayerB );
871 aZoneLayerB->
Connect( aZoneLayerA );
886 if( parentA == parentB )
922 commonLayers &= board->GetEnabledLayers();
931 if( !
static_cast<const PAD*
>( parentA )->ConditionallyFlashed( layer ) )
936 if( !
static_cast<const PCB_VIA*
>( parentA )->ConditionallyFlashed( layer ) )
942 if( !
static_cast<const PAD*
>( parentB )->ConditionallyFlashed( layer ) )
947 if( !
static_cast<const PCB_VIA*
>( parentB )->ConditionallyFlashed( layer ) )
954 m_item->Connect( aCandidate );
982 std::map<FOOTPRINT*, std::map<wxString, std::vector<CN_ITEM*>>> padsByFootprint;
986 if( !item->Valid() || item->Parent()->Type() !=
PCB_PAD_T )
989 auto pad =
static_cast<const PAD*
>( item->Parent() );
993 padsByFootprint[fp][
pad->GetNumber() ].emplace_back( item );
996 for(
auto& [footprint, padsMap] : padsByFootprint )
998 if( footprint->GetDuplicatePadNumbersAreJumpers() )
1000 for(
const std::vector<CN_ITEM*>& padsList : padsMap | std::views::values )
1002 for(
size_t i = 0; i < padsList.size(); ++i )
1004 for(
size_t j = 1; j < padsList.size(); ++j )
1006 padsList[i]->Connect( padsList[j] );
1007 padsList[j]->Connect( padsList[i] );
1013 for(
const std::set<wxString>&
group : footprint->JumperPadGroups() )
1015 std::vector<CN_ITEM*> toConnect;
1017 for(
const wxString& padNumber :
group )
1018 std::ranges::copy( padsMap[padNumber], std::back_inserter( toConnect ) );
1020 for(
size_t i = 0; i < toConnect.size(); ++i )
1022 for(
size_t j = 1; j < toConnect.size(); ++j )
1024 toConnect[i]->Connect( toConnect[j] );
1025 toConnect[j]->Connect( toConnect[i] );
@ ZLO_FORCE_NO_ZONE_CONNECTION
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
FOOTPRINT * GetParentFootprint() const
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
virtual bool IsOnCopperLayer() const
Information pertinent to a Pcbnew printed circuit board.
const ZONES & Zones() const
const FOOTPRINTS & Footprints() const
const TRACKS & Tracks() const
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
const DRAWINGS & Drawings() const
constexpr bool Contains(const Vec &aPoint) const
constexpr bool Intersects(const BOX2< Vec > &aRect) const
void FillIsolatedIslandsMap(std::map< ZONE *, std::map< PCB_LAYER_ID, ISOLATED_ISLANDS > > &aMap, bool aConnectivityAlreadyRebuilt)
Fill in the isolated islands map with copper islands that are not connected to a net.
bool Remove(BOARD_ITEM *aItem)
CONNECTIVITY_DATA * m_parentConnectivityData
void add(Container &c, BItem brditem)
PROGRESS_REPORTER * m_progressReporter
std::vector< std::shared_ptr< CN_CLUSTER > > m_connClusters
void propagateConnections(BOARD_COMMIT *aCommit=nullptr)
const CLUSTERS & GetClusters()
void LocalBuild(const std::shared_ptr< CONNECTIVITY_DATA > &aGlobalConnectivity, const std::vector< BOARD_ITEM * > &aLocalItems)
void MarkNetAsDirty(int aNet)
const CLUSTERS SearchClusters(CLUSTER_SEARCH_MODE aMode, bool aExcludeZones, int aSingleNet)
void markItemNetAsDirty(const BOARD_ITEM *aItem)
std::vector< std::shared_ptr< CN_CLUSTER > > m_ratsnestClusters
void PropagateNets(BOARD_COMMIT *aCommit=nullptr)
Propagate nets from pads to other items in clusters.
std::shared_ptr< CONNECTIVITY_DATA > m_globalConnectivityData
std::vector< bool > m_dirtyNets
std::unordered_map< const BOARD_ITEM *, ITEM_MAP_ENTRY > m_itemMap
void SetProgressReporter(PROGRESS_REPORTER *aReporter)
std::vector< std::shared_ptr< CN_CLUSTER > > CLUSTERS
void Build(BOARD *aBoard, PROGRESS_REPORTER *aReporter=nullptr)
bool Add(BOARD_ITEM *aItem)
CN_ITEM represents a BOARD_CONNETED_ITEM in the connectivity system (ie: a pad, track/arc/via,...
virtual int AnchorCount() const
const std::vector< CN_ITEM * > & ConnectedItems() const
virtual const VECTOR2I GetAnchor(int n) const
bool CanChangeNet() const
BOARD_CONNECTED_ITEM * Parent() const
std::vector< std::pair< BOARD_CONNECTED_ITEM *, int > > * m_deferredNetCodes
Deferred net code changes collected during parallel connectivity search.
void checkZoneItemConnection(CN_ZONE_LAYER *aZoneLayer, CN_ITEM *aItem)
CN_ITEM * m_item
The item we are looking for connections to.
void checkZoneZoneConnection(CN_ZONE_LAYER *aZoneLayerA, CN_ZONE_LAYER *aZoneLayerB)
std::mutex * m_deferredNetCodesMutex
bool operator()(CN_ITEM *aCandidate)
bool HasSingleConnection()
const SHAPE_LINE_CHAIN & GetOutline() const
PCB_LAYER_ID GetLayer() const
bool Collide(SHAPE *aRefShape) const
bool ContainsPoint(const VECTOR2I &p) const
bool HasValidOutline() const
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
KICAD_T Type() const
Returns the type of object.
LSET is a set of PCB_LAYER_IDs.
void RunOnLayers(const std::function< void(PCB_LAYER_ID)> &aFunction) const
Execute a function on each layer of the LSET.
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Handle the data for a net.
A small class to help profiling.
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
A progress reporter interface for use in multi-threaded environments.
virtual bool IsCancelled() const =0
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void AdvanceProgress()=0
Increment the progress bar length (inside the current virtual zone).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Check if the boundary of shape (this) lies closer to the point aP than aClearance,...
Handle a list of polygons defining a copper zone.
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
a few functions useful in geometry calculations.
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
@ NEVER_FLASHED
Never flashed for connectivity.
@ ALWAYS_FLASHED
Always flashed for connectivity.
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::priority_thread_pool thread_pool
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_NETINFO_T
class NETINFO_ITEM, a description of a net
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I