Don't conclude we're unconnected if only connected to isolated island.

Also adds the layer name to the "thermal connection incomplete" DRC
error message.

Also improves zone layer description to not say "X and 1 more" (which
takes as much room as saying "X and Y").

Fixes https://gitlab.com/kicad/code/kicad/-/issues/15279
This commit is contained in:
Jeff Young 2023-08-03 15:03:04 +01:00
parent 457e58d0d5
commit 9e019a1ad1
2 changed files with 65 additions and 32 deletions

View File

@ -79,6 +79,7 @@ void DRC_TEST_PROVIDER_ZONE_CONNECTIONS::testZoneLayer( ZONE* aZone, PCB_LAYER_I
BOARD_DESIGN_SETTINGS& bds = board->GetDesignSettings();
std::shared_ptr<CONNECTIVITY_DATA> connectivity = board->GetConnectivity();
DRC_CONSTRAINT constraint;
wxString msg;
const std::shared_ptr<SHAPE_POLY_SET>& zoneFill = aZone->GetFilledPolysList( aLayer );
ISOLATED_ISLANDS isolatedIslands;
@ -140,25 +141,28 @@ void DRC_TEST_PROVIDER_ZONE_CONNECTIONS::testZoneLayer( ZONE* aZone, PCB_LAYER_I
SHAPE_LINE_CHAIN& padOutline = padPoly.Outline( 0 );
BOX2I padBBox( item_bbox );
std::vector<SHAPE_LINE_CHAIN::INTERSECTION> intersections;
int spokes = 0;
int ignoredSpokes = 0;
for( int jj = 0; jj < zoneFill->OutlineCount(); ++jj )
{
std::vector<SHAPE_LINE_CHAIN::INTERSECTION> intersections;
zoneFill->Outline( jj ).Intersect( padOutline, intersections, true, &padBBox );
// If we connect to an island that only connects to a single item then we *are*
// that item. Thermal spokes to this (otherwise isolated) island don't provide
// electrical connectivity to anything, so we don't count them.
if( alg::contains( isolatedIslands.m_SingleConnectionOutlines, jj ) )
continue;
zoneFill->Outline( jj ).Intersect( padOutline, intersections, true, &padBBox );
ignoredSpokes += (int) intersections.size() / 2;
else
spokes += (int) intersections.size() / 2;
}
int spokes = intersections.size() / 2;
if( spokes <= 0 ) // Not connected at all
if( spokes == 0 && ignoredSpokes == 0 ) // Not connected at all
continue;
if( spokes >= minCount ) // We already have enough
if( spokes >= minCount ) // We already have enough
continue;
//
@ -186,7 +190,8 @@ void DRC_TEST_PROVIDER_ZONE_CONNECTIONS::testZoneLayer( ZONE* aZone, PCB_LAYER_I
if( spokes < minCount )
{
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_STARVED_THERMAL );
wxString msg = wxString::Format( _( "(%s min spoke count %d; actual %d)" ),
wxString msg = wxString::Format( _( "(layer %s; %s min spoke count %d; actual %d)" ),
board->GetLayerName( aLayer ),
constraint.GetName(),
minCount,
spokes );

View File

@ -600,19 +600,33 @@ void ZONE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>&
aList.emplace_back( _( "Status" ), _( "Locked" ) );
}
LSEQ layers = m_layerSet.Seq();
wxString layerDesc;
int count = 0;
for( PCB_LAYER_ID layer : m_layerSet.Seq() )
if( layers.size() == 1 )
{
if( count == 0 )
layerDesc = GetBoard()->GetLayerName( layer );
count++;
layerDesc.Printf( _( "%s" ), GetBoard()->GetLayerName( layers[0] ) );
}
else if (layers.size() == 2 )
{
layerDesc.Printf( _( "%s and %s" ),
GetBoard()->GetLayerName( layers[0] ),
GetBoard()->GetLayerName( layers[1] ) );
}
else if (layers.size() == 3 )
{
layerDesc.Printf( _( "%s, %s and %s" ),
GetBoard()->GetLayerName( layers[0] ),
GetBoard()->GetLayerName( layers[1] ),
GetBoard()->GetLayerName( layers[2] ) );
}
else if( layers.size() > 3 )
{
layerDesc.Printf( _( "%s, %s and %d more" ),
GetBoard()->GetLayerName( layers[0] ),
GetBoard()->GetLayerName( layers[1] ),
layers.size() - 2 );
}
if( count > 1 )
layerDesc.Printf( _( "%s and %d more" ), layerDesc, count - 1 );
aList.emplace_back( _( "Layer" ), layerDesc );
@ -644,7 +658,7 @@ void ZONE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>&
if( !m_FilledPolysList.empty() )
{
count = 0;
int count = 0;
for( std::pair<const PCB_LAYER_ID, std::shared_ptr<SHAPE_POLY_SET>>& ii: m_FilledPolysList )
count += ii.second->TotalVertices();
@ -807,34 +821,48 @@ bool ZONE::AppendCorner( VECTOR2I aPosition, int aHoleIdx, bool aAllowDuplicatio
wxString ZONE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
{
LSEQ layers = m_layerSet.Seq();
wxString layerDesc;
int count = 0;
for( PCB_LAYER_ID layer : m_layerSet.Seq() )
if( layers.size() == 1 )
{
if( count == 0 )
layerDesc = GetBoard()->GetLayerName( layer );
count++;
layerDesc.Printf( _( "on %s" ), GetBoard()->GetLayerName( layers[0] ) );
}
else if (layers.size() == 2 )
{
layerDesc.Printf( _( "on %s and %s" ),
GetBoard()->GetLayerName( layers[0] ),
GetBoard()->GetLayerName( layers[1] ) );
}
else if (layers.size() == 3 )
{
layerDesc.Printf( _( "on %s, %s and %s" ),
GetBoard()->GetLayerName( layers[0] ),
GetBoard()->GetLayerName( layers[1] ),
GetBoard()->GetLayerName( layers[2] ) );
}
else if( layers.size() > 3 )
{
layerDesc.Printf( _( "on %s, %s and %d more" ),
GetBoard()->GetLayerName( layers[0] ),
GetBoard()->GetLayerName( layers[1] ),
layers.size() - 2 );
}
if( count > 1 )
layerDesc.Printf( _( "%s and %d more" ), layerDesc, count - 1 );
// Check whether the selected contour is a hole (contour index > 0)
if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
{
if( GetIsRuleArea() )
return wxString::Format( _( "Rule Area Cutout on %s" ), layerDesc );
return wxString::Format( _( "Rule Area Cutout %s" ), layerDesc );
else
return wxString::Format( _( "Zone Cutout on %s" ), layerDesc );
return wxString::Format( _( "Zone Cutout %s" ), layerDesc );
}
else
{
if( GetIsRuleArea() )
return wxString::Format( _( "Rule Area on %s" ), layerDesc );
return wxString::Format( _( "Rule Area %s" ), layerDesc );
else
return wxString::Format( _( "Zone %s on %s" ), GetNetnameMsg(), layerDesc );
return wxString::Format( _( "Zone %s %s" ), GetNetnameMsg(), layerDesc );
}
}