Performance improvements.

1) Move a bunch of std::map's to std::unordered_map to get constant-time
look-ups
2) Lengthen progress-reporting intervals to spend more time doing work
and less time talking about it
3) Reverse order of SHAPE_LINE_CHAINs in thermal intersection checks to
make (much) better use of bbox caches
4) Don't re-generate bboxes we already have
5) Fix some autos that weren't by reference (and were therefore copying
large datasets)
6) Rename delta progressDelta so it's easier to search for in future
7) Get rid of a few more autos (because I don't like them)
8) Pass large items to lambdas by reference

Fixes https://gitlab.com/kicad/code/kicad/issues/12130
This commit is contained in:
Jeff Young 2022-08-03 10:10:23 +01:00
parent 26cbdcf3fa
commit 96f01d33c8
44 changed files with 352 additions and 236 deletions

View File

@ -87,7 +87,7 @@ void DS_DATA_ITEM::SyncDrawItems( DS_DRAW_ITEM_LIST* aCollector, KIGFX::VIEW* aV
pensize = aCollector ? aCollector->GetDefaultPenSize() : 0; pensize = aCollector ? aCollector->GetDefaultPenSize() : 0;
std::map<size_t, EDA_ITEM_FLAGS> itemFlags; std::map<size_t, EDA_ITEM_FLAGS> itemFlags;
DS_DRAW_ITEM_BASE* item = nullptr; DS_DRAW_ITEM_BASE* item = nullptr;
for( size_t i = 0; i < m_drawItems.size(); ++i ) for( size_t i = 0; i < m_drawItems.size(); ++i )
{ {

View File

@ -989,7 +989,7 @@ void CONNECTION_GRAPH::generateInvisiblePinSubGraphs()
subgraph->AddItem( pin ); subgraph->AddItem( pin );
subgraph->ResolveDrivers(); subgraph->ResolveDrivers();
auto key = std::make_pair( subgraph->GetNetName(), code ); NET_NAME_CODE_CACHE_KEY key = { subgraph->GetNetName(), code };
m_net_code_to_subgraphs_map[ key ].push_back( subgraph ); m_net_code_to_subgraphs_map[ key ].push_back( subgraph );
m_subgraphs.push_back( subgraph ); m_subgraphs.push_back( subgraph );
m_driver_subgraphs.push_back( subgraph ); m_driver_subgraphs.push_back( subgraph );
@ -1609,8 +1609,8 @@ void CONNECTION_GRAPH::buildConnectionGraph()
for( CONNECTION_SUBGRAPH* subgraph : m_driver_subgraphs ) for( CONNECTION_SUBGRAPH* subgraph : m_driver_subgraphs )
{ {
auto key = std::make_pair( subgraph->GetNetName(), NET_NAME_CODE_CACHE_KEY key = { subgraph->GetNetName(),
subgraph->m_driver_connection->NetCode() ); subgraph->m_driver_connection->NetCode() };
m_net_code_to_subgraphs_map[ key ].push_back( subgraph ); m_net_code_to_subgraphs_map[ key ].push_back( subgraph );
m_net_name_to_subgraphs_map[subgraph->m_driver_connection->Name()].push_back( subgraph ); m_net_name_to_subgraphs_map[subgraph->m_driver_connection->Name()].push_back( subgraph );

View File

@ -236,11 +236,33 @@ public:
SCH_ITEM* m_second_driver; SCH_ITEM* m_second_driver;
}; };
/// Associates a net code with the final name of a net struct NET_NAME_CODE_CACHE_KEY
typedef std::pair<wxString, int> NET_NAME_CODE; {
wxString Name;
int Netcode;
bool operator==(const NET_NAME_CODE_CACHE_KEY& other) const
{
return Name == other.Name && Netcode == other.Netcode;
}
};
namespace std
{
template <>
struct hash<NET_NAME_CODE_CACHE_KEY>
{
std::size_t operator()( const NET_NAME_CODE_CACHE_KEY& k ) const
{
const std::size_t prime = 19937;
return hash<wxString>()( k.Name ) ^ ( hash<int>()( k.Netcode ) * prime );
}
};
}
/// Associates a NET_CODE_NAME with all the subgraphs in that net /// Associates a NET_CODE_NAME with all the subgraphs in that net
typedef std::map<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> NET_MAP; typedef std::unordered_map<NET_NAME_CODE_CACHE_KEY, std::vector<CONNECTION_SUBGRAPH*>> NET_MAP;
/** /**
* Calculates the connectivity of a schematic and generates netlists * Calculates the connectivity of a schematic and generates netlists
@ -552,20 +574,20 @@ private:
std::vector<std::pair<SCH_SHEET_PATH, SCH_PIN*>> m_invisible_power_pins; std::vector<std::pair<SCH_SHEET_PATH, SCH_PIN*>> m_invisible_power_pins;
std::unordered_map< wxString, std::shared_ptr<BUS_ALIAS> > m_bus_alias_cache; std::unordered_map<wxString, std::shared_ptr<BUS_ALIAS>> m_bus_alias_cache;
std::map<wxString, int> m_net_name_to_code_map; std::unordered_map<wxString, int> m_net_name_to_code_map;
std::map<wxString, int> m_bus_name_to_code_map; std::unordered_map<wxString, int> m_bus_name_to_code_map;
std::map<wxString, std::vector<const CONNECTION_SUBGRAPH*>> m_global_label_cache; std::unordered_map<wxString, std::vector<const CONNECTION_SUBGRAPH*>> m_global_label_cache;
std::map< std::pair<SCH_SHEET_PATH, wxString>, std::map< std::pair<SCH_SHEET_PATH, wxString>,
std::vector<const CONNECTION_SUBGRAPH*> > m_local_label_cache; std::vector<const CONNECTION_SUBGRAPH*> > m_local_label_cache;
std::unordered_map<wxString, std::vector<CONNECTION_SUBGRAPH*>> m_net_name_to_subgraphs_map; std::unordered_map<wxString, std::vector<CONNECTION_SUBGRAPH*>> m_net_name_to_subgraphs_map;
std::map<SCH_ITEM*, CONNECTION_SUBGRAPH*> m_item_to_subgraph_map; std::unordered_map<SCH_ITEM*, CONNECTION_SUBGRAPH*> m_item_to_subgraph_map;
NET_MAP m_net_code_to_subgraphs_map; NET_MAP m_net_code_to_subgraphs_map;

View File

@ -405,7 +405,7 @@ int ERC_TESTER::TestNoConnectPins()
for( const SCH_SHEET_PATH& sheet : m_schematic->GetSheets() ) for( const SCH_SHEET_PATH& sheet : m_schematic->GetSheets() )
{ {
std::map<VECTOR2I, std::vector<SCH_PIN*>> pinMap; std::unordered_map<VECTOR2I, std::vector<SCH_PIN*>> pinMap;
for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) ) for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
{ {
@ -448,7 +448,7 @@ int ERC_TESTER::TestPinToPin()
int errors = 0; int errors = 0;
for( const std::pair<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets ) for( const std::pair<NET_NAME_CODE_CACHE_KEY, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
{ {
std::vector<SCH_PIN*> pins; std::vector<SCH_PIN*> pins;
std::unordered_map<EDA_ITEM*, SCH_SCREEN*> pinToScreenMap; std::unordered_map<EDA_ITEM*, SCH_SCREEN*> pinToScreenMap;
@ -596,9 +596,9 @@ int ERC_TESTER::TestMultUnitPinConflicts()
std::unordered_map<wxString, std::pair<wxString, SCH_PIN*>> pinToNetMap; std::unordered_map<wxString, std::pair<wxString, SCH_PIN*>> pinToNetMap;
for( const std::pair<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets ) for( const std::pair<NET_NAME_CODE_CACHE_KEY, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
{ {
const wxString& netName = net.first.first; const wxString& netName = net.first.Name;
for( CONNECTION_SUBGRAPH* subgraph : net.second ) for( CONNECTION_SUBGRAPH* subgraph : net.second )
{ {
@ -654,7 +654,7 @@ int ERC_TESTER::TestSimilarLabels()
std::unordered_map<wxString, SCH_LABEL_BASE*> labelMap; std::unordered_map<wxString, SCH_LABEL_BASE*> labelMap;
for( const std::pair<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets ) for( const std::pair<NET_NAME_CODE_CACHE_KEY, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
{ {
for( CONNECTION_SUBGRAPH* subgraph : net.second ) for( CONNECTION_SUBGRAPH* subgraph : net.second )
{ {

View File

@ -118,9 +118,9 @@ bool NETLIST_EXPORTER_CADSTAR::writeListOfNets( FILE* f )
for( const auto& it : m_schematic->ConnectionGraph()->GetNetMap() ) for( const auto& it : m_schematic->ConnectionGraph()->GetNetMap() )
{ {
auto subgraphs = it.second; const std::vector<CONNECTION_SUBGRAPH*>& subgraphs = it.second;
netName.Printf( wxT( "\"%s\"" ), it.first.first ); netName.Printf( wxT( "\"%s\"" ), it.first.Name );
std::vector<std::pair<SCH_PIN*, SCH_SHEET_PATH>> sorted_items; std::vector<std::pair<SCH_PIN*, SCH_SHEET_PATH>> sorted_items;

View File

@ -670,9 +670,9 @@ XNODE* NETLIST_EXPORTER_XML::makeListOfNets( unsigned aCtl )
for( const auto& it : m_schematic->ConnectionGraph()->GetNetMap() ) for( const auto& it : m_schematic->ConnectionGraph()->GetNetMap() )
{ {
wxString net_name = it.first.first; wxString net_name = it.first.Name;
auto subgraphs = it.second; const std::vector<CONNECTION_SUBGRAPH*>& subgraphs = it.second;
NET_RECORD* net_record; NET_RECORD* net_record = nullptr;
if( subgraphs.empty() ) if( subgraphs.empty() )
continue; continue;

View File

@ -484,7 +484,7 @@ protected:
// to store a initial pos of the item or mouse cursor // to store a initial pos of the item or mouse cursor
/// Store pointers to other items that are connected to this one, per sheet. /// Store pointers to other items that are connected to this one, per sheet.
std::map<SCH_SHEET_PATH, SCH_ITEM_SET, SHEET_PATH_CMP> m_connected_items; std::unordered_map<SCH_SHEET_PATH, SCH_ITEM_SET, SHEET_PATH_HASH, SHEET_PATH_CMP> m_connected_items;
/// Store connectivity information, per sheet. /// Store connectivity information, per sheet.
std::unordered_map<SCH_SHEET_PATH, SCH_CONNECTION*> m_connection_map; std::unordered_map<SCH_SHEET_PATH, SCH_CONNECTION*> m_connection_map;

View File

@ -400,6 +400,14 @@ namespace std
}; };
} }
struct SHEET_PATH_HASH
{
const size_t operator()( const SCH_SHEET_PATH& path ) const
{
return path.GetCurrentHash();
}
};
struct SHEET_PATH_CMP struct SHEET_PATH_CMP
{ {
bool operator()( const SCH_SHEET_PATH& lhs, const SCH_SHEET_PATH& rhs ) const bool operator()( const SCH_SHEET_PATH& lhs, const SCH_SHEET_PATH& rhs ) const

View File

@ -241,7 +241,6 @@ std::vector<wxString> SCHEMATIC::GetNetClassAssignmentCandidates()
{ {
std::vector<wxString> names; std::vector<wxString> names;
// Key is a NET_NAME_CODE aka std::pair<name, code>
for( const NET_MAP::value_type& pair: m_connectionGraph->GetNetMap() ) for( const NET_MAP::value_type& pair: m_connectionGraph->GetNetMap() )
{ {
CONNECTION_SUBGRAPH* subgraph = pair.second[0]; CONNECTION_SUBGRAPH* subgraph = pair.second[0];
@ -249,7 +248,7 @@ std::vector<wxString> SCHEMATIC::GetNetClassAssignmentCandidates()
if( !subgraph->m_driver_connection->IsBus() if( !subgraph->m_driver_connection->IsBus()
&& subgraph->GetDriverPriority() >= CONNECTION_SUBGRAPH::PRIORITY::PIN ) && subgraph->GetDriverPriority() >= CONNECTION_SUBGRAPH::PRIORITY::PIN )
{ {
names.emplace_back( pair.first.first ); names.emplace_back( pair.first.Name );
} }
} }

View File

@ -645,7 +645,8 @@ public:
* @return the number of intersections found. * @return the number of intersections found.
*/ */
int Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS& aIp, int Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS& aIp,
bool aExcludeColinearAndTouching = false ) const; bool aExcludeColinearAndTouching = false,
BOX2I* aChainBBox = nullptr ) const;
/** /**
* Compute the walk path length from the beginning of the line chain and the point \a aP * Compute the walk path length from the beginning of the line chain and the point \a aP

View File

@ -1395,9 +1395,9 @@ static inline void addIntersection( SHAPE_LINE_CHAIN::INTERSECTIONS& aIps, int a
int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS& aIp, int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS& aIp,
bool aExcludeColinearAndTouching ) const bool aExcludeColinearAndTouching, BOX2I* aChainBBox ) const
{ {
BOX2I bb_other = aChain.BBox(); BOX2I bb_other = aChainBBox ? *aChainBBox : aChain.BBox();
for( int s1 = 0; s1 < SegmentCount(); s1++ ) for( int s1 = 0; s1 < SegmentCount(); s1++ )
{ {

View File

@ -665,7 +665,7 @@ void BOARD::CacheTriangulation( PROGRESS_REPORTER* aReporter, const std::vector<
returns.emplace_back( tp.submit( cache_zones, zone ) ); returns.emplace_back( tp.submit( cache_zones, zone ) );
// Finalize the triangulation threads // Finalize the triangulation threads
for( auto& retval : returns ) for( const std::future<size_t>& retval : returns )
{ {
std::future_status status; std::future_status status;
@ -674,8 +674,9 @@ void BOARD::CacheTriangulation( PROGRESS_REPORTER* aReporter, const std::vector<
if( aReporter ) if( aReporter )
aReporter->KeepRefreshing(); aReporter->KeepRefreshing();
status = retval.wait_for( std::chrono::milliseconds( 100 ) ); status = retval.wait_for( std::chrono::milliseconds( 250 ) );
} while( status != std::future_status::ready ); }
while( status != std::future_status::ready );
} }
} }

View File

@ -63,6 +63,54 @@ class PROGRESS_REPORTER;
// Forward declare endpoint from class_track.h // Forward declare endpoint from class_track.h
enum ENDPOINT_T : int; enum ENDPOINT_T : int;
struct PTR_PTR_CACHE_KEY
{
BOARD_ITEM* A;
BOARD_ITEM* B;
bool operator==(const PTR_PTR_CACHE_KEY& other) const
{
return A == other.A && B == other.B;
}
};
struct PTR_PTR_LAYER_CACHE_KEY
{
BOARD_ITEM* A;
BOARD_ITEM* B;
PCB_LAYER_ID Layer;
bool operator==(const PTR_PTR_LAYER_CACHE_KEY& other) const
{
return A == other.A && B == other.B && Layer == other.Layer;
}
};
namespace std
{
template <>
struct hash<PTR_PTR_CACHE_KEY>
{
std::size_t operator()( const PTR_PTR_CACHE_KEY& k ) const
{
return hash<void*>()( k.A ) ^ hash<void*>()( k.B );
}
};
template <>
struct hash<PTR_PTR_LAYER_CACHE_KEY>
{
std::size_t operator()( const PTR_PTR_LAYER_CACHE_KEY& k ) const
{
const std::size_t prime = 19937;
return hash<void*>()( k.A ) ^ hash<void*>()( k.B ) ^ ( hash<int>()( k.Layer ) * prime );
}
};
}
/** /**
* The allowed types of layers, same as Specctra DSN spec. * The allowed types of layers, same as Specctra DSN spec.
*/ */
@ -1071,14 +1119,14 @@ public:
}; };
// ------------ Run-time caches ------------- // ------------ Run-time caches -------------
std::mutex m_CachesMutex; std::mutex m_CachesMutex;
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool > m_InsideCourtyardCache; std::unordered_map<PTR_PTR_CACHE_KEY, bool> m_InsideCourtyardCache;
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool > m_InsideFCourtyardCache; std::unordered_map<PTR_PTR_CACHE_KEY, bool> m_InsideFCourtyardCache;
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool > m_InsideBCourtyardCache; std::unordered_map<PTR_PTR_CACHE_KEY, bool> m_InsideBCourtyardCache;
std::map< std::tuple<BOARD_ITEM*, BOARD_ITEM*, PCB_LAYER_ID>, bool > m_InsideAreaCache; std::unordered_map<PTR_PTR_LAYER_CACHE_KEY, bool> m_InsideAreaCache;
std::map< wxString, LSET > m_LayerExpressionCache; std::unordered_map< wxString, LSET > m_LayerExpressionCache;
std::map< ZONE*, std::unique_ptr<DRC_RTREE> > m_CopperZoneRTreeCache; std::unordered_map<ZONE*, std::unique_ptr<DRC_RTREE>> m_CopperZoneRTreeCache;
std::unique_ptr<DRC_RTREE> m_CopperItemRTreeCache; std::unique_ptr<DRC_RTREE> m_CopperItemRTreeCache;
// ------------ DRC caches ------------- // ------------ DRC caches -------------
std::vector<ZONE*> m_DRCZones; std::vector<ZONE*> m_DRCZones;
@ -1148,4 +1196,5 @@ private:
std::vector<BOARD_LISTENER*> m_listeners; std::vector<BOARD_LISTENER*> m_listeners;
}; };
#endif // CLASS_BOARD_H_ #endif // CLASS_BOARD_H_

View File

@ -245,7 +245,7 @@ void CN_CONNECTIVITY_ALGO::searchConnections()
auto conn_lambda = auto conn_lambda =
[&dirtyItems]( size_t aItem, CN_LIST* aItemList, [&dirtyItems]( size_t aItem, CN_LIST* aItemList,
PROGRESS_REPORTER* aReporter) -> size_t PROGRESS_REPORTER* aReporter) -> size_t
{ {
if( aReporter && aReporter->IsCancelled() ) if( aReporter && aReporter->IsCancelled() )
return 0; return 0;
@ -262,17 +262,18 @@ void CN_CONNECTIVITY_ALGO::searchConnections()
for( size_t ii = 0; ii < dirtyItems.size(); ++ii ) for( size_t ii = 0; ii < dirtyItems.size(); ++ii )
returns[ii] = tp.submit( conn_lambda, ii, &m_itemList, m_progressReporter ); returns[ii] = tp.submit( conn_lambda, ii, &m_itemList, m_progressReporter );
for( auto& retval : returns ) for( const std::future<size_t>& retval : returns )
{ {
// Here we balance returns with a 100ms timeout to allow UI updating // Here we balance returns with a 250ms timeout to allow UI updating
std::future_status status; std::future_status status;
do do
{ {
if( m_progressReporter ) if( m_progressReporter )
m_progressReporter->KeepRefreshing(); m_progressReporter->KeepRefreshing();
status = retval.wait_for( std::chrono::milliseconds( 100 ) ); status = retval.wait_for( std::chrono::milliseconds( 250 ) );
} while( status != std::future_status::ready ); }
while( status != std::future_status::ready );
} }
if( m_progressReporter ) if( m_progressReporter )
@ -299,7 +300,8 @@ const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUST
const CN_CONNECTIVITY_ALGO::CLUSTERS const CN_CONNECTIVITY_ALGO::CLUSTERS
CN_CONNECTIVITY_ALGO::SearchClusters( CLUSTER_SEARCH_MODE aMode, const std::initializer_list<KICAD_T>& aTypes, CN_CONNECTIVITY_ALGO::SearchClusters( CLUSTER_SEARCH_MODE aMode,
const std::initializer_list<KICAD_T>& aTypes,
int aSingleNet, CN_ITEM* rootItem ) int aSingleNet, CN_ITEM* rootItem )
{ {
bool withinAnyNet = ( aMode != CSM_PROPAGATE ); bool withinAnyNet = ( aMode != CSM_PROPAGATE );
@ -313,7 +315,7 @@ CN_CONNECTIVITY_ALGO::SearchClusters( CLUSTER_SEARCH_MODE aMode, const std::init
searchConnections(); searchConnections();
auto addToSearchList = auto addToSearchList =
[&item_set, withinAnyNet, aSingleNet, aTypes, rootItem ]( CN_ITEM *aItem ) [&item_set, withinAnyNet, aSingleNet, &aTypes, rootItem ]( CN_ITEM *aItem )
{ {
if( withinAnyNet && aItem->Net() <= 0 ) if( withinAnyNet && aItem->Net() <= 0 )
return; return;
@ -428,7 +430,7 @@ void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
// Setup progress metrics // Setup progress metrics
// //
int delta = 50; // Number of additions between 2 calls to the progress bar int progressDelta = 50;
double size = 0.0; double size = 0.0;
size += zitems.size(); // Once for building RTrees size += zitems.size(); // Once for building RTrees
@ -440,12 +442,12 @@ void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
size *= 1.5; // Our caller gets the other third of the progress bar size *= 1.5; // Our caller gets the other third of the progress bar
delta = std::max( delta, KiROUND( size / 10 ) ); progressDelta = std::max( progressDelta, (int) size / 4 );
auto report = auto report =
[&]( int progress ) [&]( int progress )
{ {
if( aReporter && ( progress % delta ) == 0 ) if( aReporter && ( progress % progressDelta ) == 0 )
{ {
aReporter->SetCurrentProgress( progress / size ); aReporter->SetCurrentProgress( progress / size );
aReporter->KeepRefreshing( false ); aReporter->KeepRefreshing( false );
@ -457,12 +459,13 @@ void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
thread_pool& tp = GetKiCadThreadPool(); thread_pool& tp = GetKiCadThreadPool();
std::vector<std::future<size_t>> returns( zitems.size() ); std::vector<std::future<size_t>> returns( zitems.size() );
auto cache_zones = [aReporter]( CN_ZONE_LAYER* aZone ) -> size_t auto cache_zones =
[aReporter]( CN_ZONE_LAYER* aZoneLayer ) -> size_t
{ {
if( aReporter && aReporter->IsCancelled() ) if( aReporter && aReporter->IsCancelled() )
return 0; return 0;
aZone->BuildRTree(); aZoneLayer->BuildRTree();
if( aReporter ) if( aReporter )
aReporter->AdvanceProgress(); aReporter->AdvanceProgress();
@ -473,7 +476,7 @@ void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
for( size_t ii = 0; ii < zitems.size(); ++ii ) for( size_t ii = 0; ii < zitems.size(); ++ii )
returns[ii] = tp.submit( cache_zones, zitems[ii] ); returns[ii] = tp.submit( cache_zones, zitems[ii] );
for( auto& retval : returns ) for( const std::future<size_t>& retval : returns )
{ {
std::future_status status; std::future_status status;
@ -482,8 +485,9 @@ void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
if( aReporter ) if( aReporter )
aReporter->KeepRefreshing(); aReporter->KeepRefreshing();
status = retval.wait_for( std::chrono::milliseconds( 100 ) ); status = retval.wait_for( std::chrono::milliseconds( 250 ) );
} while( status != std::future_status::ready ); }
while( status != std::future_status::ready );
} }
@ -575,7 +579,7 @@ void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit, PROPAGAT
// normal cluster: just propagate from the pads // normal cluster: just propagate from the pads
int n_changed = 0; int n_changed = 0;
for( auto item : *cluster ) for( CN_ITEM* item : *cluster )
{ {
if( item->CanChangeNet() ) if( item->CanChangeNet() )
{ {
@ -601,8 +605,10 @@ void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit, PROPAGAT
(const char*) cluster->OriginNetName().c_str() ); (const char*) cluster->OriginNetName().c_str() );
} }
else else
{
wxLogTrace( wxT( "CN" ), wxT( "Cluster %p : nothing to propagate" ), wxLogTrace( wxT( "CN" ), wxT( "Cluster %p : nothing to propagate" ),
cluster.get() ); cluster.get() );
}
} }
else else
{ {
@ -651,9 +657,11 @@ void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( ZONE* aZone, PCB_LAYER_ID
void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLATED_ISLAND_LIST>& aZones, void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLATED_ISLAND_LIST>& aZones,
bool aConnectivityAlreadyRebuilt ) bool aConnectivityAlreadyRebuilt )
{ {
int delta = 10; // Number of additions between 2 calls to the progress bar int progressDelta = 50;
int ii = 0; int ii = 0;
progressDelta = std::max( progressDelta, (int) aZones.size() / 4 );
if( !aConnectivityAlreadyRebuilt ) if( !aConnectivityAlreadyRebuilt )
{ {
for( CN_ZONE_ISOLATED_ISLAND_LIST& z : aZones ) for( CN_ZONE_ISOLATED_ISLAND_LIST& z : aZones )
@ -662,7 +670,7 @@ void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLAT
Add( z.m_zone ); Add( z.m_zone );
ii++; ii++;
if( m_progressReporter && ( ii % delta ) == 0 ) if( m_progressReporter && ( ii % progressDelta ) == 0 )
{ {
m_progressReporter->SetCurrentProgress( (double) ii / (double) aZones.size() ); m_progressReporter->SetCurrentProgress( (double) ii / (double) aZones.size() );
m_progressReporter->KeepRefreshing( false ); m_progressReporter->KeepRefreshing( false );

View File

@ -193,7 +193,7 @@ public:
return m_dirtyNets.size(); return m_dirtyNets.size();
} }
void Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter = nullptr ); void Build( BOARD* aZoneLayer, PROGRESS_REPORTER* aReporter = nullptr );
void LocalBuild( const std::vector<BOARD_ITEM*>& aItems ); void LocalBuild( const std::vector<BOARD_ITEM*>& aItems );
void Clear(); void Clear();

View File

@ -92,7 +92,7 @@ bool DRC_CACHE_GENERATOR::Run()
} }
// This is the number of tests between 2 calls to the progress bar // This is the number of tests between 2 calls to the progress bar
size_t delta = 50; size_t progressDelta = 200;
size_t count = 0; size_t count = 0;
size_t ii = 0; size_t ii = 0;
@ -106,7 +106,7 @@ bool DRC_CACHE_GENERATOR::Run()
auto addToCopperTree = auto addToCopperTree =
[&]( BOARD_ITEM* item ) -> bool [&]( BOARD_ITEM* item ) -> bool
{ {
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; return false;
LSET layers = item->GetLayerSet(); LSET layers = item->GetLayerSet();
@ -149,17 +149,17 @@ bool DRC_CACHE_GENERATOR::Run()
// Cache zone bounding boxes, triangulation, copper zone rtrees, and footprint courtyards // Cache zone bounding boxes, triangulation, copper zone rtrees, and footprint courtyards
// before we start. // before we start.
m_drcEngine->SetMaxProgress( allZones.size() );
for( FOOTPRINT* footprint : m_board->Footprints() ) for( FOOTPRINT* footprint : m_board->Footprints() )
footprint->BuildCourtyardCaches(); footprint->BuildCourtyardCaches();
thread_pool& tp = GetKiCadThreadPool(); thread_pool& tp = GetKiCadThreadPool();
std::vector<std::future<size_t>> returns; std::vector<std::future<size_t>> returns;
std::atomic<size_t> done( 1 );
returns.reserve( allZones.size() ); returns.reserve( allZones.size() );
auto cache_zones = [this]( ZONE* aZone ) -> size_t auto cache_zones =
[this, &done]( ZONE* aZone ) -> size_t
{ {
if( m_drcEngine->IsCancelled() ) if( m_drcEngine->IsCancelled() )
return 0; return 0;
@ -179,7 +179,8 @@ bool DRC_CACHE_GENERATOR::Run()
std::unique_lock<std::mutex> cacheLock( m_board->m_CachesMutex ); std::unique_lock<std::mutex> cacheLock( m_board->m_CachesMutex );
m_board->m_CopperZoneRTreeCache[ aZone ] = std::move( rtree ); m_board->m_CopperZoneRTreeCache[ aZone ] = std::move( rtree );
m_drcEngine->AdvanceProgress();
done.fetch_add( 1 );
} }
return 1; return 1;
@ -188,15 +189,16 @@ bool DRC_CACHE_GENERATOR::Run()
for( ZONE* zone : allZones ) for( ZONE* zone : allZones )
returns.emplace_back( tp.submit( cache_zones, zone ) ); returns.emplace_back( tp.submit( cache_zones, zone ) );
for( auto& retval : returns ) for( const std::future<size_t>& retval : returns )
{ {
std::future_status status; std::future_status status;
do do
{ {
m_drcEngine->KeepRefreshing(); m_drcEngine->ReportProgress( static_cast<double>( done ) / allZones.size() );
status = retval.wait_for( std::chrono::milliseconds( 100 ) ); status = retval.wait_for( std::chrono::milliseconds( 250 ) );
} while( status != std::future_status::ready ); }
while( status != std::future_status::ready );
} }
return !m_drcEngine->IsCancelled(); return !m_drcEngine->IsCancelled();

View File

@ -77,7 +77,7 @@ bool DRC_TEST_PROVIDER_ANNULAR_WIDTH::Run()
return true; // continue with other tests return true; // continue with other tests
} }
const int delta = 250; // This is the number of tests between 2 calls to the progress bar const int progressDelta = 500;
if( !m_drcEngine->HasRulesForConstraintType( ANNULAR_WIDTH_CONSTRAINT ) ) if( !m_drcEngine->HasRulesForConstraintType( ANNULAR_WIDTH_CONSTRAINT ) )
{ {
@ -126,7 +126,7 @@ bool DRC_TEST_PROVIDER_ANNULAR_WIDTH::Run()
} }
} }
return 100; return 5;
} }
default: default:
@ -286,7 +286,7 @@ bool DRC_TEST_PROVIDER_ANNULAR_WIDTH::Run()
{ {
ii += calcEffort( item ); ii += calcEffort( item );
if( !reportProgress( ii, total, delta ) ) if( !reportProgress( ii, total, progressDelta ) )
return false; // DRC cancelled return false; // DRC cancelled
if( !checkAnnularWidth( item ) ) if( !checkAnnularWidth( item ) )
@ -299,7 +299,7 @@ bool DRC_TEST_PROVIDER_ANNULAR_WIDTH::Run()
{ {
ii += calcEffort( pad ); ii += calcEffort( pad );
if( !reportProgress( ii, total, delta ) ) if( !reportProgress( ii, total, progressDelta ) )
return false; // DRC cancelled return false; // DRC cancelled
if( !checkAnnularWidth( pad ) ) if( !checkAnnularWidth( pad ) )

View File

@ -736,7 +736,7 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
for( const std::pair<const std::pair<int, PCB_LAYER_ID>, ITEMS_POLY>& netLayer : dataset ) for( const std::pair<const std::pair<int, PCB_LAYER_ID>, ITEMS_POLY>& netLayer : dataset )
total_effort += calc_effort( netLayer.second.items, netLayer.first.second ); total_effort += calc_effort( netLayer.second.items, netLayer.first.second );
total_effort += total_effort * distinctMinWidths.size(); total_effort += std::max( (size_t) 1, total_effort ) * distinctMinWidths.size();
returns.reserve( dataset.size() ); returns.reserve( dataset.size() );
@ -753,8 +753,9 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
do do
{ {
m_drcEngine->ReportProgress( static_cast<double>( done ) / total_effort ); m_drcEngine->ReportProgress( static_cast<double>( done ) / total_effort );
status = retval.wait_for( std::chrono::milliseconds( 100 ) ); status = retval.wait_for( std::chrono::milliseconds( 250 ) );
} while( status != std::future_status::ready ); }
while( status != std::future_status::ready );
} }
returns.clear(); returns.clear();
@ -776,8 +777,9 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
do do
{ {
m_drcEngine->ReportProgress( static_cast<double>( done ) / total_effort ); m_drcEngine->ReportProgress( static_cast<double>( done ) / total_effort );
status = retval.wait_for( std::chrono::milliseconds( 100 ) ); status = retval.wait_for( std::chrono::milliseconds( 250 ) );
} while( status != std::future_status::ready ); }
while( status != std::future_status::ready );
} }
return true; return true;

View File

@ -87,7 +87,7 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
connectivity->Build( board, m_drcEngine->GetProgressReporter() ); connectivity->Build( board, m_drcEngine->GetProgressReporter() );
connectivity->FindIsolatedCopperIslands( islandsList, true ); connectivity->FindIsolatedCopperIslands( islandsList, true );
int delta = 100; // This is the number of tests between 2 calls to the progress bar int progressDelta = 250;
int ii = 0; int ii = 0;
int count = board->Tracks().size() + islandsList.size(); int count = board->Tracks().size() + islandsList.size();
@ -106,7 +106,7 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
else if( track->Type() == PCB_TRACE_T && exceedT ) else if( track->Type() == PCB_TRACE_T && exceedT )
continue; continue;
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; // DRC cancelled return false; // DRC cancelled
// Test for dangling items // Test for dangling items
@ -127,7 +127,7 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
if( m_drcEngine->IsErrorLimitExceeded( DRCE_ISOLATED_COPPER ) ) if( m_drcEngine->IsErrorLimitExceeded( DRCE_ISOLATED_COPPER ) )
break; break;
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; // DRC cancelled return false; // DRC cancelled
for( PCB_LAYER_ID layer : zone.m_zone->GetLayerSet().Seq() ) for( PCB_LAYER_ID layer : zone.m_zone->GetLayerSet().Seq() )
@ -158,7 +158,6 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
std::vector<CN_EDGE> edges; std::vector<CN_EDGE> edges;
connectivity->GetUnconnectedEdges( edges ); connectivity->GetUnconnectedEdges( edges );
delta = 250;
ii = 0; ii = 0;
count = edges.size(); count = edges.size();
@ -167,7 +166,7 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
if( m_drcEngine->IsErrorLimitExceeded( DRCE_UNCONNECTED_ITEMS ) ) if( m_drcEngine->IsErrorLimitExceeded( DRCE_UNCONNECTED_ITEMS ) )
break; break;
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; // DRC cancelled return false; // DRC cancelled
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS ); std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS );

View File

@ -413,16 +413,16 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testItemAgainstZone( BOARD_ITEM* aItem,
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances() void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
{ {
// This is the number of tests between 2 calls to the progress bar // This is the number of tests between 2 calls to the progress bar
const int delta = 100; const int progressDelta = 100;
int ii = 0; int ii = 0;
reportAux( wxT( "Testing %d tracks & vias..." ), m_board->Tracks().size() ); reportAux( wxT( "Testing %d tracks & vias..." ), m_board->Tracks().size() );
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, int> checkedPairs; std::unordered_map<PTR_PTR_CACHE_KEY, int> checkedPairs;
for( PCB_TRACK* track : m_board->Tracks() ) for( PCB_TRACK* track : m_board->Tracks() )
{ {
if( !reportProgress( ii++, m_board->Tracks().size(), delta ) ) if( !reportProgress( ii++, m_board->Tracks().size(), progressDelta ) )
break; break;
for( PCB_LAYER_ID layer : track->GetLayerSet().Seq() ) for( PCB_LAYER_ID layer : track->GetLayerSet().Seq() )
@ -687,17 +687,16 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadAgainstItem( PAD* pad, SHAPE* pa
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadClearances( ) void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadClearances( )
{ {
const int delta = 50; // This is the number of tests between 2 calls to the progress bar const int progressDelta = 100;
size_t count = 0;
size_t count = 0; int ii = 0;
for( FOOTPRINT* footprint : m_board->Footprints() ) for( FOOTPRINT* footprint : m_board->Footprints() )
count += footprint->Pads().size(); count += footprint->Pads().size();
reportAux( wxT( "Testing %d pads..." ), count ); reportAux( wxT( "Testing %d pads..." ), count );
int ii = 0; std::unordered_map<PTR_PTR_CACHE_KEY, int> checkedPairs;
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, int> checkedPairs;
for( FOOTPRINT* footprint : m_board->Footprints() ) for( FOOTPRINT* footprint : m_board->Footprints() )
{ {
@ -745,7 +744,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadClearances( )
} }
} }
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return; return;
} }
@ -757,7 +756,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadClearances( )
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones() void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
{ {
const int delta = 50; // This is the number of tests between 2 calls to the progress bar const int progressDelta = 50;
SHAPE_POLY_SET buffer; SHAPE_POLY_SET buffer;
SHAPE_POLY_SET* boardOutline = nullptr; SHAPE_POLY_SET* boardOutline = nullptr;
@ -790,7 +789,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
for( size_t ia = 0; ia < m_board->m_DRCCopperZones.size(); ia++ ) for( size_t ia = 0; ia < m_board->m_DRCCopperZones.size(); ia++ )
{ {
if( !reportProgress( layer_id * m_board->m_DRCCopperZones.size() + ia, if( !reportProgress( layer_id * m_board->m_DRCCopperZones.size() + ia,
B_Cu * m_board->m_DRCCopperZones.size(), delta ) ) B_Cu * m_board->m_DRCCopperZones.size(), progressDelta ) )
{ {
return; // DRC cancelled return; // DRC cancelled
} }

View File

@ -78,8 +78,6 @@ private:
bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions() bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
{ {
const int delta = 100; // This is the number of tests between 2 calls to the progress bar
// Detects missing (or malformed) footprint courtyards // Detects missing (or malformed) footprint courtyards
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_MALFORMED_COURTYARD) if( !m_drcEngine->IsErrorLimitExceeded( DRCE_MALFORMED_COURTYARD)
|| !m_drcEngine->IsErrorLimitExceeded( DRCE_MISSING_COURTYARD) ) || !m_drcEngine->IsErrorLimitExceeded( DRCE_MISSING_COURTYARD) )
@ -98,11 +96,12 @@ bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
return true; // continue with other tests return true; // continue with other tests
} }
int ii = 0; const int progressDelta = 500;
int ii = 0;
for( FOOTPRINT* footprint : m_board->Footprints() ) for( FOOTPRINT* footprint : m_board->Footprints() )
{ {
if( !reportProgress( ii++, m_board->Footprints().size(), delta ) ) if( !reportProgress( ii++, m_board->Footprints().size(), progressDelta ) )
return false; // DRC cancelled return false; // DRC cancelled
if( ( footprint->GetFlags() & MALFORMED_COURTYARDS ) != 0 ) if( ( footprint->GetFlags() & MALFORMED_COURTYARDS ) != 0 )
@ -148,16 +147,15 @@ bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances() bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances()
{ {
const int delta = 100; // This is the number of tests between 2 calls to the progress bar
if( !reportPhase( _( "Checking footprints for overlapping courtyards..." ) ) ) if( !reportPhase( _( "Checking footprints for overlapping courtyards..." ) ) )
return false; // DRC cancelled return false; // DRC cancelled
int ii = 0; const int progressDelta = 100;
int ii = 0;
for( auto itA = m_board->Footprints().begin(); itA != m_board->Footprints().end(); itA++ ) for( auto itA = m_board->Footprints().begin(); itA != m_board->Footprints().end(); itA++ )
{ {
if( !reportProgress( ii++, m_board->Footprints().size(), delta ) ) if( !reportProgress( ii++, m_board->Footprints().size(), progressDelta ) )
return false; // DRC cancelled return false; // DRC cancelled
if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_FOOTPRINTS) if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_FOOTPRINTS)

View File

@ -150,9 +150,7 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
if( m_drcEngine->IsCancelled() ) if( m_drcEngine->IsCancelled() )
return 0; return 0;
std::tuple<BOARD_ITEM*, BOARD_ITEM*, PCB_LAYER_ID> key( ruleArea, PTR_PTR_LAYER_CACHE_KEY key = { ruleArea, copperZone, UNDEFINED_LAYER };
copperZone,
UNDEFINED_LAYER );
{ {
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex ); std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
@ -179,8 +177,9 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
do do
{ {
m_drcEngine->ReportProgress( static_cast<double>( done ) / toCache.size() ); m_drcEngine->ReportProgress( static_cast<double>( done ) / toCache.size() );
status = retval.wait_for( std::chrono::milliseconds( 100 ) ); status = retval.wait_for( std::chrono::milliseconds( 250 ) );
} while( status != std::future_status::ready ); }
while( status != std::future_status::ready );
} }
if( m_drcEngine->IsCancelled() ) if( m_drcEngine->IsCancelled() )
@ -189,8 +188,8 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
// Now go through all the board objects calling the DRC_ENGINE to run the actual disallow // Now go through all the board objects calling the DRC_ENGINE to run the actual disallow
// tests. These should be reasonably quick using the caches generated above. // tests. These should be reasonably quick using the caches generated above.
// //
int delta = 100; const int progressDelta = 250;
int ii = static_cast<int>( toCache.size() ); int ii = static_cast<int>( toCache.size() );
auto checkTextOnEdgeCuts = auto checkTextOnEdgeCuts =
[&]( BOARD_ITEM* item ) [&]( BOARD_ITEM* item )
@ -258,7 +257,7 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
} }
} }
if( !reportProgress( ii++, totalCount, delta ) ) if( !reportProgress( ii++, totalCount, progressDelta ) )
return false; return false;
return true; return true;

View File

@ -246,8 +246,7 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
} }
} }
// This is the number of tests between 2 calls to the progress bar const int progressDelta = 200;
const int delta = 100;
int count = 0; int count = 0;
int ii = 0; int ii = 0;
@ -267,7 +266,7 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
if( !testCopper && !testSilk ) if( !testCopper && !testSilk )
return false; // We're done return false; // We're done
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; // DRC cancelled; we're done return false; // DRC cancelled; we're done
if( isInvisibleText( item ) ) if( isInvisibleText( item ) )

View File

@ -120,8 +120,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
if( !reportPhase( _( "Checking hole to hole clearances..." ) ) ) if( !reportPhase( _( "Checking hole to hole clearances..." ) ) )
return false; // DRC cancelled return false; // DRC cancelled
// This is the number of tests between 2 calls to the progress bar const size_t progressDelta = 200;
const size_t delta = 100;
size_t count = 0; size_t count = 0;
size_t ii = 0; size_t ii = 0;
@ -139,7 +138,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
forEachGeometryItem( { PCB_PAD_T, PCB_VIA_T }, LSET::AllLayersMask(), forEachGeometryItem( { PCB_PAD_T, PCB_VIA_T }, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool [&]( BOARD_ITEM* item ) -> bool
{ {
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; return false;
if( item->Type() == PCB_PAD_T ) if( item->Type() == PCB_PAD_T )
@ -162,7 +161,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
return true; return true;
} ); } );
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, int> checkedPairs; std::unordered_map<PTR_PTR_CACHE_KEY, int> checkedPairs;
for( PCB_TRACK* track : m_board->Tracks() ) for( PCB_TRACK* track : m_board->Tracks() )
{ {
@ -171,7 +170,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
PCB_VIA* via = static_cast<PCB_VIA*>( track ); PCB_VIA* via = static_cast<PCB_VIA*>( track );
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; // DRC cancelled return false; // DRC cancelled
// We only care about mechanically drilled (ie: non-laser) holes // We only care about mechanically drilled (ie: non-laser) holes
@ -216,7 +215,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
{ {
for( PAD* pad : footprint->Pads() ) for( PAD* pad : footprint->Pads() )
{ {
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; // DRC cancelled return false; // DRC cancelled
// We only care about drilled (ie: round) holes // We only care about drilled (ie: round) holes

View File

@ -456,7 +456,7 @@ bool DRC_TEST_PROVIDER_LIBRARY_PARITY::Run()
FP_LIB_TABLE* libTable = project->PcbFootprintLibs(); FP_LIB_TABLE* libTable = project->PcbFootprintLibs();
wxString msg; wxString msg;
int ii = 0; int ii = 0;
const int delta = 50; // Number of tests between calls to progress bar const int progressDelta = 250;
if( !reportPhase( _( "Checking board footprints against library..." ) ) ) if( !reportPhase( _( "Checking board footprints against library..." ) ) )
return false; return false;
@ -469,7 +469,7 @@ bool DRC_TEST_PROVIDER_LIBRARY_PARITY::Run()
return true; // Continue with other tests return true; // Continue with other tests
} }
if( !reportProgress( ii++, board->Footprints().size(), delta ) ) if( !reportProgress( ii++, board->Footprints().size(), progressDelta ) )
return false; // DRC cancelled return false; // DRC cancelled
LIB_ID fpID = footprint->GetFPID(); LIB_ID fpID = footprint->GetFPID();

View File

@ -230,8 +230,7 @@ bool DRC_TEST_PROVIDER_MATCHED_LENGTH::runInternal( bool aDelayReportMode )
ftCache->Rebuild( m_board ); ftCache->Rebuild( m_board );
// This is the number of tests between 2 calls to the progress bar const size_t progressDelta = 100;
const size_t delta = 50;
size_t count = 0; size_t count = 0;
size_t ii = 0; size_t ii = 0;
@ -245,7 +244,7 @@ bool DRC_TEST_PROVIDER_MATCHED_LENGTH::runInternal( bool aDelayReportMode )
forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T }, LSET::AllCuMask(), forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T }, LSET::AllCuMask(),
[&]( BOARD_ITEM *item ) -> bool [&]( BOARD_ITEM *item ) -> bool
{ {
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; return false;
const DRC_CONSTRAINT_T constraintsToCheck[] = { const DRC_CONSTRAINT_T constraintsToCheck[] = {
@ -297,16 +296,16 @@ bool DRC_TEST_PROVIDER_MATCHED_LENGTH::runInternal( bool aDelayReportMode )
{ {
if( citem->Type() == PCB_VIA_T ) if( citem->Type() == PCB_VIA_T )
{ {
const BOARD_DESIGN_SETTINGS& ds = m_board->GetDesignSettings(); const BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
const BOARD_STACKUP& stackup = bds.GetStackupDescriptor();
ent.viaCount++; ent.viaCount++;
if( ds.m_UseHeightForLengthCalcs ) if( bds.m_UseHeightForLengthCalcs )
{ {
const PCB_VIA* v = static_cast<PCB_VIA*>( citem ); const PCB_VIA* v = static_cast<PCB_VIA*>( citem );
ent.totalVia += ds.GetStackupDescriptor().GetLayerDistance( ent.totalVia += stackup.GetLayerDistance( v->TopLayer(), v->BottomLayer() );
v->TopLayer(), v->BottomLayer() );
} }
} }
else if( citem->Type() == PCB_TRACE_T ) else if( citem->Type() == PCB_TRACE_T )
@ -357,7 +356,7 @@ bool DRC_TEST_PROVIDER_MATCHED_LENGTH::runInternal( bool aDelayReportMode )
DRC_RULE *rule = it.first; DRC_RULE *rule = it.first;
auto& matchedConnections = it.second; auto& matchedConnections = it.second;
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; return false;
std::sort( matchedConnections.begin(), matchedConnections.end(), std::sort( matchedConnections.begin(), matchedConnections.end(),

View File

@ -123,9 +123,7 @@ void DRC_TEST_PROVIDER_MISC::testOutline()
void DRC_TEST_PROVIDER_MISC::testDisabledLayers() void DRC_TEST_PROVIDER_MISC::testDisabledLayers()
{ {
// This is the number of tests between 2 calls to the progress bar const int progressDelta = 2000;
const int delta = 2000;
int ii = 0; int ii = 0;
int items = 0; int items = 0;
@ -147,7 +145,7 @@ void DRC_TEST_PROVIDER_MISC::testDisabledLayers()
if( m_drcEngine->IsErrorLimitExceeded( DRCE_DISABLED_LAYER_ITEM ) ) if( m_drcEngine->IsErrorLimitExceeded( DRCE_DISABLED_LAYER_ITEM ) )
return false; return false;
if( !reportProgress( ii++, items, delta ) ) if( !reportProgress( ii++, items, progressDelta ) )
return false; return false;
PCB_LAYER_ID badLayer = UNDEFINED_LAYER; PCB_LAYER_ID badLayer = UNDEFINED_LAYER;
@ -216,9 +214,7 @@ void DRC_TEST_PROVIDER_MISC::testDisabledLayers()
void DRC_TEST_PROVIDER_MISC::testAssertions() void DRC_TEST_PROVIDER_MISC::testAssertions()
{ {
// This is the number of tests between 2 calls to the progress bar const int progressDelta = 2000;
const int delta = 2000;
int ii = 0; int ii = 0;
int items = 0; int items = 0;
@ -235,7 +231,7 @@ void DRC_TEST_PROVIDER_MISC::testAssertions()
if( m_drcEngine->IsErrorLimitExceeded( DRCE_ASSERTION_FAILURE ) ) if( m_drcEngine->IsErrorLimitExceeded( DRCE_ASSERTION_FAILURE ) )
return false; return false;
if( !reportProgress( ii++, items, delta ) ) if( !reportProgress( ii++, items, progressDelta ) )
return false; return false;
m_drcEngine->ProcessAssertions( item, m_drcEngine->ProcessAssertions( item,
@ -259,9 +255,7 @@ void DRC_TEST_PROVIDER_MISC::testAssertions()
void DRC_TEST_PROVIDER_MISC::testTextVars() void DRC_TEST_PROVIDER_MISC::testTextVars()
{ {
// This is the number of tests between 2 calls to the progress bar const int progressDelta = 2000;
const int delta = 2000;
int ii = 0; int ii = 0;
int items = 0; int items = 0;
@ -283,7 +277,7 @@ void DRC_TEST_PROVIDER_MISC::testTextVars()
if( m_drcEngine->IsErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) ) if( m_drcEngine->IsErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) )
return false; return false;
if( !reportProgress( ii++, items, delta ) ) if( !reportProgress( ii++, items, progressDelta ) )
return false; return false;
BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item ); BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item );

View File

@ -101,8 +101,7 @@ bool DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::Run()
reportAux( wxT( "Largest physical clearance : %d nm" ), m_board->m_DRCMaxPhysicalClearance ); reportAux( wxT( "Largest physical clearance : %d nm" ), m_board->m_DRCMaxPhysicalClearance );
// This is the number of tests between 2 calls to the progress bar size_t progressDelta = 250;
size_t delta = 100;
size_t count = 0; size_t count = 0;
size_t ii = 0; size_t ii = 0;
@ -130,7 +129,7 @@ bool DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::Run()
forEachGeometryItem( itemTypes, LSET::AllLayersMask(), forEachGeometryItem( itemTypes, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool [&]( BOARD_ITEM* item ) -> bool
{ {
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; return false;
LSET layers = item->GetLayerSet(); LSET layers = item->GetLayerSet();
@ -155,7 +154,8 @@ bool DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::Run()
return true; return true;
} ); } );
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, int> checkedPairs; std::unordered_map<PTR_PTR_CACHE_KEY, int> checkedPairs;
progressDelta = 100;
ii = 0; ii = 0;
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE ) if( !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE )
@ -167,7 +167,7 @@ bool DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::Run()
forEachGeometryItem( itemTypes, LSET::AllLayersMask(), forEachGeometryItem( itemTypes, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool [&]( BOARD_ITEM* item ) -> bool
{ {
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; return false;
LSET layers = item->GetLayerSet(); LSET layers = item->GetLayerSet();
@ -216,6 +216,7 @@ bool DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::Run()
} ); } );
} }
progressDelta = 100;
count = 0; count = 0;
ii = 0; ii = 0;
@ -247,7 +248,7 @@ bool DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::Run()
{ {
if( IsCopperLayer( layer ) ) if( IsCopperLayer( layer ) )
{ {
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; return false;
DRC_CONSTRAINT c = m_drcEngine->EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, DRC_CONSTRAINT c = m_drcEngine->EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT,

View File

@ -76,8 +76,7 @@ private:
bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run() bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
{ {
// This is the number of tests between 2 calls to the progress bar const int progressDelta = 500;
const int delta = 500;
if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_SILK ) ) if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_SILK ) )
{ {
@ -113,7 +112,7 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
auto addToSilkTree = auto addToSilkTree =
[&]( BOARD_ITEM* item ) -> bool [&]( BOARD_ITEM* item ) -> bool
{ {
if( !reportProgress( ii++, items, delta ) ) if( !reportProgress( ii++, items, progressDelta ) )
return false; return false;
for( PCB_LAYER_ID layer : { F_SilkS, B_SilkS } ) for( PCB_LAYER_ID layer : { F_SilkS, B_SilkS } )
@ -128,7 +127,7 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
auto addToTargetTree = auto addToTargetTree =
[&]( BOARD_ITEM* item ) -> bool [&]( BOARD_ITEM* item ) -> bool
{ {
if( !reportProgress( ii++, items, delta ) ) if( !reportProgress( ii++, items, progressDelta ) )
return false; return false;
for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() ) for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
@ -261,7 +260,7 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
m_largestClearance, m_largestClearance,
[&]( int aCount, int aSize ) -> bool [&]( int aCount, int aSize ) -> bool
{ {
return reportProgress( aCount, aSize, delta ); return reportProgress( aCount, aSize, progressDelta );
} ); } );
reportRuleStatistics(); reportRuleStatistics();

View File

@ -176,7 +176,7 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
for( size_t ii = 0; ii < copperLayers.size(); ++ii ) for( size_t ii = 0; ii < copperLayers.size(); ++ii )
returns.emplace_back( tp.submit( sliver_checker, ii ) ); returns.emplace_back( tp.submit( sliver_checker, ii ) );
for( auto& retval : returns ) for( const std::future<size_t>& retval : returns )
{ {
std::future_status status; std::future_status status;
@ -184,8 +184,9 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
{ {
m_drcEngine->ReportProgress( static_cast<double>( zoneLayerCount ) / done ); m_drcEngine->ReportProgress( static_cast<double>( zoneLayerCount ) / done );
status = retval.wait_for( std::chrono::milliseconds( 100 ) ); status = retval.wait_for( std::chrono::milliseconds( 250 ) );
} while( status != std::future_status::ready ); }
while( status != std::future_status::ready );
} }

View File

@ -98,7 +98,7 @@ private:
std::unique_ptr<DRC_RTREE> m_tesselatedTree; std::unique_ptr<DRC_RTREE> m_tesselatedTree;
std::unique_ptr<DRC_RTREE> m_itemTree; std::unique_ptr<DRC_RTREE> m_itemTree;
std::map< std::tuple<BOARD_ITEM*, BOARD_ITEM*, PCB_LAYER_ID>, int> m_checkedPairs; std::unordered_map<PTR_PTR_LAYER_CACHE_KEY, int> m_checkedPairs;
// Shapes used to define solder mask apertures don't have nets, so we assign them the // Shapes used to define solder mask apertures don't have nets, so we assign them the
// first object+net that bridges their aperture (after which any other nets will generate // first object+net that bridges their aperture (after which any other nets will generate
@ -178,9 +178,9 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::buildRTrees()
ZONE* solderMask = m_board->m_SolderMask; ZONE* solderMask = m_board->m_SolderMask;
LSET layers = { 4, F_Mask, B_Mask, F_Cu, B_Cu }; LSET layers = { 4, F_Mask, B_Mask, F_Cu, B_Cu };
size_t delta = 50; // Number of tests between 2 calls to the progress bar const size_t progressDelta = 500;
int count = 0; int count = 0;
int ii = 0; int ii = 0;
solderMask->GetFill( F_Mask )->RemoveAllContours(); solderMask->GetFill( F_Mask )->RemoveAllContours();
solderMask->GetFill( B_Mask )->RemoveAllContours(); solderMask->GetFill( B_Mask )->RemoveAllContours();
@ -198,7 +198,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::buildRTrees()
forEachGeometryItem( s_allBasicItems, layers, forEachGeometryItem( s_allBasicItems, layers,
[&]( BOARD_ITEM* item ) -> bool [&]( BOARD_ITEM* item ) -> bool
{ {
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; return false;
addItemToRTrees( item ); addItemToRTrees( item );
@ -230,9 +230,9 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testSilkToMaskClearance()
{ {
LSET silkLayers = { 2, F_SilkS, B_SilkS }; LSET silkLayers = { 2, F_SilkS, B_SilkS };
size_t delta = 100; // Number of tests between 2 calls to the progress bar const size_t progressDelta = 250;
int count = 0; int count = 0;
int ii = 0; int ii = 0;
forEachGeometryItem( s_allBasicItems, silkLayers, forEachGeometryItem( s_allBasicItems, silkLayers,
[&]( BOARD_ITEM* item ) -> bool [&]( BOARD_ITEM* item ) -> bool
@ -247,7 +247,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testSilkToMaskClearance()
if( m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_CLEARANCE ) ) if( m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_CLEARANCE ) )
return false; return false;
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; return false;
if( isInvisibleText( item ) ) if( isInvisibleText( item ) )
@ -606,9 +606,9 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testMaskBridges()
{ {
LSET copperAndMaskLayers = { 4, F_Mask, B_Mask, F_Cu, B_Cu }; LSET copperAndMaskLayers = { 4, F_Mask, B_Mask, F_Cu, B_Cu };
size_t delta = 50; // Number of tests between 2 calls to the progress bar const size_t progressDelta = 250;
int count = 0; int count = 0;
int ii = 0; int ii = 0;
forEachGeometryItem( s_allBasicItemsButZones, copperAndMaskLayers, forEachGeometryItem( s_allBasicItemsButZones, copperAndMaskLayers,
[&]( BOARD_ITEM* item ) -> bool [&]( BOARD_ITEM* item ) -> bool
@ -623,7 +623,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testMaskBridges()
if( m_drcEngine->IsErrorLimitExceeded( DRCE_SOLDERMASK_BRIDGE ) ) if( m_drcEngine->IsErrorLimitExceeded( DRCE_SOLDERMASK_BRIDGE ) )
return false; return false;
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; return false;
EDA_RECT itemBBox = item->GetBoundingBox(); EDA_RECT itemBBox = item->GetBoundingBox();

View File

@ -67,7 +67,7 @@ public:
bool DRC_TEST_PROVIDER_TEXT_DIMS::Run() bool DRC_TEST_PROVIDER_TEXT_DIMS::Run()
{ {
const int delta = 100; // This is the number of tests between 2 calls to the progress bar const int progressDelta = 250;
int count = 0; int count = 0;
int ii = 0; int ii = 0;
@ -273,7 +273,7 @@ bool DRC_TEST_PROVIDER_TEXT_DIMS::Run()
forEachGeometryItem( itemTypes, LSET::AllLayersMask(), forEachGeometryItem( itemTypes, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool [&]( BOARD_ITEM* item ) -> bool
{ {
if( !reportProgress( ii++, count, delta ) ) if( !reportProgress( ii++, count, progressDelta ) )
return false; return false;
EDA_TEXT* text = nullptr; EDA_TEXT* text = nullptr;

View File

@ -61,8 +61,6 @@ public:
bool DRC_TEST_PROVIDER_TRACK_WIDTH::Run() bool DRC_TEST_PROVIDER_TRACK_WIDTH::Run()
{ {
const int delta = 100; // This is the number of tests between 2 calls to the progress bar
if( m_drcEngine->IsErrorLimitExceeded( DRCE_TRACK_WIDTH ) ) if( m_drcEngine->IsErrorLimitExceeded( DRCE_TRACK_WIDTH ) )
{ {
reportAux( wxT( "Track width violations ignored. Tests not run." ) ); reportAux( wxT( "Track width violations ignored. Tests not run." ) );
@ -153,11 +151,12 @@ bool DRC_TEST_PROVIDER_TRACK_WIDTH::Run()
return true; return true;
}; };
int ii = 0; const int progressDelta = 250;
int ii = 0;
for( PCB_TRACK* item : m_drcEngine->GetBoard()->Tracks() ) for( PCB_TRACK* item : m_drcEngine->GetBoard()->Tracks() )
{ {
if( !reportProgress( ii++, m_drcEngine->GetBoard()->Tracks().size(), delta ) ) if( !reportProgress( ii++, m_drcEngine->GetBoard()->Tracks().size(), progressDelta ) )
break; break;
if( !checkTrackWidth( item ) ) if( !checkTrackWidth( item ) )

View File

@ -61,8 +61,6 @@ public:
bool DRC_TEST_PROVIDER_VIA_DIAMETER::Run() bool DRC_TEST_PROVIDER_VIA_DIAMETER::Run()
{ {
const int delta = 100; // This is the number of tests between 2 calls to the progress bar
if( m_drcEngine->IsErrorLimitExceeded( DRCE_VIA_DIAMETER ) ) if( m_drcEngine->IsErrorLimitExceeded( DRCE_VIA_DIAMETER ) )
{ {
reportAux( wxT( "Via diameter violations ignored. Tests not run." ) ); reportAux( wxT( "Via diameter violations ignored. Tests not run." ) );
@ -143,11 +141,12 @@ bool DRC_TEST_PROVIDER_VIA_DIAMETER::Run()
return true; return true;
}; };
int ii = 0; const int progressDelta = 500;
int ii = 0;
for( PCB_TRACK* item : m_drcEngine->GetBoard()->Tracks() ) for( PCB_TRACK* item : m_drcEngine->GetBoard()->Tracks() )
{ {
if( !reportProgress( ii++, m_drcEngine->GetBoard()->Tracks().size(), delta ) ) if( !reportProgress( ii++, m_drcEngine->GetBoard()->Tracks().size(), progressDelta ) )
break; break;
if( !checkViaDiameter( item ) ) if( !checkViaDiameter( item ) )

View File

@ -94,15 +94,15 @@ void DRC_TEST_PROVIDER_ZONE_CONNECTIONS::testZoneLayer( ZONE* aZone, PCB_LAYER_I
// Quick tests for "connected": // Quick tests for "connected":
// //
if( !pad->FlashLayer( aLayer ) )
continue;
if( pad->GetNetCode() != aZone->GetNetCode() || pad->GetNetCode() <= 0 ) if( pad->GetNetCode() != aZone->GetNetCode() || pad->GetNetCode() <= 0 )
continue; continue;
EDA_RECT item_boundingbox = pad->GetBoundingBox(); EDA_RECT item_bbox = pad->GetBoundingBox();
if( !item_boundingbox.Intersects( aZone->GetCachedBoundingBox() ) ) if( !item_bbox.Intersects( aZone->GetCachedBoundingBox() ) )
continue;
if( !pad->FlashLayer( aLayer ) )
continue; continue;
// If those passed, do a thorough test: // If those passed, do a thorough test:
@ -125,19 +125,21 @@ void DRC_TEST_PROVIDER_ZONE_CONNECTIONS::testZoneLayer( ZONE* aZone, PCB_LAYER_I
ERROR_OUTSIDE ); ERROR_OUTSIDE );
SHAPE_LINE_CHAIN& padOutline = padPoly.Outline( 0 ); SHAPE_LINE_CHAIN& padOutline = padPoly.Outline( 0 );
BOX2I padBBox( item_bbox );
std::vector<SHAPE_LINE_CHAIN::INTERSECTION> intersections; std::vector<SHAPE_LINE_CHAIN::INTERSECTION> intersections;
int spokes = 0;
for( int jj = 0; jj < zoneFill->OutlineCount(); ++jj ) for( int jj = 0; jj < zoneFill->OutlineCount(); ++jj )
padOutline.Intersect( zoneFill->Outline( jj ), intersections, true ); zoneFill->Outline( jj ).Intersect( padOutline, intersections, true, &padBBox );
spokes += intersections.size() / 2; int spokes = intersections.size() / 2;
if( spokes <= 0 ) if( spokes <= 0 ) // Not connected at all
continue; continue;
// Now we know we're connected, so see if there are any other manual spokes if( spokes >= minCount ) // We already have enough
// added: continue;
// See if there are any other manual spokes added:
// //
for( PCB_TRACK* track : connectivity->GetConnectedTracks( pad ) ) for( PCB_TRACK* track : connectivity->GetConnectedTracks( pad ) )
{ {
@ -198,6 +200,8 @@ bool DRC_TEST_PROVIDER_ZONE_CONNECTIONS::Run()
} }
} }
total_effort = std::max( (size_t) 1, total_effort );
thread_pool& tp = GetKiCadThreadPool(); thread_pool& tp = GetKiCadThreadPool();
std::vector<std::future<int>> returns; std::vector<std::future<int>> returns;
@ -219,15 +223,16 @@ bool DRC_TEST_PROVIDER_ZONE_CONNECTIONS::Run()
zonelayer.first, zonelayer.second ) ); zonelayer.first, zonelayer.second ) );
} }
for( std::future<int>& retval : returns ) for( const std::future<int>& retval : returns )
{ {
std::future_status status; std::future_status status;
do do
{ {
m_drcEngine->ReportProgress( static_cast<double>( done ) / total_effort ); m_drcEngine->ReportProgress( static_cast<double>( done ) / total_effort );
status = retval.wait_for( std::chrono::milliseconds( 100 ) ); status = retval.wait_for( std::chrono::milliseconds( 250 ) );
} while( status != std::future_status::ready ); }
while( status != std::future_status::ready );
} }
return !m_drcEngine->IsCancelled(); return !m_drcEngine->IsCancelled();

View File

@ -2356,7 +2356,7 @@ void FOOTPRINT::CheckPads( const std::function<void( const PAD*, int,
void FOOTPRINT::CheckOverlappingPads( const std::function<void( const PAD*, const PAD*, void FOOTPRINT::CheckOverlappingPads( const std::function<void( const PAD*, const PAD*,
const VECTOR2I& )>& aErrorHandler ) const VECTOR2I& )>& aErrorHandler )
{ {
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, int> checkedPairs; std::unordered_map<PTR_PTR_CACHE_KEY, int> checkedPairs;
for( PAD* pad : Pads() ) for( PAD* pad : Pads() )
{ {

View File

@ -191,7 +191,7 @@ void FOOTPRINT_LIST_IMPL::loadLibs()
for( size_t ii = 0; ii < num_returns; ++ii ) for( size_t ii = 0; ii < num_returns; ++ii )
returns[ii] = tp.submit( loader_job ); returns[ii] = tp.submit( loader_job );
for( auto& retval : returns ) for( const std::future<size_t>& retval : returns )
{ {
std::future_status status; std::future_status status;
@ -200,8 +200,9 @@ void FOOTPRINT_LIST_IMPL::loadLibs()
if( m_progress_reporter && !m_progress_reporter->KeepRefreshing() ) if( m_progress_reporter && !m_progress_reporter->KeepRefreshing() )
m_cancelled = true; m_cancelled = true;
status = retval.wait_for( std::chrono::milliseconds( 100 ) ); status = retval.wait_for( std::chrono::milliseconds( 250 ) );
} while( status != std::future_status::ready ); }
while( status != std::future_status::ready );
} }
} }
@ -257,7 +258,7 @@ void FOOTPRINT_LIST_IMPL::loadFootprints()
for( size_t ii = 0; ii < num_elements; ++ii ) for( size_t ii = 0; ii < num_elements; ++ii )
returns[ii] = tp.submit( fp_thread ); returns[ii] = tp.submit( fp_thread );
for( auto& retval : returns ) for( const std::future<size_t>& retval : returns )
{ {
std::future_status status; std::future_status status;
@ -266,8 +267,9 @@ void FOOTPRINT_LIST_IMPL::loadFootprints()
if( m_progress_reporter ) if( m_progress_reporter )
m_progress_reporter->KeepRefreshing(); m_progress_reporter->KeepRefreshing();
status = retval.wait_for( std::chrono::milliseconds( 100 ) ); status = retval.wait_for( std::chrono::milliseconds( 250 ) );
} while( status != std::future_status::ready ); }
while( status != std::future_status::ready );
} }
std::unique_ptr<FOOTPRINT_INFO> fpi; std::unique_ptr<FOOTPRINT_INFO> fpi;

View File

@ -221,11 +221,11 @@ bool isInsideCourtyard( BOARD_ITEM* aItem, const EDA_RECT& aItemBBox,
if( !aFootprint ) if( !aFootprint )
return false; return false;
BOARD* board = aItem->GetBoard(); BOARD* board = aItem->GetBoard();
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex ); std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
std::pair<BOARD_ITEM*, BOARD_ITEM*> key( aFootprint, aItem ); PTR_PTR_CACHE_KEY key = { aFootprint, aItem };
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool >* cache; std::unordered_map<PTR_PTR_CACHE_KEY, bool>* cache;
switch( aSide ) switch( aSide )
{ {
@ -579,11 +579,11 @@ bool isInsideArea( BOARD_ITEM* aItem, const EDA_RECT& aItemBBox, PCB_EXPR_CONTEX
if( !aArea || aArea == aItem || aArea->GetParent() == aItem ) if( !aArea || aArea == aItem || aArea->GetParent() == aItem )
return false; return false;
BOARD* board = aArea->GetBoard(); BOARD* board = aArea->GetBoard();
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex ); std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
PCB_LAYER_ID layer = aCtx->GetLayer(); PCB_LAYER_ID layer = aCtx->GetLayer();
std::tuple<BOARD_ITEM*, BOARD_ITEM*, PCB_LAYER_ID> key( aArea, aItem, layer ); PTR_PTR_LAYER_CACHE_KEY key = { aArea, aItem, layer };
auto i = board->m_InsideAreaCache.find( key ); auto i = board->m_InsideAreaCache.find( key );
if( i != board->m_InsideAreaCache.end() ) if( i != board->m_InsideAreaCache.end() )
return i->second; return i->second;

View File

@ -2073,7 +2073,7 @@ void PCB_PAINTER::draw( const FOOTPRINT* aFootprint, int aLayer )
m_gal->DrawLine( center - VECTOR2D( 0, anchorSize ), center + VECTOR2D( 0, anchorSize ) ); m_gal->DrawLine( center - VECTOR2D( 0, anchorSize ), center + VECTOR2D( 0, anchorSize ) );
} }
if( aLayer == LAYER_LOCKED_ITEM_SHADOW ) // happens only if locked if( aLayer == LAYER_LOCKED_ITEM_SHADOW && m_frameType == FRAME_PCB_EDITOR ) // happens only if locked
{ {
const COLOR4D color = m_pcbSettings.GetColor( aFootprint, aLayer ); const COLOR4D color = m_pcbSettings.GetColor( aFootprint, aLayer );
@ -2081,8 +2081,12 @@ void PCB_PAINTER::draw( const FOOTPRINT* aFootprint, int aLayer )
m_gal->SetIsStroke( false ); m_gal->SetIsStroke( false );
m_gal->SetFillColor( color ); m_gal->SetFillColor( color );
#if 0 // GetBoundingHull() can be very slow, especially for logos imported from graphics
const SHAPE_POLY_SET& poly = aFootprint->GetBoundingHull(); const SHAPE_POLY_SET& poly = aFootprint->GetBoundingHull();
m_gal->DrawPolygon( poly ); m_gal->DrawPolygon( poly );
#else
m_gal->DrawRectangle( aFootprint->GetBoundingBox( true, false ) );
#endif
} }
if( aLayer == LAYER_CONFLICTS_SHADOW ) // happens only if locked if( aLayer == LAYER_CONFLICTS_SHADOW ) // happens only if locked

View File

@ -127,7 +127,7 @@ void PCB_PARSER::checkpoint()
unsigned curLine = reader->LineNumber(); unsigned curLine = reader->LineNumber();
auto delta = std::chrono::duration_cast<TIMEOUT>( curTime - m_lastProgressTime ); auto delta = std::chrono::duration_cast<TIMEOUT>( curTime - m_lastProgressTime );
if( delta > std::chrono::milliseconds( 100 ) ) if( delta > std::chrono::milliseconds( 250 ) )
{ {
m_progressReporter->SetCurrentProgress( ( (double) curLine ) m_progressReporter->SetCurrentProgress( ( (double) curLine )
/ std::max( 1U, m_lineCount ) ); / std::max( 1U, m_lineCount ) );

View File

@ -71,6 +71,31 @@
typedef VECTOR2I::extended_type ecoord; typedef VECTOR2I::extended_type ecoord;
struct CLEARANCE_CACHE_KEY
{
const PNS::ITEM* A;
const PNS::ITEM* B;
bool Flag;
bool operator==(const CLEARANCE_CACHE_KEY& other) const
{
return A == other.A && B == other.B && Flag == other.Flag;
}
};
namespace std
{
template <>
struct hash<CLEARANCE_CACHE_KEY>
{
std::size_t operator()( const CLEARANCE_CACHE_KEY& k ) const
{
return hash<const void*>()( k.A ) ^ hash<const void*>()( k.B ) ^ hash<int>()( k.Flag );
}
};
}
class PNS_PCBNEW_RULE_RESOLVER : public PNS::RULE_RESOLVER class PNS_PCBNEW_RULE_RESOLVER : public PNS::RULE_RESOLVER
{ {
public: public:
@ -120,11 +145,9 @@ private:
PCB_VIA m_dummyVias[2]; PCB_VIA m_dummyVias[2];
int m_clearanceEpsilon; int m_clearanceEpsilon;
typedef std::tuple<const PNS::ITEM*, const PNS::ITEM*, bool> CLEARANCE_CACHE_KEY; std::unordered_map<CLEARANCE_CACHE_KEY, int> m_clearanceCache;
std::unordered_map<CLEARANCE_CACHE_KEY, int> m_holeClearanceCache;
std::map<CLEARANCE_CACHE_KEY, int> m_clearanceCache; std::unordered_map<CLEARANCE_CACHE_KEY, int> m_holeToHoleClearanceCache;
std::map<CLEARANCE_CACHE_KEY, int> m_holeClearanceCache;
std::map<CLEARANCE_CACHE_KEY, int> m_holeToHoleClearanceCache;
}; };
@ -311,15 +334,18 @@ bool PNS_PCBNEW_RULE_RESOLVER::QueryConstraint( PNS::CONSTRAINT_TYPE aType,
void PNS_PCBNEW_RULE_RESOLVER::ClearCacheForItem( const PNS::ITEM* aItem ) void PNS_PCBNEW_RULE_RESOLVER::ClearCacheForItem( const PNS::ITEM* aItem )
{ {
m_clearanceCache.erase( std::make_tuple( aItem, nullptr, false ) ); CLEARANCE_CACHE_KEY key = { aItem, nullptr, false };
m_clearanceCache.erase( std::make_tuple( aItem, nullptr, true ) ); m_clearanceCache.erase( key );
key.Flag = true;
m_clearanceCache.erase( key );
} }
int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB, int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB,
bool aUseClearanceEpsilon ) bool aUseClearanceEpsilon )
{ {
CLEARANCE_CACHE_KEY key( aA, aB, aUseClearanceEpsilon ); CLEARANCE_CACHE_KEY key = { aA, aB, aUseClearanceEpsilon };
auto it = m_clearanceCache.find( key ); auto it = m_clearanceCache.find( key );
if( it != m_clearanceCache.end() ) if( it != m_clearanceCache.end() )
@ -360,7 +386,7 @@ int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS::ITEM* aA, const PNS::ITEM* a
int PNS_PCBNEW_RULE_RESOLVER::HoleClearance( const PNS::ITEM* aA, const PNS::ITEM* aB, int PNS_PCBNEW_RULE_RESOLVER::HoleClearance( const PNS::ITEM* aA, const PNS::ITEM* aB,
bool aUseClearanceEpsilon ) bool aUseClearanceEpsilon )
{ {
CLEARANCE_CACHE_KEY key( aA, aB, aUseClearanceEpsilon ); CLEARANCE_CACHE_KEY key = { aA, aB, aUseClearanceEpsilon };
auto it = m_holeClearanceCache.find( key ); auto it = m_holeClearanceCache.find( key );
if( it != m_holeClearanceCache.end() ) if( it != m_holeClearanceCache.end() )
@ -389,7 +415,7 @@ int PNS_PCBNEW_RULE_RESOLVER::HoleClearance( const PNS::ITEM* aA, const PNS::ITE
int PNS_PCBNEW_RULE_RESOLVER::HoleToHoleClearance( const PNS::ITEM* aA, const PNS::ITEM* aB, int PNS_PCBNEW_RULE_RESOLVER::HoleToHoleClearance( const PNS::ITEM* aA, const PNS::ITEM* aB,
bool aUseClearanceEpsilon ) bool aUseClearanceEpsilon )
{ {
CLEARANCE_CACHE_KEY key( aA, aB, aUseClearanceEpsilon ); CLEARANCE_CACHE_KEY key = { aA, aB, aUseClearanceEpsilon };
auto it = m_holeToHoleClearanceCache.find( key ); auto it = m_holeToHoleClearanceCache.find( key );
if( it != m_holeToHoleClearanceCache.end() ) if( it != m_holeToHoleClearanceCache.end() )

View File

@ -1121,12 +1121,12 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks(
auto connectivity = board()->GetConnectivity(); auto connectivity = board()->GetConnectivity();
std::map<VECTOR2I, std::vector<PCB_TRACK*>> trackMap; std::unordered_map<VECTOR2I, std::vector<PCB_TRACK*>> trackMap;
std::map<VECTOR2I, PCB_VIA*> viaMap; std::unordered_map<VECTOR2I, PCB_VIA*> viaMap;
std::map<VECTOR2I, PAD*> padMap; std::unordered_map<VECTOR2I, PAD*> padMap;
std::set<PAD*> startPadSet; std::set<PAD*> startPadSet;
std::vector<BOARD_CONNECTED_ITEM*> cleanupItems; std::vector<BOARD_CONNECTED_ITEM*> cleanupItems;
std::vector<std::pair<VECTOR2I, LSET>> activePts; std::vector<std::pair<VECTOR2I, LSET>> activePts;
for( BOARD_CONNECTED_ITEM* startItem : aStartItems ) for( BOARD_CONNECTED_ITEM* startItem : aStartItems )
{ {

View File

@ -215,22 +215,22 @@ bool TRACKS_CLEANER::testTrackEndpointIsNode( PCB_TRACK* aTrack, bool aTstStart
{ {
// A node is a point where more than 2 items are connected. // A node is a point where more than 2 items are connected.
auto connectivity = m_brd->GetConnectivity(); const std::list<CN_ITEM*>& items =
auto items = connectivity->GetConnectivityAlgo()->ItemEntry( aTrack ).GetItems(); m_brd->GetConnectivity()->GetConnectivityAlgo()->ItemEntry( aTrack ).GetItems();
if( items.empty() ) if( items.empty() )
return false; return false;
auto citem = items.front(); CN_ITEM* citem = items.front();
if( !citem->Valid() ) if( !citem->Valid() )
return false; return false;
auto anchors = citem->Anchors(); const std::vector<std::shared_ptr<CN_ANCHOR>>& anchors = citem->Anchors();
VECTOR2I refpoint = aTstStart ? aTrack->GetStart() : aTrack->GetEnd(); VECTOR2I refpoint = aTstStart ? aTrack->GetStart() : aTrack->GetEnd();
for( const auto& anchor : anchors ) for( const std::shared_ptr<CN_ANCHOR>& anchor : anchors )
{ {
if( anchor->Pos() != refpoint ) if( anchor->Pos() != refpoint )
continue; continue;
@ -486,7 +486,8 @@ void TRACKS_CLEANER::cleanup( bool aDeleteDuplicateVias, bool aDeleteNullSegment
merged = false; merged = false;
m_brd->BuildConnectivity(); m_brd->BuildConnectivity();
auto connectivity = m_brd->GetConnectivity()->GetConnectivityAlgo(); std::shared_ptr<CN_CONNECTIVITY_ALGO> connectivity =
m_brd->GetConnectivity()->GetConnectivityAlgo();
// Keep a duplicate deque to all deleting in the primary // Keep a duplicate deque to all deleting in the primary
std::deque<PCB_TRACK*> temp_segments( m_brd->Tracks() ); std::deque<PCB_TRACK*> temp_segments( m_brd->Tracks() );
@ -716,7 +717,7 @@ bool TRACKS_CLEANER::mergeCollinearSegments( PCB_TRACK* aSeg1, PCB_TRACK* aSeg2
void TRACKS_CLEANER::removeItems( std::set<BOARD_ITEM*>& aItems ) void TRACKS_CLEANER::removeItems( std::set<BOARD_ITEM*>& aItems )
{ {
for( auto item : aItems ) for( BOARD_ITEM* item : aItems )
{ {
m_brd->Remove( item ); m_brd->Remove( item );
m_commit.Removed( item ); m_commit.Removed( item );

View File

@ -265,10 +265,10 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
thread_pool& tp = GetKiCadThreadPool(); thread_pool& tp = GetKiCadThreadPool();
for( auto& fillItem : toFill ) for( const std::pair<ZONE*, PCB_LAYER_ID>& fillItem : toFill )
returns.emplace_back( tp.submit( fill_lambda, fillItem ) ); returns.emplace_back( tp.submit( fill_lambda, fillItem ) );
for( auto& ret : returns ) for( const std::future<int>& ret : returns )
{ {
std::future_status status; std::future_status status;
@ -277,8 +277,9 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
if( m_progressReporter ) if( m_progressReporter )
m_progressReporter->KeepRefreshing(); m_progressReporter->KeepRefreshing();
status = ret.wait_for( std::chrono::milliseconds( 100 ) ); status = ret.wait_for( std::chrono::milliseconds( 250 ) );
} while( status != std::future_status::ready ); }
while( status != std::future_status::ready );
} }
alg::delete_if( toFill, [&]( const std::pair<ZONE*, PCB_LAYER_ID> pair ) -> bool alg::delete_if( toFill, [&]( const std::pair<ZONE*, PCB_LAYER_ID> pair ) -> bool