mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Optimize zone-zone clearance checks
Improve the CREEPAGE_GRAPH:::GeneratePaths to skip unused checks. Handle zone-zone paralellism better Fixes https://gitlab.com/kicad/code/kicad/-/issues/21353
This commit is contained in:
parent
4c03ab8ebb
commit
faeaee824a
@ -2245,7 +2245,7 @@ void CREEPAGE_GRAPH::Addshape( const SHAPE& aShape, std::shared_ptr<GRAPH_NODE>&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CREEPAGE_GRAPH::GeneratePaths( double aMaxWeight, PCB_LAYER_ID aLayer, bool aClearance )
|
void CREEPAGE_GRAPH::GeneratePaths( double aMaxWeight, PCB_LAYER_ID aLayer )
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<GRAPH_NODE>> nodes;
|
std::vector<std::shared_ptr<GRAPH_NODE>> nodes;
|
||||||
std::mutex nodes_lock;
|
std::mutex nodes_lock;
|
||||||
@ -2265,102 +2265,134 @@ void CREEPAGE_GRAPH::GeneratePaths( double aMaxWeight, PCB_LAYER_ID aLayer, bool
|
|||||||
&& gn1->m_net < gn2->m_net );
|
&& gn1->m_net < gn2->m_net );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
auto processNodes = [&]( size_t i, size_t j ) -> bool
|
// Build parent -> net -> nodes mapping for efficient filtering
|
||||||
|
std::unordered_map<const BOARD_ITEM*, std::unordered_map<int, std::vector<std::shared_ptr<GRAPH_NODE>>>> parent_net_groups;
|
||||||
|
std::vector<const BOARD_ITEM*> parent_keys;
|
||||||
|
|
||||||
|
for( const auto& gn : nodes )
|
||||||
{
|
{
|
||||||
for( size_t ii = i; ii < j; ii++ )
|
const BOARD_ITEM* parent = gn->m_parent->GetParent();
|
||||||
|
|
||||||
|
if( parent_net_groups[parent].empty() )
|
||||||
|
parent_keys.push_back( parent );
|
||||||
|
|
||||||
|
parent_net_groups[parent][gn->m_net].push_back( gn );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate work items: compare nodes between different parents only
|
||||||
|
struct WorkItem {
|
||||||
|
std::shared_ptr<GRAPH_NODE> node1, node2;
|
||||||
|
};
|
||||||
|
std::vector<WorkItem> work_items;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < parent_keys.size(); ++i )
|
||||||
|
{
|
||||||
|
for( size_t j = i + 1; j < parent_keys.size(); ++j )
|
||||||
|
{
|
||||||
|
const auto& group1_nets = parent_net_groups[parent_keys[i]];
|
||||||
|
const auto& group2_nets = parent_net_groups[parent_keys[j]];
|
||||||
|
|
||||||
|
for( const auto& [net1, nodes1] : group1_nets )
|
||||||
{
|
{
|
||||||
std::shared_ptr<GRAPH_NODE> gn1 = nodes[ii];
|
for( const auto& [net2, nodes2] : group2_nets )
|
||||||
|
|
||||||
for( size_t jj = ii + 1; jj < nodes.size(); jj++ )
|
|
||||||
{
|
{
|
||||||
std::shared_ptr<GRAPH_NODE> gn2 = nodes[jj];
|
// Skip if same net and both nets have only conductive nodes
|
||||||
|
if( net1 == net2 )
|
||||||
if( gn1->m_parent->GetParent() == gn2->m_parent->GetParent() )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( ( gn1->m_net == gn2->m_net ) && ( gn1->m_parent->IsConductive() )
|
|
||||||
&& ( gn2->m_parent->IsConductive() ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for( PATH_CONNECTION pc : GetPaths( gn1->m_parent, gn2->m_parent, aMaxWeight ) )
|
|
||||||
{
|
{
|
||||||
std::vector<const BOARD_ITEM*> IgnoreForTest;
|
bool all_conductive_1 = std::all_of( nodes1.begin(), nodes1.end(),
|
||||||
IgnoreForTest.push_back( gn1->m_parent->GetParent() );
|
[]( const auto& n ) { return n->m_parent->IsConductive(); } );
|
||||||
IgnoreForTest.push_back( gn2->m_parent->GetParent() );
|
bool all_conductive_2 = std::all_of( nodes2.begin(), nodes2.end(),
|
||||||
|
[]( const auto& n ) { return n->m_parent->IsConductive(); } );
|
||||||
|
|
||||||
if( !pc.isValid( m_board, aLayer, m_boardEdge, IgnoreForTest, m_boardOutline,
|
if( all_conductive_1 && all_conductive_2 )
|
||||||
{ false, true }, m_minGrooveWidth ) )
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::shared_ptr<GRAPH_NODE>* connect1 = &gn1;
|
|
||||||
std::shared_ptr<GRAPH_NODE>* connect2 = &gn2;
|
|
||||||
std::shared_ptr<GRAPH_NODE> gnt1 = nullptr;
|
|
||||||
std::shared_ptr<GRAPH_NODE> gnt2 = nullptr;
|
|
||||||
std::lock_guard<std::mutex> lock( nodes_lock );
|
|
||||||
|
|
||||||
if( gn1->m_parent->GetType() != CREEP_SHAPE::TYPE::POINT )
|
|
||||||
{
|
|
||||||
gnt1 = AddNode( GRAPH_NODE::POINT, gn1->m_parent, pc.a1 );
|
|
||||||
gnt1->m_connectDirectly = false;
|
|
||||||
|
|
||||||
if( gn1->m_parent->IsConductive() )
|
|
||||||
{
|
|
||||||
std::shared_ptr<GRAPH_CONNECTION> gc = AddConnection( gn1, gnt1 );
|
|
||||||
|
|
||||||
if( gc )
|
|
||||||
gc->m_path.m_show = false;
|
|
||||||
}
|
|
||||||
connect1 = &gnt1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( gn2->m_parent->GetType() != CREEP_SHAPE::TYPE::POINT )
|
|
||||||
{
|
|
||||||
gnt2 = AddNode( GRAPH_NODE::POINT, gn2->m_parent, pc.a2 );
|
|
||||||
gnt2->m_connectDirectly = false;
|
|
||||||
|
|
||||||
if( gn2->m_parent->IsConductive() )
|
|
||||||
{
|
|
||||||
std::shared_ptr<GRAPH_CONNECTION> gc = AddConnection( gn2, gnt2 );
|
|
||||||
|
|
||||||
if( gc )
|
|
||||||
gc->m_path.m_show = false;
|
|
||||||
}
|
|
||||||
connect2 = &gnt2;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddConnection( *connect1, *connect2, pc );
|
|
||||||
}
|
}
|
||||||
} // for jj
|
|
||||||
} // for ii
|
|
||||||
|
|
||||||
return true;
|
// Add all node pairs from these net groups
|
||||||
};
|
for( const auto& gn1 : nodes1 )
|
||||||
|
for( const auto& gn2 : nodes2 )
|
||||||
|
work_items.push_back( { gn1, gn2 } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Running in the clearance test, we are already in a parallelized loop, so parallelizing again
|
auto processWorkItems = [&]( size_t start_idx, size_t end_idx ) -> bool
|
||||||
// will run into deadlock as all threads start waiting
|
{
|
||||||
if( aClearance )
|
for( size_t idx = start_idx; idx < end_idx; ++idx )
|
||||||
processNodes( 0, nodes.size() );
|
{
|
||||||
|
auto [gn1, gn2] = work_items[idx];
|
||||||
|
|
||||||
|
for( PATH_CONNECTION pc : GetPaths( gn1->m_parent, gn2->m_parent, aMaxWeight ) )
|
||||||
|
{
|
||||||
|
std::vector<const BOARD_ITEM*> IgnoreForTest = {
|
||||||
|
gn1->m_parent->GetParent(), gn2->m_parent->GetParent()
|
||||||
|
};
|
||||||
|
|
||||||
|
if( !pc.isValid( m_board, aLayer, m_boardEdge, IgnoreForTest, m_boardOutline,
|
||||||
|
{ false, true }, m_minGrooveWidth ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::shared_ptr<GRAPH_NODE> connect1 = gn1, connect2 = gn2;
|
||||||
|
std::lock_guard<std::mutex> lock( nodes_lock );
|
||||||
|
|
||||||
|
// Handle non-point node1
|
||||||
|
if( gn1->m_parent->GetType() != CREEP_SHAPE::TYPE::POINT )
|
||||||
|
{
|
||||||
|
auto gnt1 = AddNode( GRAPH_NODE::POINT, gn1->m_parent, pc.a1 );
|
||||||
|
gnt1->m_connectDirectly = false;
|
||||||
|
connect1 = gnt1;
|
||||||
|
|
||||||
|
if( gn1->m_parent->IsConductive() )
|
||||||
|
{
|
||||||
|
if( auto gc = AddConnection( gn1, gnt1 ) )
|
||||||
|
gc->m_path.m_show = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle non-point node2
|
||||||
|
if( gn2->m_parent->GetType() != CREEP_SHAPE::TYPE::POINT )
|
||||||
|
{
|
||||||
|
auto gnt2 = AddNode( GRAPH_NODE::POINT, gn2->m_parent, pc.a2 );
|
||||||
|
gnt2->m_connectDirectly = false;
|
||||||
|
connect2 = gnt2;
|
||||||
|
|
||||||
|
if( gn2->m_parent->IsConductive() )
|
||||||
|
{
|
||||||
|
if( auto gc = AddConnection( gn2, gnt2 ) )
|
||||||
|
gc->m_path.m_show = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AddConnection( connect1, connect2, pc );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// If the number of tasks is high enough, this indicates that the calling process
|
||||||
|
// has already parallelized the work, so we can process all items in one go.
|
||||||
|
if( tp.get_tasks_total() >= tp.get_thread_count() - 4 )
|
||||||
|
{
|
||||||
|
processWorkItems( 0, work_items.size() );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto ret = tp.parallelize_loop( nodes.size(), processNodes );
|
auto ret = tp.parallelize_loop( work_items.size(), processWorkItems );
|
||||||
|
|
||||||
for( size_t ii = 0; ii < ret.size(); ii++ )
|
for( size_t ii = 0; ii < ret.size(); ii++ )
|
||||||
{
|
{
|
||||||
std::future<bool>& r = ret[ii];
|
std::future<bool>& r = ret[ii];
|
||||||
|
|
||||||
if( r.valid() )
|
if( !r.valid() )
|
||||||
{
|
continue;
|
||||||
std::future_status status = r.wait_for( std::chrono::seconds( 0 ) );
|
|
||||||
|
|
||||||
while( status != std::future_status::ready )
|
while( r.wait_for( std::chrono::milliseconds( 100 ) ) != std::future_status::ready ){}
|
||||||
{
|
|
||||||
status = r.wait_for( std::chrono::milliseconds( 100 ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CREEPAGE_GRAPH::Trim( double aWeightLimit )
|
void CREEPAGE_GRAPH::Trim( double aWeightLimit )
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<GRAPH_CONNECTION>> toRemove;
|
std::vector<std::shared_ptr<GRAPH_CONNECTION>> toRemove;
|
||||||
|
@ -69,7 +69,7 @@ struct PATH_CONNECTION
|
|||||||
bool isValid( const BOARD& aBoard, PCB_LAYER_ID aLayer,
|
bool isValid( const BOARD& aBoard, PCB_LAYER_ID aLayer,
|
||||||
const std::vector<BOARD_ITEM*>& aBoardEdges,
|
const std::vector<BOARD_ITEM*>& aBoardEdges,
|
||||||
const std::vector<const BOARD_ITEM*>& aIgnoreForTest, SHAPE_POLY_SET* aOutline,
|
const std::vector<const BOARD_ITEM*>& aIgnoreForTest, SHAPE_POLY_SET* aOutline,
|
||||||
const std::pair<bool, bool>& aTestLocalConcavity, int aMinGrooveWidth )
|
const std::pair<bool, bool>& aTestLocalConcavity, int aMinGrooveWidth ) const
|
||||||
{
|
{
|
||||||
if( !aOutline )
|
if( !aOutline )
|
||||||
return true; // We keep the segment if there is a problem
|
return true; // We keep the segment if there is a problem
|
||||||
@ -760,7 +760,7 @@ public:
|
|||||||
double Solve( std::shared_ptr<GRAPH_NODE>& aFrom, std::shared_ptr<GRAPH_NODE>& aTo,
|
double Solve( std::shared_ptr<GRAPH_NODE>& aFrom, std::shared_ptr<GRAPH_NODE>& aTo,
|
||||||
std::vector<std::shared_ptr<GRAPH_CONNECTION>>& aResult );
|
std::vector<std::shared_ptr<GRAPH_CONNECTION>>& aResult );
|
||||||
|
|
||||||
void GeneratePaths( double aMaxWeight, PCB_LAYER_ID aLayer, bool aClearance );
|
void GeneratePaths( double aMaxWeight, PCB_LAYER_ID aLayer );
|
||||||
|
|
||||||
std::shared_ptr<GRAPH_NODE> AddNetElements( int aNetCode, PCB_LAYER_ID aLayer, int aMaxCreepage );
|
std::shared_ptr<GRAPH_NODE> AddNetElements( int aNetCode, PCB_LAYER_ID aLayer, int aMaxCreepage );
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ void DRC_TEST_PROVIDER_CLEARANCE_BASE::ReportAndShowPathCuToCu( std::shared_ptr<
|
|||||||
graph.Addshape( *( aItem1->GetEffectiveShape( layer ) ), NetA, nullptr );
|
graph.Addshape( *( aItem1->GetEffectiveShape( layer ) ), NetA, nullptr );
|
||||||
graph.Addshape( *( aItem2->GetEffectiveShape( layer ) ), NetB, nullptr );
|
graph.Addshape( *( aItem2->GetEffectiveShape( layer ) ), NetB, nullptr );
|
||||||
|
|
||||||
graph.GeneratePaths( aDistance * 2, layer, true );
|
graph.GeneratePaths( aDistance * 2, layer );
|
||||||
|
|
||||||
double minValue = aDistance * 2;
|
double minValue = aDistance * 2;
|
||||||
GRAPH_CONNECTION* minGc = nullptr;
|
GRAPH_CONNECTION* minGc = nullptr;
|
||||||
|
@ -1203,83 +1203,94 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||||||
std::vector<std::map<PCB_LAYER_ID, std::vector<SEG>>> poly_segments;
|
std::vector<std::map<PCB_LAYER_ID, std::vector<SEG>>> poly_segments;
|
||||||
poly_segments.resize( m_board->m_DRCCopperZones.size() );
|
poly_segments.resize( m_board->m_DRCCopperZones.size() );
|
||||||
|
|
||||||
// Contains the index for zoneA, zoneB, the conflict point, the actual clearance, the
|
thread_pool& tp = GetKiCadThreadPool();
|
||||||
// constraint, and the layer
|
std::atomic<size_t> done( 0 );
|
||||||
using REPORT_DATA = std::tuple<int, int, VECTOR2I, int, DRC_CONSTRAINT, PCB_LAYER_ID>;
|
size_t count = 0;
|
||||||
|
|
||||||
std::vector<std::future<REPORT_DATA>> futures;
|
auto reportZoneZoneViolation = [this]( ZONE* zoneA, ZONE* zoneB, VECTOR2I& pt, int actual,
|
||||||
thread_pool& tp = GetKiCadThreadPool();
|
const DRC_CONSTRAINT& constraint, PCB_LAYER_ID layer ) -> void
|
||||||
std::atomic<size_t> done( 1 );
|
{
|
||||||
|
std::shared_ptr<DRC_ITEM> drce;
|
||||||
|
|
||||||
auto checkZones =
|
if( constraint.IsNull() )
|
||||||
[this, testClearance, testIntersects, &poly_segments, &done]
|
{
|
||||||
( int zoneA_idx, int zoneB_idx, bool sameNet, PCB_LAYER_ID layer ) -> REPORT_DATA
|
drce = DRC_ITEM::Create( DRCE_ZONES_INTERSECT );
|
||||||
|
wxString msg = _( "(intersecting zones must have distinct priorities)" );
|
||||||
|
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + msg );
|
||||||
|
drce->SetItems( zoneA, zoneB );
|
||||||
|
reportViolation( drce, pt, layer );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
drce = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||||
|
wxString msg = formatMsg( _( "(%s clearance %s; actual %s)" ), constraint.GetName(),
|
||||||
|
constraint.GetValue().Min(), std::max( actual, 0 ) );
|
||||||
|
|
||||||
|
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + msg );
|
||||||
|
drce->SetItems( zoneA, zoneB );
|
||||||
|
drce->SetViolatingRule( constraint.GetParentRule() );
|
||||||
|
ReportAndShowPathCuToCu( drce, pt, layer, zoneA, zoneB, layer, actual );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto checkZones = [this, testClearance, testIntersects, reportZoneZoneViolation, &poly_segments,
|
||||||
|
&done]( int zoneA_idx, int zoneB_idx, bool sameNet, PCB_LAYER_ID layer ) -> void
|
||||||
|
{
|
||||||
|
ZONE* zoneA = m_board->m_DRCCopperZones[zoneA_idx];
|
||||||
|
ZONE* zoneB = m_board->m_DRCCopperZones[zoneB_idx];
|
||||||
|
int actual = 0;
|
||||||
|
VECTOR2I pt;
|
||||||
|
|
||||||
|
if( sameNet && testIntersects )
|
||||||
|
{
|
||||||
|
if( zoneA->Outline()->Collide( zoneB->Outline(), 0, &actual, &pt ) )
|
||||||
{
|
{
|
||||||
ZONE* zoneA = m_board->m_DRCCopperZones[zoneA_idx];
|
done.fetch_add( 1 );
|
||||||
ZONE* zoneB = m_board->m_DRCCopperZones[zoneB_idx];
|
reportZoneZoneViolation( zoneA, zoneB, pt, actual, DRC_CONSTRAINT(), layer );
|
||||||
int actual = 0;
|
return;
|
||||||
VECTOR2I pt;
|
}
|
||||||
|
}
|
||||||
|
else if( !sameNet && testClearance )
|
||||||
|
{
|
||||||
|
DRC_CONSTRAINT constraint = m_drcEngine->EvalRules( CLEARANCE_CONSTRAINT, zoneA, zoneB, layer );
|
||||||
|
int clearance = constraint.GetValue().Min();
|
||||||
|
|
||||||
if( sameNet && testIntersects )
|
if( constraint.GetSeverity() != RPT_SEVERITY_IGNORE && clearance > 0 )
|
||||||
|
{
|
||||||
|
std::map<VECTOR2I, int> conflictPoints;
|
||||||
|
|
||||||
|
std::vector<SEG>& refSegments = poly_segments[zoneA_idx][layer];
|
||||||
|
std::vector<SEG>& testSegments = poly_segments[zoneB_idx][layer];
|
||||||
|
|
||||||
|
// Iterate through all the segments in zoneA
|
||||||
|
for( SEG& refSegment : refSegments )
|
||||||
{
|
{
|
||||||
if( zoneA->Outline()->Collide( zoneB->Outline(), 0, &actual, &pt ) )
|
// Iterate through all the segments in zoneB
|
||||||
|
for( SEG& testSegment : testSegments )
|
||||||
{
|
{
|
||||||
done.fetch_add( 1 );
|
// We have ensured that the 'A' segment starts before the 'B' segment, so if the
|
||||||
return std::make_tuple( zoneA_idx, zoneB_idx, pt, 0, DRC_CONSTRAINT(), layer );
|
// 'A' segment ends before the 'B' segment starts, we can skip to the next 'A'
|
||||||
}
|
if( refSegment.B.x < testSegment.A.x )
|
||||||
}
|
break;
|
||||||
else if( !sameNet && testClearance )
|
|
||||||
{
|
|
||||||
DRC_CONSTRAINT constraint = m_drcEngine->EvalRules( CLEARANCE_CONSTRAINT, zoneA, zoneB, layer );
|
|
||||||
int clearance = constraint.GetValue().Min();
|
|
||||||
|
|
||||||
if( constraint.GetSeverity() != RPT_SEVERITY_IGNORE && clearance > 0 )
|
int64_t dist_sq = 0;
|
||||||
{
|
VECTOR2I other_pt;
|
||||||
std::map<VECTOR2I, int> conflictPoints;
|
refSegment.NearestPoints( testSegment, pt, other_pt, dist_sq );
|
||||||
|
actual = std::floor( std::sqrt( dist_sq ) + 0.5 );
|
||||||
|
|
||||||
std::vector<SEG>& refSegments = poly_segments[zoneA_idx][layer];
|
if( actual < clearance )
|
||||||
std::vector<SEG>& testSegments = poly_segments[zoneB_idx][layer];
|
|
||||||
|
|
||||||
// Iterate through all the segments in zoneA
|
|
||||||
for( SEG& refSegment : refSegments )
|
|
||||||
{
|
{
|
||||||
int ax1 = refSegment.A.x;
|
done.fetch_add( 1 );
|
||||||
int ay1 = refSegment.A.y;
|
reportZoneZoneViolation( zoneA, zoneB, pt, actual, constraint, layer );
|
||||||
int ax2 = refSegment.B.x;
|
return;
|
||||||
int ay2 = refSegment.B.y;
|
|
||||||
|
|
||||||
// Iterate through all the segments in zoneB
|
|
||||||
for( SEG& testSegment : testSegments )
|
|
||||||
{
|
|
||||||
// Build test segment
|
|
||||||
int bx1 = testSegment.A.x;
|
|
||||||
int by1 = testSegment.A.y;
|
|
||||||
int bx2 = testSegment.B.x;
|
|
||||||
int by2 = testSegment.B.y;
|
|
||||||
|
|
||||||
// We have ensured that the 'A' segment starts before the 'B' segment, so if the
|
|
||||||
// 'A' segment ends before the 'B' segment starts, we can skip to the next 'A'
|
|
||||||
if( ax2 < bx1 )
|
|
||||||
break;
|
|
||||||
|
|
||||||
int64_t dist_sq = 0;
|
|
||||||
VECTOR2I other_pt;
|
|
||||||
refSegment.NearestPoints( testSegment, pt, other_pt, dist_sq );
|
|
||||||
actual = std::floor( std::sqrt( dist_sq ) + 0.5 );
|
|
||||||
|
|
||||||
if( actual < clearance )
|
|
||||||
{
|
|
||||||
done.fetch_add( 1 );
|
|
||||||
return std::make_tuple( zoneA_idx, zoneB_idx, pt, actual, constraint, layer );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
done.fetch_add( 1 );
|
done.fetch_add( 1 );
|
||||||
return std::make_tuple( -1, -1, VECTOR2I(), 0, DRC_CONSTRAINT(), F_Cu );
|
};
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu, m_board->GetCopperLayerCount() ) )
|
for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu, m_board->GetCopperLayerCount() ) )
|
||||||
@ -1312,8 +1323,6 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<int, int>> zonePairs;
|
|
||||||
|
|
||||||
for( size_t ia = 0; ia < m_board->m_DRCCopperZones.size(); ia++ )
|
for( size_t ia = 0; ia < m_board->m_DRCCopperZones.size(); ia++ )
|
||||||
{
|
{
|
||||||
ZONE* zoneA = m_board->m_DRCCopperZones[ia];
|
ZONE* zoneA = m_board->m_DRCCopperZones[ia];
|
||||||
@ -1356,75 +1365,24 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||||||
if( !polyA->BBoxFromCaches().Intersects( polyB->BBoxFromCaches() ) )
|
if( !polyA->BBoxFromCaches().Intersects( polyB->BBoxFromCaches() ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
futures.push_back( tp.submit( checkZones, ia, ia2, sameNet, layer ) );
|
count++;
|
||||||
|
tp.push_task( checkZones, ia, ia2, sameNet, layer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t count = futures.size();
|
while( true )
|
||||||
|
|
||||||
for( std::future<REPORT_DATA>& task : futures )
|
|
||||||
{
|
{
|
||||||
if( !task.valid() )
|
reportProgress( done, count );
|
||||||
continue;
|
|
||||||
|
|
||||||
std::future_status result;
|
if( m_drcEngine->IsCancelled() )
|
||||||
|
break;
|
||||||
|
|
||||||
while( true )
|
if( tp.wait_for_tasks_duration( std::chrono::milliseconds( 250 ) ) )
|
||||||
{
|
break;
|
||||||
result = task.wait_for( std::chrono::milliseconds( 250 ) );
|
|
||||||
|
|
||||||
reportProgress( done, count );
|
|
||||||
|
|
||||||
if( m_drcEngine->IsCancelled() )
|
|
||||||
break;
|
|
||||||
|
|
||||||
if( result == std::future_status::ready )
|
|
||||||
{
|
|
||||||
REPORT_DATA data = task.get();
|
|
||||||
int zoneA_idx = std::get<0>( data );
|
|
||||||
int zoneB_idx = std::get<1>( data );
|
|
||||||
VECTOR2I pt = std::get<2>( data );
|
|
||||||
int actual = std::get<3>( data );
|
|
||||||
DRC_CONSTRAINT constraint = std::get<4>( data );
|
|
||||||
PCB_LAYER_ID layer = std::get<5>( data );
|
|
||||||
|
|
||||||
if( zoneA_idx >= 0 )
|
|
||||||
{
|
|
||||||
ZONE* zoneA = m_board->m_DRCCopperZones[zoneA_idx];
|
|
||||||
ZONE* zoneB = m_board->m_DRCCopperZones[zoneB_idx];
|
|
||||||
|
|
||||||
std::shared_ptr<DRC_ITEM> drce;
|
|
||||||
|
|
||||||
if( constraint.IsNull() )
|
|
||||||
{
|
|
||||||
drce = DRC_ITEM::Create( DRCE_ZONES_INTERSECT );
|
|
||||||
wxString msg = _( "(intersecting zones must have distinct priorities)" );
|
|
||||||
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + msg );
|
|
||||||
drce->SetItems( zoneA, zoneB );
|
|
||||||
reportViolation( drce, pt, layer );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
drce = DRC_ITEM::Create( DRCE_CLEARANCE );
|
|
||||||
wxString msg = formatMsg( _( "(%s clearance %s; actual %s)" ),
|
|
||||||
constraint.GetName(),
|
|
||||||
constraint.GetValue().Min(),
|
|
||||||
std::max( actual, 0 ) );
|
|
||||||
|
|
||||||
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + msg );
|
|
||||||
drce->SetItems( zoneA, zoneB );
|
|
||||||
drce->SetViolatingRule( constraint.GetParentRule() );
|
|
||||||
ReportAndShowPathCuToCu( drce, pt, layer, zoneA, zoneB, layer, actual );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
@ -137,7 +137,7 @@ int DRC_TEST_PROVIDER_CREEPAGE::testCreepage( CREEPAGE_GRAPH& aGraph, int aNetCo
|
|||||||
std::shared_ptr<GRAPH_NODE> NetB = aGraph.AddNetElements( aNetCodeB, aLayer, creepageValue );
|
std::shared_ptr<GRAPH_NODE> NetB = aGraph.AddNetElements( aNetCodeB, aLayer, creepageValue );
|
||||||
|
|
||||||
|
|
||||||
aGraph.GeneratePaths( creepageValue, aLayer, false );
|
aGraph.GeneratePaths( creepageValue, aLayer );
|
||||||
|
|
||||||
std::vector<std::shared_ptr<GRAPH_NODE>> temp_nodes;
|
std::vector<std::shared_ptr<GRAPH_NODE>> temp_nodes;
|
||||||
|
|
||||||
@ -347,7 +347,7 @@ int DRC_TEST_PROVIDER_CREEPAGE::testCreepage()
|
|||||||
graph.RemoveDuplicatedShapes();
|
graph.RemoveDuplicatedShapes();
|
||||||
graph.TransformCreepShapesToNodes( graph.m_shapeCollection );
|
graph.TransformCreepShapesToNodes( graph.m_shapeCollection );
|
||||||
|
|
||||||
graph.GeneratePaths( maxConstraint, Edge_Cuts, false );
|
graph.GeneratePaths( maxConstraint, Edge_Cuts );
|
||||||
|
|
||||||
int beNodeSize = graph.m_nodes.size();
|
int beNodeSize = graph.m_nodes.size();
|
||||||
int beConnectionsSize = graph.m_connections.size();
|
int beConnectionsSize = graph.m_connections.size();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user