51 bool anythingDeleted =
false;
54 switch( aItem->
Type() )
63 anythingDeleted =
true;
81 anythingDeleted =
true;
129 return !it->second.GetItems().empty();
132 switch( aItem->
Type() )
145 if( !
pad->IsOnCopperLayer() )
148 if( alreadyAdded(
pad ) )
168 if( alreadyAdded( aItem ) )
176 if( alreadyAdded( aItem ) )
183 if( alreadyAdded( aItem ) )
190 if( alreadyAdded( aItem ) )
200 if( alreadyAdded( aItem ) )
214 ZONE* zone =
static_cast<ZONE*
>( aItem );
216 if( alreadyAdded( aItem ) )
249 item->RemoveInvalidRefs();
255 std::lock_guard lock(
m_mutex );
257 PROF_TIMER garbage_collection(
"garbage-collection" );
259 std::vector<CN_ITEM*> garbage;
260 garbage.reserve( 1024 );
273 garbage_collection.
Show();
278 std::vector<CN_ITEM*> dirtyItems;
282 return aItem->Dirty();
298 std::vector<std::pair<CN_ITEM*, int>> deferredNetCodes;
299 std::mutex deferredNetCodesMutex;
303 auto returns =
tp.submit_loop(
size_t( 0 ), dirtyItems.size(),
304 [&dirtyItems,
this, &deferredNetCodes, &deferredNetCodesMutex](
const size_t ii )
306 if( m_progressReporter && m_progressReporter->IsCancelled() )
309 CN_VISITOR visitor( dirtyItems[ii], &deferredNetCodes, &deferredNetCodesMutex );
310 m_itemList.FindNearby( dirtyItems[ii], visitor );
312 if( m_progressReporter )
313 m_progressReporter->AdvanceProgress();
317 while( !returns.wait_for( std::chrono::milliseconds( 250 ) ) )
336 std::sort( deferredNetCodes.begin(), deferredNetCodes.end(),
337 [](
const auto& a,
const auto& b ) { return a.first < b.first; } );
339 for(
auto it = deferredNetCodes.begin(); it != deferredNetCodes.end(); )
346 while( groupEnd != deferredNetCodes.end() && groupEnd->first == cnItem )
352 return c->Parent()->Type() != PCB_ZONE_T;
361 bool keepExisting =
false;
362 int bestNet = std::numeric_limits<int>::max();
364 for(
auto entry = it; entry != groupEnd; ++entry )
366 if( entry->second == existingNet )
372 bestNet = std::min( bestNet, entry->second );
411 std::vector<CN_ITEM*> members;
412 std::vector<int> memberOf(
m_itemList.Size(), -1 );
418 std::vector<bool> selected;
423 bool participates = item->Valid()
424 && !( withinAnyNet && item->Net() <= 0 )
425 && !( withinAnyNet && aSingleNet >= 0 && item->Net() != aSingleNet )
426 && !( aExcludeZones && item->Parent()->Type() ==
PCB_ZONE_T );
430 memberOf[item->ListIndex()] =
static_cast<int>( members.size() );
431 members.push_back( item );
432 selected.push_back( aSingleNet < 0 || item->Net() == aSingleNet );
445 for(
size_t ii = 0; ii < members.size(); ++ii )
451 int listIndex = neighbour->ListIndex();
454 if( listIndex < 0 || listIndex >= (
int) memberOf.size() )
457 int index = memberOf[listIndex];
462 if( withinAnyNet && neighbour->Net() != item->
Net() )
465 forest.
Unite( ii,
static_cast<size_t>(
index ) );
474 std::vector<int> clusterOf( members.size(), -1 );
475 std::vector<bool> clusterSelected;
477 for(
size_t ii = 0; ii < members.size(); ++ii )
481 if( clusterOf[root] < 0 )
483 clusterOf[root] =
static_cast<int>( clusters.size() );
484 clusters.push_back( std::make_shared<CN_CLUSTER>() );
485 clusterSelected.push_back(
false );
488 clusters[clusterOf[root]]->Add( members[ii] );
491 clusterSelected[clusterOf[root]] =
true;
495 if( aSingleNet >= 0 )
499 for(
size_t ii = 0; ii < clusters.size(); ++ii )
501 if( clusterSelected[ii] )
502 keep.push_back( std::move( clusters[ii] ) );
505 clusters = std::move( keep );
508 std::sort( clusters.begin(), clusters.end(),
509 [](
const std::shared_ptr<CN_CLUSTER>& a,
const std::shared_ptr<CN_CLUSTER>& b )
511 return a->OriginNet() < b->OriginNet();
526 std::vector<CN_ZONE_LAYER*> zitems;
530 if( zone->IsOnCopperLayer() )
543 for(
int j = 0; j < zone->GetFilledPolysList( layer )->OutlineCount(); j++ )
551 int progressDelta = 50;
554 size += zitems.size();
555 size += zitems.size();
556 size += aBoard->
Tracks().size();
560 size += footprint->Pads().size();
564 progressDelta = std::max( progressDelta, (
int) size / 4 );
569 if( aReporter && ( progress % progressDelta ) == 0 )
579 std::vector<std::future<size_t>> returns( zitems.size() );
587 aZoneLayer->BuildRTree();
595 for(
size_t ii = 0; ii < zitems.size(); ++ii )
598 returns[ii] =
tp.submit_task(
599 [cache_zones, ptr] {
return cache_zones( ptr ); } );
602 for(
const std::future<size_t>& ret : returns )
604 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
606 while( status != std::future_status::ready )
611 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
618 int ii = zitems.size();
623 m_itemMap[ zitem->Parent() ].Link( zitem );
635 for(
PAD*
pad : footprint->Pads() )
646 if( shape->IsOnCopperLayer() )
662 const std::vector<BOARD_ITEM*>& aLocalItems )
669 switch( item->Type() )
689 for(
const std::shared_ptr<CN_CLUSTER>& cluster :
m_connClusters )
691 if( cluster->IsConflicting() )
695 wxLogTrace( wxT(
"CN" ), wxT(
"Conflicting pads in cluster %p; skipping propagation" ),
698 else if( cluster->HasValidNet() )
704 for(
CN_ITEM* item : *cluster )
706 if( item->Valid() && item->CanChangeNet()
707 && item->Parent()->GetNetCode() != cluster->OriginNet() )
713 aCommit->
Modify( item->Parent() );
715 item->Parent()->SetNetCode( cluster->OriginNet() );
722 wxLogTrace( wxT(
"CN" ), wxT(
"Cluster %p: net: %d %s" ),
724 cluster->OriginNet(),
725 (
const char*) cluster->OriginNetName().c_str() );
729 wxLogTrace( wxT(
"CN" ), wxT(
"Cluster %p: no changeable items to propagate to" ),
735 wxLogTrace( wxT(
"CN" ), wxT(
"Cluster %p: connected to unused net" ),
751 bool aConnectivityAlreadyRebuilt )
753 int progressDelta = 50;
756 progressDelta = std::max( progressDelta, (
int) aMap.size() / 4 );
758 if( !aConnectivityAlreadyRebuilt )
760 for(
const auto& [ zone, islands ] : aMap )
781 struct ZONE_CLUSTER_ITEM
787 std::unordered_map<const BOARD_ITEM*, std::map<PCB_LAYER_ID, std::vector<ZONE_CLUSTER_ITEM>>>
790 for(
const auto& [ zone, zoneIslands ] : aMap )
793 for(
const std::shared_ptr<CN_CLUSTER>& cluster :
m_connClusters )
795 const bool orphaned = cluster->IsOrphaned();
797 for(
CN_ITEM* item : *cluster )
799 auto it = zoneItems.find( item->Parent() );
801 if( it != zoneItems.end() )
803 it->second[item->GetBoardLayer()].push_back(
809 for(
auto& [ zone, zoneIslands ] : aMap )
811 const auto& layerItems = zoneItems[zone];
813 for(
auto& [ layer, layerIslands ] : zoneIslands )
815 if( zone->GetFilledPolysList( layer )->IsEmpty() )
818 auto layerIt = layerItems.find( layer );
819 bool notInConnectivity = layerIt == layerItems.end();
821 if( !notInConnectivity )
823 for(
const ZONE_CLUSTER_ITEM& entry : layerIt->second )
825 if( entry.m_orphaned )
826 layerIslands.m_IsolatedOutlines.push_back( entry.m_item->SubpolyIndex() );
827 else if( entry.m_item->HasSingleConnection() )
828 layerIslands.m_SingleConnectionOutlines.push_back( entry.m_item->SubpolyIndex() );
837 layerIslands.m_IsolatedOutlines.push_back( 0 );
864 for(
int i = lastNet; i < aNet + 1; i++ )
900 if(
pad->ConditionallyFlashed( layer )
907 if(
pad->IsBackdrilledOrPostMachined( layer ) )
914 if(
via->ConditionallyFlashed( layer )
921 if(
via->IsBackdrilledOrPostMachined( layer ) )
959 if( aZoneLayerB->
GetLayer() != layer )
967 for(
int i = 0; i < outlineA.
PointCount(); i++ )
976 aZoneLayerA->
Connect( aZoneLayerB );
977 aZoneLayerB->
Connect( aZoneLayerA );
984 for(
int i = 0; i < outlineB.
PointCount(); i++ )
993 aZoneLayerA->
Connect( aZoneLayerB );
994 aZoneLayerB->
Connect( aZoneLayerA );
1009 if( parentA == parentB )
1045 commonLayers &= board->GetEnabledLayers();
1054 if( !
static_cast<const PAD*
>( parentA )->ConditionallyFlashed( layer ) )
1059 if( !
static_cast<const PCB_VIA*
>( parentA )->ConditionallyFlashed( layer ) )
1065 if( !
static_cast<const PAD*
>( parentB )->ConditionallyFlashed( layer ) )
1070 if( !
static_cast<const PCB_VIA*
>( parentB )->ConditionallyFlashed( layer ) )
1077 m_item->Connect( aCandidate );
1105 std::map<FOOTPRINT*, std::map<wxString, std::vector<CN_ITEM*>>> padsByFootprint;
1109 if( !item->Valid() || item->Parent()->Type() !=
PCB_PAD_T )
1112 auto pad =
static_cast<const PAD*
>( item->Parent() );
1116 padsByFootprint[fp][
pad->GetNumber() ].emplace_back( item );
1119 for(
auto& [footprint, padsMap] : padsByFootprint )
1121 if( footprint->GetDuplicatePadNumbersAreJumpers() )
1123 for(
const std::vector<CN_ITEM*>& padsList : padsMap | std::views::values )
1125 for(
size_t i = 0; i < padsList.size(); ++i )
1127 for(
size_t j = 1; j < padsList.size(); ++j )
1129 padsList[i]->Connect( padsList[j] );
1130 padsList[j]->Connect( padsList[i] );
1136 for(
const std::set<wxString>&
group : footprint->JumperPadGroups() )
1138 std::vector<CN_ITEM*> toConnect;
1140 for(
const wxString& padNumber :
group )
1141 std::ranges::copy( padsMap[padNumber], std::back_inserter( toConnect ) );
1143 for(
size_t i = 0; i < toConnect.size(); ++i )
1145 for(
size_t j = 1; j < toConnect.size(); ++j )
1147 toConnect[i]->Connect( toConnect[j] );
1148 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,...
virtual bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
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
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT, DRC_CONSTRAINT_T aUsage=NULL_CONSTRAINT) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
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
Hold bulk mode for a scope.
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::vector< std::pair< CN_ITEM *, int > > * m_deferredNetCodes
Deferred net code changes collected during parallel connectivity search.
std::mutex * m_deferredNetCodesMutex
bool operator()(CN_ITEM *aCandidate)
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.
Lock-free disjoint-set over a dense range of indices.
size_t FindCompress(size_t aX)
Shorten the path from aX to its root so that later queries walk less of it.
bool Unite(size_t aA, size_t aB)
Merge the components that hold aA and aB.
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
void RunOnLayers(const std::function< void(PCB_LAYER_ID)> &aFunction) const
Execute a function on each layer of the LSET.
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